Esempio n. 1
0
def inverse(bmat):
    '''
    Inverse of a linear combination of Hs norms. We very strictly 
    enforce the form of sum_j alpha_j H^{s_j}
    '''
    if isinstance(bmat, InterpolationMatrix):
        return bmat**-1

    if isinstance(bmat, block_utils.VectorizedOperator):
        return block_utils.VectorizedOperator(inverse(bmat.bmat), bmat.W)

    # Does it satisfy the definittion
    assert is_well_defined(bmat)
    # Try to see if sombody computes the eigenvalues
    lmbda, U = extract_attributes(bmat, ('lmbda', 'U'))
    # Do it your self
    if U is None or lmbda is None:
        A, M = extract_attributes(bmat, ('A', 'M'))
        lmbda, U = eigh(A.array(), M.array())

    diagonal = np.zeros_like(lmbda)
    for alpha, s in collect(bmat):
        diagonal[:] += alpha * (lmbda**s)
    # Invert
    diagonal[:] = 1. / diagonal

    array = U.dot(np.diag(diagonal).dot(U.T))

    return numpy_to_petsc(array)
Esempio n. 2
0
def inverse(bmat):
    '''
    Inverse of a linear combination of Hs norms. We very strictly 
    enforce the form of sum_j alpha_j H^{s_j}
    '''
    if isinstance(bmat, InterpolationMatrix):
        return bmat**-1

    if isinstance(bmat, block_utils.VectorizedOperator):
        return block_utils.VectorizedOperator(inverse(bmat.bmat), bmat.W)
    
    # Does it satisfy the definittion
    assert is_well_defined(bmat)
    # Try to see if sombody computes the eigenvalues
    lmbda, U = extract_attributes(bmat, ('lmbda', 'U'))
    # Do it your self
    if U is None or lmbda is None:
        A, M = extract_attributes(bmat, ('A', 'M'))
        lmbda, U = eigh(A.array(), M.array())

    diagonal = np.zeros_like(lmbda)
    for alpha, s in collect(bmat):
        diagonal[:] += alpha*(lmbda**s)
    # Invert
    diagonal[:] = 1./diagonal
    
    array = U.dot(np.diag(diagonal).dot(U.T))

    return numpy_to_petsc(array)
Esempio n. 3
0
def as_block(monolithic, blocks):
    '''Turn monolithic operator into block-structured one with indices specified in blocks'''
    comm = mpi_comm_world()

    # We want list of PETSc.IS-es
    elm_type, = element_types(blocks)
    if elm_type is FunctionSpace:
        offsets = np.cumsum(np.r_[0, [Wi.dim() for Wi in blocks]])

        idx = []
        for first, last in zip(offsets[:-1], offsets[1:]):
            idx.append(PETSc.IS().createStride(last - first, first, 1))
        return as_block(monolithic, idx)

    elif elm_type in (list, np.ndarray):
        return as_block(monolithic, [
            PETSc.IS().createGeneral(np.asarray(block, dtype='int32'))
            for block in blocks
        ])

    assert elm_type is PETSc.IS

    # Break up Vector to block-vec
    if isinstance(monolithic, (GenericVector, Vector)):
        return as_block(as_backend_type(monolithic).vec(), blocks)

    if isinstance(monolithic, (GenericMatrix, Matrix)):
        return as_block(as_backend_type(monolithic).mat(), blocks)

    if isinstance(monolithic, PETSc.Vec):
        b = [
            PETSc.Vec().createWithArray(monolithic.getValues(block), comm=comm)
            for block in blocks
        ]
        for bi in b:
            bi.assemblyBegin()
            bi.assemblyEnd()
        return block_vec(list(map(PETScVector, b)))

    # Otherwise we have a Matrix
    try:
        monolithic.getSubMatrix
        A = [[
            PETScMatrix(monolithic.getSubMatrix(block_row, block_col))
            for block_col in blocks
        ] for block_row in blocks]
    # NOTE: 3.8+ does not ahve getSubMatrix, there is getLocalSubMatrix
    # but cannot get that to work - petsc error 73. So for now everything
    # is done with scipy
    except AttributeError:
        monolithic = csr_matrix(monolithic.getValuesCSR()[::-1],
                                shape=monolithic.size)

        A = [[
            numpy_to_petsc(monolithic[block_row.array, :][:, block_col.array])
            for block_col in blocks
        ] for block_row in blocks]
    # Done
    return block_mat(A)
Esempio n. 4
0
def uniform_extension_matrix(V, EV):
    '''
    Map vector of coeficients of V(over 1d domain) to vector of coefficients of 
    EV(over 2d domain). The spaces need to use the same element type.
    '''
    gdim = V.mesh().geometry().dim()
    assert gdim == EV.mesh().geometry().dim()
    
    # For Vector and Tensor elements more than 1 degree of freedom is 
    # associated with the same geometric point. It is therefore cheaper
    # to compute the mapping based only on the scalar/one subspace considerations.
    is_tensor_elm = isinstance(V.ufl_element(), (df.VectorElement, df.TensorElement))
    # Base on scalar
    if is_tensor_elm:
        V_dofs_x = V.sub(0).collapse().tabulate_dof_coordinates().reshape((-1, gdim))
        EV_dofs_x = EV.sub(0).collapse().tabulate_dof_coordinates().reshape((-1, gdim))
    # Otherwise 'scalar', (Hdiv element belong here as well)
    else:
        V_dofs_x = V.tabulate_dof_coordinates().reshape((V.dim(), gdim))
        EV_dofs_x = EV.tabulate_dof_coordinates().reshape((EV.dim(), gdim))
        
    # Compute distance from every EV dof(row) to every V dof(column)
    lookup = cdist(EV_dofs_x, V_dofs_x)
    # Make sure the two domains do not intersect
    assert np.linalg.norm(lookup, np.inf) > 0

    # Now get the closest dof to E
    columns = np.argmin(lookup, axis=1)
    # Every scalar can be used used to set all the components
    if is_tensor_elm:
        shift = V.dim()/len(V_dofs_x)
        component_idx = np.arange(shift)
        # shift*dof + components
        columns = (shift*np.array([columns]).T + component_idx).flatten()

    # As csr (1 col per row)
    values = np.ones_like(columns)
    rows = np.arange(EV.dim()+1)

    E = csr_matrix((values, columns, rows), shape=(EV.dim(), V.dim()))

    return numpy_to_petsc(E)
Esempio n. 5
0
def apply_bc(A, b, bcs, diag_val=1.):
    '''
    Apply block boundary conditions to block system A, b    
    '''
    if not any(bcs): return A, b
    
    # Allow for A, b be simple matrices. To proceed we wrap them as
    # block objects
    has_wrapped_A = False
    if not isinstance(A, block_mat):
        A = block_mat([[A]])
        has_wrapped_A = True

    if b is None:
        b = A.create_vec()
    
    if not isinstance(b, block_vec):
        assert has_wrapped_A
        b = block_vec([b])
        bcs = [bcs]

    # block boundary conditions is a list with bcs for each block of A, b
    assert len(A) == len(b) == len(bcs)

    bcs_ = []
    for bc in bcs:
        assert isinstance(bc, (DirichletBC, list))
        if isinstance(bc, DirichletBC):
            bcs_.append([bc])
        else:
            bcs_.append(bc)
    bcs = bcs_

    if not bcs or not any(bcs): return A, b

    # Obtain a monolithic matrix
    AA, bb = map(convert, (A, b))
    # PETSc guys
    AA, bb = as_backend_type(AA).mat(), as_backend_type(bb).vec()

    # We want to make a monotlithic matrix corresponding to function sp ace
    # where the spaces are serialized
    
    # Break apart for block
    offsets = [0]
    for bi in b:
        offsets.append(offsets[-1] + bi.size())

    rows = []
    x_values = []
    # Each bc in the group has dofs numbered only wrt to its space.
    # We're after global numbering
    for shift, bcs_sub in zip(offsets, bcs): 
        for bc in bcs_sub:
            # NOTE: bcs can be a dict or DirichletBC in which case we extract
            # the dict
            if isinstance(bc, DirichletBC): bc = bc.get_boundary_values()
            # Dofs and values for rhs
            rows.extend(shift + np.array(bc.keys(), dtype='int32'))
            x_values.extend(bc.values())
            
    rows = np.hstack(rows)
    x_values = np.array(x_values)

    x = bb.copy()
    x.zeroEntries()
    x.setValues(rows, x_values)

    # Apply to monolithic
    len(rows) and AA.zeroRowsColumns(rows, diag=diag_val, x=x, b=bb)

    blocks = []
    for first, last in zip(offsets[:-1], offsets[1:]):
        blocks.append(PETSc.IS().createStride(last-first, first, 1))

    # Reasamble
    comm = mpi_comm_world()
    b = [PETSc.Vec().createWithArray(bb.getValues(block), comm=comm) for block in blocks]
    for bi in b:
        bi.assemblyBegin()
        bi.assemblyEnd()
    b = block_vec(map(PETScVector, b))

    # PETSc 3.7.x
    try:
        AA.getSubMatrix
        A = [[PETScMatrix(AA.getSubMatrix(block_row, block_col)) for block_col in blocks]
             for block_row in blocks]
    # NOTE: 3.8+ does not ahve getSubMatrix, there is getLocalSubMatrix
    # but cannot get that to work - petsc error 73. So for now everything
    # is done with scipy    
    except AttributeError:
        AA = csr_matrix(AA.getValuesCSR()[::-1], shape=AA.size)

        A = [[numpy_to_petsc(AA[block_row.array, :][:, block_col.array]) for block_col in blocks]
             for block_row in blocks]
    # Block mat
    A = block_mat(A)

    if has_wrapped_A: return A[0][0], b[0]
    
    return A, b