Ejemplo n.º 1
0
def ToHypreParVec(vec):
    import mfem.par as mfem
    from mpi4py import MPI

    if mfem.sizeof_HYPRE_Int() == 4:
        dtype = 'int32'
    else:
        dtype = 'int64'

    comm = MPI.COMM_WORLD
    num_proc = MPI.COMM_WORLD.size
    myid = MPI.COMM_WORLD.rank

    vec = vec.flatten()
    ml = vec.shape[0]

    # collect col array to determin partitioning
    m_array = comm.allgather(ml)
    cols = [0] + list(np.cumsum(m_array))
    glob_size = cols[-1]
    col_starts = np.array([cols[myid], cols[myid + 1], glob_size], dtype=dtype)

    vec = vec.astype('float', copy=False)
    v = mfem.HypreParVector(MPI.COMM_WORLD, glob_size, [vec, col_starts])

    return v
Ejemplo n.º 2
0
def ToHypreParCSR(mat,
                  check_partitioning=False,
                  verbose=False,
                  col_starts=None,
                  assert_non_square_no_col_starts=True):
    '''
    convert scipy sparse matrix to hypre

    vertically stack csr matrix to generte HYPRE Par CSR

    Note:
    row partitioning is inferred from distribution of input matrix.
    column patitioning needs to be specified col_starts.

    If col_starts is not given, column partitioning is chosen 
    to be the same as row partitioning. This works if matrix is square (M = N).

    For an aribtrary rectangular matrix, the column partitioning can be
    different from the row partitioning. For example, MFEM mixedbilinearfomr 
    uses different partitiong rules for row and column.

    ToDo: change default assert_non_square_no_col_starts to False
    
    '''

    from mpi4py import MPI
    import mfem.par as mfem

    if mfem.sizeof_HYPRE_Int() == 4:
        dtype = 'int32'
    else:
        dtype = 'int64'

    comm = MPI.COMM_WORLD
    num_proc = MPI.COMM_WORLD.size
    myid = MPI.COMM_WORLD.rank

    def verbose_message(m, n, nrows, i, j, data, row_starts, col_starts):
        for k in range(num_proc):
            MPI.COMM_WORLD.Barrier()
            if myid == k:
                print 'MyID : ', k
                print(m,
                      n), nrows, len(data), i, j, data, row_starts, col_starts
                print 'NNZ', np.sum(data != 0.0)
        MPI.COMM_WORLD.Barrier()

    from scipy.sparse import csr_matrix

    if isinstance(mat, csr_matrix):
        mat = mat.astype('float')
        ml, nl = mat.shape
        n_array = comm.allgather(nl)
    else:
        raise ValueError("Import Matrix Format should be csr or None")

    # collect row array to determin the size of matrix
    m_array = comm.allgather(ml)

    rows = [0] + list(np.cumsum(m_array))
    m = rows[-1]
    row_starts = np.array([rows[myid], rows[myid + 1], m], dtype=dtype)

    n = nl
    nrows = ml

    i = mat.indptr.astype(dtype)
    j = mat.indices.astype(dtype)
    data = mat.data

    if col_starts is None and m != nl:
        col_starts = get_assumed_patitioning(nl)
        if assert_non_square_no_col_starts:
            assert False, "col_starts must be specified for non diagonal array"
    if col_starts is None:
        col_starts = row_starts.copy()
        col_starts[-1] = n
        if col_starts[0] > n:
            col_starts[0] = n
        if col_starts[1] > n:
            col_starts[1] = n
        col_starts[2] = n
    else:
        # make sure that dtype is right....
        col_starts = np.array(col_starts, dtype=dtype)
    if check_partitioning:
        ch = get_assumed_patitioning(m)
        if (row_starts[0] != ch[0] or row_starts[1] != ch[1]
                or nrows != ch[2]):
            for k in range(num_proc):
                MPI.COMM_WORLD.Barrier()
                if myid == k:
                    print 'MyID : ', k
                    print ch, nrows, row_starts, col_starts
                    print 'NNZ', np.sum(data != 0.0)
            MPI.COMM_WORLD.Barrier()
            raise ValueError("partitioning of input matrix is not correct")
    if verbose:
        verbose_message(m, n, nrows, i, j, data, row_starts, col_starts)

    #
    # it seems row_starts and col_starts are both to determin
    # which part is treated diagnal element.
    #
    if (m == n and row_starts[0] == col_starts[0]
            and row_starts[1] == col_starts[1]):
        # this will cause hypre_CSRMatrixReorder call.
        M = mfem.HypreParMatrix(MPI.COMM_WORLD, nrows, m, n,
                                [i, j, data, col_starts])
        M.CopyRowStarts()
        M.CopyColStarts()
    else:
        M = mfem.HypreParMatrix(MPI.COMM_WORLD, nrows, m, n,
                                [i, j, data, row_starts, col_starts])
        M.CopyRowStarts()
        M.CopyColStarts()
    return M