Exemple #1
0
def extend_hierarchy(levels, CF, l, maxp, theta_a, keep):
    """Extend the multigrid hierarchy."""
    def unpack_arg(v):
        if isinstance(v, tuple):
            return v[0], v[1]
        else:
            return v, {}

    A = levels[-1].A

    # Generate the C/F splitting
    fn, kwargs = unpack_arg(CF)
    if fn == 'CR':
        splitting = CR(A, **kwargs)
    else:
        raise ValueError('unknown C/F splitting method (%s)' % CF)

    # rs_C = classical_strength_of_connection(A, theta=0.25)
    # rs_splitting = split.RS(rs_C)
    # rs_P = direct_interpolation(A.copy(), rs_C.copy(), rs_splitting.copy())
    #
    # rs_P_sparsity = rs_P.copy()
    # rs_P_sparsity.data[:] = 1
    #
    # rs_fine = np.where(rs_splitting == 0)[0]
    # rs_coarse = np.where(rs_splitting == 1)[0]
    # rs_A_fc = A[rs_fine][:, rs_coarse]
    # rs_W = rs_P[rs_fine]
    # my_rs_P, my_rs_W = my_direct_interpolation(rs_A_fc, A, rs_W, rs_coarse, rs_fine)
    #
    # my_rs_P_sparsity = my_rs_P.copy()
    # my_rs_P_sparsity.data[:] = 1
    #
    # rs_A_sparsity = A[:, rs_coarse].copy()
    # rs_A_sparsity.data[:] = 1

    # Generate the interpolation matrix that maps from the coarse-grid to the
    # fine-grid
    P = truncation_interpolation(A, splitting, l, maxp, theta_a)
    # P = optimal_interpolation(A, splitting)
    # P = rs_P

    # Generate the restriction matrix that maps from the fine-grid to the
    # coarse-grid
    R = P.T.tocsr()

    # Store relevant information for this level
    if keep:
        levels[-1].splitting = splitting  # C/F splitting

    levels[-1].P = P  # prolongation operator
    levels[-1].R = R  # restriction operator

    levels.append(multilevel_solver.level())

    # Form next level through Galerkin product
    A = R * A * P
    levels[-1].A = A
Exemple #2
0
    def test_cr(self):
        A = self.cases[6]

        # 1d-tests, should be alternating aggregates
        #       (n-1)/2 < = sum <= (n+1)/2.
        # Test auto thetacs and set thetacs values
        for i in range(3, 10):
            A = self.cases[i]
            h_split_auto = CR(A, method='habituated', thetacr=0.7,
                              thetacs='auto')
            assert(h_split_auto.sum() <= (h_split_auto.shape[0]+1)/2)
            assert(h_split_auto.sum() >= (h_split_auto.shape[0]-1)/2)

            c_split_auto = CR(A, method='concurrent', thetacr=0.7,
                              thetacs='auto')
            assert(c_split_auto.sum() <= (c_split_auto.shape[0]+1)/2)
            assert(c_split_auto.sum() >= (c_split_auto.shape[0]-1)/2)

            h_split = CR(A, method='habituated', thetacr=0.7,
                         thetacs=[0.3, 0.5])
            assert(h_split.sum() <= (h_split.shape[0]+1)/2)
            assert(h_split.sum() >= (h_split.shape[0]-1)/2)

            c_split = CR(A, method='concurrent', thetacr=0.7,
                         thetacs=[0.3, 0.5])
            assert(c_split.sum() <= (c_split.shape[0]+1)/2)
            assert(c_split.sum() >= (c_split.shape[0]-1)/2)

        # 2d-tests. CR is a little more picky with parameters and relaxation
        # type in 2d. Can still bound above by (n+1)/2.
        # Need looser lower bound,
        # say (n+1)/4.
        for i in range(10, 15):
            A = self.cases[i]
            h_split_auto = CR(A, method='habituated', thetacr=0.7,
                              thetacs='auto')
            assert(h_split_auto.sum() <= (h_split_auto.shape[0]+1)/2)
            assert(h_split_auto.sum() >= (h_split_auto.shape[0]-1)/4)

            c_split_auto = CR(A, method='concurrent', thetacr=0.7,
                              thetacs='auto')
            assert(c_split_auto.sum() <= (c_split_auto.shape[0]+1)/2)
            assert(c_split_auto.sum() >= (c_split_auto.shape[0]-1)/4)

            h_split = CR(A, method='habituated', thetacr=0.7,
                         thetacs=[0.3, 0.5])
            assert(h_split.sum() <= (h_split.shape[0]+1)/2)
            assert(h_split.sum() >= (h_split.shape[0]-1)/4)

            c_split = CR(A, method='concurrent', thetacr=0.7,
                         thetacs=[0.3, 0.5])
            assert(c_split.sum() <= (c_split.shape[0]+1)/2)
            assert(c_split.sum() >= (c_split.shape[0]-1)/4)
def extend_hierarchy(levels, strength, CF, keep, prolongation_function):
    """Extend the multigrid hierarchy."""

    def unpack_arg(v):
        if isinstance(v, tuple):
            return v[0], v[1]
        else:
            return v, {}

    A = levels[-1].A

    # Compute the strength-of-connection matrix C, where larger
    # C[i,j] denote stronger couplings between i and j.
    fn, kwargs = unpack_arg(strength)
    if fn == 'symmetric':
        C = symmetric_strength_of_connection(A, **kwargs)
    elif fn == 'classical':
        C = classical_strength_of_connection(A, **kwargs)
    elif fn == 'distance':
        C = distance_strength_of_connection(A, **kwargs)
    elif (fn == 'ode') or (fn == 'evolution'):
        C = evolution_strength_of_connection(A, **kwargs)
    elif fn == 'energy_based':
        C = energy_based_strength_of_connection(A, **kwargs)
    elif fn == 'algebraic_distance':
        C = algebraic_distance(A, **kwargs)
    elif fn == 'affinity':
        C = affinity_distance(A, **kwargs)
    elif fn is None:
        C = A
    else:
        raise ValueError('unrecognized strength of connection method: %s' %
                         str(fn))

    # Generate the C/F splitting
    fn, kwargs = unpack_arg(CF)
    if fn == 'RS':
        splitting = split.RS(C, **kwargs)
    elif fn == 'PMIS':
        splitting = split.PMIS(C, **kwargs)
    elif fn == 'PMISc':
        splitting = split.PMISc(C, **kwargs)
    elif fn == 'CLJP':
        splitting = split.CLJP(C, **kwargs)
    elif fn == 'CLJPc':
        splitting = split.CLJPc(C, **kwargs)
    elif fn == 'CR':
        splitting = CR(C, **kwargs)
    else:
        raise ValueError('unknown C/F splitting method (%s)' % CF)

    # Generate the interpolation matrix that maps from the coarse-grid to the
    # fine-grid
    baseline_P = direct_interpolation(A, C, splitting)
    coarse_nodes = np.nonzero(splitting)[0]

    # Create a prolongation matrix with the same coarse-fine splitting and sparsity pattern
    # as the baseline
    P = prolongation_function(A, coarse_nodes, baseline_P, C)

    # Generate the restriction matrix that maps from the fine-grid to the
    # coarse-grid
    R = P.T.tocsr()

    # Store relevant information for this level
    if keep:
        levels[-1].C = C  # strength of connection matrix
        levels[-1].splitting = splitting  # C/F splitting

    levels[-1].P = P  # prolongation operator
    levels[-1].R = R  # restriction operator

    levels.append(multilevel_solver.level())

    # Form next level through Galerkin product
    A = R * A * P
    levels[-1].A = A
Exemple #4
0
def extend_hierarchy(levels, strength, CF, interp, restrict, filter_operator,
                     coarse_grid_P, coarse_grid_R, keep):
    """ helper function for local methods """

    # Filter operator. Need to keep original matrix on fineest level for
    # computing residuals
    if (filter_operator is not None) and (filter_operator[1] != 0):
        if len(levels) == 1:
            A = deepcopy(levels[-1].A)
        else:
            A = levels[-1].A
        filter_matrix_rows(A,
                           filter_operator[1],
                           diagonal=True,
                           lump=filter_operator[0])
    else:
        A = levels[-1].A

    # Check if matrix was filtered to be diagonal --> coarsest grid
    if A.nnz == A.shape[0]:
        return 1

    # Zero initial complexities for strength, splitting and interpolation
    levels[-1].complexity['CF'] = 0.0
    levels[-1].complexity['strength'] = 0.0
    levels[-1].complexity['interpolate'] = 0.0

    # Compute the strength-of-connection matrix C, where larger
    # C[i,j] denote stronger couplings between i and j.
    fn, kwargs = unpack_arg(strength)
    if fn == 'symmetric':
        C = symmetric_strength_of_connection(A, **kwargs)
    elif fn == 'classical':
        C = classical_strength_of_connection(A, **kwargs)
    elif fn == 'distance':
        C = distance_strength_of_connection(A, **kwargs)
    elif (fn == 'ode') or (fn == 'evolution'):
        C = evolution_strength_of_connection(A, **kwargs)
    elif fn == 'energy_based':
        C = energy_based_strength_of_connection(A, **kwargs)
    elif fn == 'algebraic_distance':
        C = algebraic_distance(A, **kwargs)
    elif fn == 'affinity':
        C = affinity_distance(A, **kwargs)
    elif fn is None:
        C = A
    else:
        raise ValueError('unrecognized strength of connection method: %s' %
                         str(fn))
    levels[-1].complexity['strength'] += kwargs['cost'][0] * A.nnz / float(
        A.nnz)

    # Generate the C/F splitting
    fn, kwargs = unpack_arg(CF)
    if fn == 'RS':
        splitting = RS(C, **kwargs)
    elif fn == 'PMIS':
        splitting = PMIS(C, **kwargs)
    elif fn == 'PMISc':
        splitting = PMISc(C, **kwargs)
    elif fn == 'CLJP':
        splitting = CLJP(C, **kwargs)
    elif fn == 'CLJPc':
        splitting = CLJPc(C, **kwargs)
    elif fn == 'CR':
        splitting = CR(C, **kwargs)
    elif fn == 'weighted_matching':
        splitting, soc = weighted_matching(C, **kwargs)
        if soc is not None:
            C = soc
    else:
        raise ValueError('unknown C/F splitting method (%s)' % CF)
    levels[-1].complexity['CF'] += kwargs['cost'][0] * C.nnz / float(A.nnz)
    temp = np.sum(splitting)
    if (temp == len(splitting)) or (temp == 0):
        return 1

    # Generate the interpolation matrix that maps from the coarse-grid to the
    # fine-grid
    r_flag = False
    fn, kwargs = unpack_arg(interp)
    if fn == 'standard':
        P = standard_interpolation(A, C, splitting, **kwargs)
    elif fn == 'distance_two':
        P = distance_two_interpolation(A, C, splitting, **kwargs)
    elif fn == 'direct':
        P = direct_interpolation(A, C, splitting, **kwargs)
    elif fn == 'one_point':
        P = one_point_interpolation(A, C, splitting, **kwargs)
    elif fn == 'inject':
        P = injection_interpolation(A, splitting, **kwargs)
    elif fn == 'neumann':
        P = neumann_ideal_interpolation(A, splitting, **kwargs)
    elif fn == 'scaledAfc':
        P = scaled_Afc_interpolation(A, splitting, **kwargs)
    elif fn == 'air':
        if isspmatrix_bsr(A):
            temp_A = bsr_matrix(A.T)
            P = local_AIR(temp_A, splitting, **kwargs)
            P = bsr_matrix(P.T)
        else:
            temp_A = csr_matrix(A.T)
            P = local_AIR(temp_A, splitting, **kwargs)
            P = csr_matrix(P.T)
    elif fn == 'restrict':
        r_flag = True
    else:
        raise ValueError('unknown interpolation method (%s)' % interp)
    levels[-1].complexity['interpolate'] += kwargs['cost'][0] * A.nnz / float(
        A.nnz)

    # Build restriction operator
    fn, kwargs = unpack_arg(restrict)
    if fn is None:
        R = P.T
    elif fn == 'air':
        R = local_AIR(A, splitting, **kwargs)
    elif fn == 'neumann':
        R = neumann_AIR(A, splitting, **kwargs)
    elif fn == 'one_point':  # Don't need A^T here
        temp_C = C.T.tocsr()
        R = one_point_interpolation(A, temp_C, splitting, **kwargs)
        if isspmatrix_bsr(A):
            R = R.T.tobsr()
        else:
            R = R.T.tocsr()
    elif fn == 'inject':  # Don't need A^T or C^T here
        R = injection_interpolation(A, splitting, **kwargs)
        if isspmatrix_bsr(A):
            R = R.T.tobsr()
        else:
            R = R.T.tocsr()
    elif fn == 'standard':
        if isspmatrix_bsr(A):
            temp_A = A.T.tobsr()
            temp_C = C.T.tobsr()
            R = standard_interpolation(temp_A, temp_C, splitting, **kwargs)
            R = R.T.tobsr()
        else:
            temp_A = A.T.tocsr()
            temp_C = C.T.tocsr()
            R = standard_interpolation(temp_A, temp_C, splitting, **kwargs)
            R = R.T.tocsr()
    elif fn == 'distance_two':
        if isspmatrix_bsr(A):
            temp_A = A.T.tobsr()
            temp_C = C.T.tobsr()
            R = distance_two_interpolation(temp_A, temp_C, splitting, **kwargs)
            R = R.T.tobsr()
        else:
            temp_A = A.T.tocsr()
            temp_C = C.T.tocsr()
            R = distance_two_interpolation(temp_A, temp_C, splitting, **kwargs)
            R = R.T.tocsr()
    elif fn == 'direct':
        if isspmatrix_bsr(A):
            temp_A = A.T.tobsr()
            temp_C = C.T.tobsr()
            R = direct_interpolation(temp_A, temp_C, splitting, **kwargs)
            R = R.T.tobsr()
        else:
            temp_A = A.T.tocsr()
            temp_C = C.T.tocsr()
            R = direct_interpolation(temp_A, temp_C, splitting, **kwargs)
            R = R.T.tocsr()
    else:
        raise ValueError('unknown restriction method (%s)' % restrict)

    # If set P = R^T
    if r_flag:
        P = R.T

    # Optional different interpolation for RAP
    fn, kwargs = unpack_arg(coarse_grid_P)
    if fn == 'standard':
        P_temp = standard_interpolation(A, C, splitting, **kwargs)
    elif fn == 'distance_two':
        P_temp = distance_two_interpolation(A, C, splitting, **kwargs)
    elif fn == 'direct':
        P_temp = direct_interpolation(A, C, splitting, **kwargs)
    elif fn == 'one_point':
        P_temp = one_point_interpolation(A, C, splitting, **kwargs)
    elif fn == 'inject':
        P_temp = injection_interpolation(A, splitting, **kwargs)
    elif fn == 'neumann':
        P_temp = neumann_ideal_interpolation(A, splitting, **kwargs)
    elif fn == 'air':
        if isspmatrix_bsr(A):
            temp_A = bsr_matrix(A.T)
            P_temp = local_AIR(temp_A, splitting, **kwargs)
            P_temp = bsr_matrix(P_temp.T)
        else:
            temp_A = csr_matrix(A.T)
            P_temp = local_AIR(temp_A, splitting, **kwargs)
            P_temp = csr_matrix(P_temp.T)
    else:
        P_temp = P

    # Optional different restriction for RAP
    fn, kwargs = unpack_arg(coarse_grid_R)
    if fn == 'air':
        R_temp = local_AIR(A, splitting, **kwargs)
    elif fn == 'neumann':
        R_temp = neumann_AIR(A, splitting, **kwargs)
    elif fn == 'one_point':  # Don't need A^T here
        temp_C = C.T.tocsr()
        R_temp = one_point_interpolation(A, temp_C, splitting, **kwargs)
        if isspmatrix_bsr(A):
            R_temp = R_temp.T.tobsr()
        else:
            R_temp = R_temp.T.tocsr()
    elif fn == 'inject':  # Don't need A^T or C^T here
        R_temp = injection_interpolation(A, splitting, **kwargs)
        if isspmatrix_bsr(A):
            R_temp = R_temp.T.tobsr()
        else:
            R_temp = R_temp.T.tocsr()
    elif fn == 'standard':
        if isspmatrix_bsr(A):
            temp_A = A.T.tobsr()
            temp_C = C.T.tobsr()
            R_temp = standard_interpolation(temp_A, temp_C, splitting,
                                            **kwargs)
            R_temp = R_temp.T.tobsr()
        else:
            temp_A = A.T.tocsr()
            temp_C = C.T.tocsr()
            R_temp = standard_interpolation(temp_A, temp_C, splitting,
                                            **kwargs)
            R_temp = R_temp.T.tocsr()
    elif fn == 'distance_two':
        if isspmatrix_bsr(A):
            temp_A = A.T.tobsr()
            temp_C = C.T.tobsr()
            R_temp = distance_two_interpolation(temp_A, temp_C, splitting,
                                                **kwargs)
            R_temp = R_temp.T.tobsr()
        else:
            temp_A = A.T.tocsr()
            temp_C = C.T.tocsr()
            R_temp = distance_two_interpolation(temp_A, temp_C, splitting,
                                                **kwargs)
            R_temp = R_temp.T.tocsr()
    elif fn == 'direct':
        if isspmatrix_bsr(A):
            temp_A = A.T.tobsr()
            temp_C = C.T.tobsr()
            R_temp = direct_interpolation(temp_A, temp_C, splitting, **kwargs)
            R_temp = R_temp.T.tobsr()
        else:
            temp_A = A.T.tocsr()
            temp_C = C.T.tocsr()
            R_temp = direct_interpolation(temp_A, temp_C, splitting, **kwargs)
            R_temp = R_temp.T.tocsr()
    else:
        R_temp = R

    # Store relevant information for this level
    if keep:
        levels[-1].C = C  # strength of connection matrix

    levels[-1].P = P  # prolongation operator
    levels[-1].R = R  # restriction operator
    levels[-1].splitting = splitting  # C/F splitting

    # Form coarse grid operator, get complexity
    #levels[-1].complexity['RAP'] = mat_mat_complexity(R_temp,A) / float(A.nnz)
    #RA = R_temp * A
    #levels[-1].complexity['RAP'] += mat_mat_complexity(RA,P_temp) / float(A.nnz)
    #A = RA * P_temp

    # RL: RAP = R*(A*P)
    levels[-1].complexity['RAP'] = mat_mat_complexity(A, P_temp) / float(A.nnz)
    AP = A * P_temp
    levels[-1].complexity['RAP'] += mat_mat_complexity(R_temp, AP) / float(
        A.nnz)
    A = R_temp * AP

    # Make sure coarse-grid operator is in correct sparse format
    if (isspmatrix_csr(P) and (not isspmatrix_csr(A))):
        A = A.tocsr()
    elif (isspmatrix_bsr(P) and (not isspmatrix_bsr(A))):
        A = A.tobsr()

    A.eliminate_zeros()
    levels.append(multilevel_solver.level())
    levels[-1].A = A
    return 0
Exemple #5
0
    def test_cr(self):
        A = self.cases[6]
        splitting = CR(A)

        # 1d-tests, should be alternating aggregates 
        #       (n-1)/2 < = sum <= (n+1)/2.
        # Test auto thetacs and set thetacs values
        for i in range(3,10):
            A = self.cases[i]
            h_split_auto = CR(A, method='habituated', thetacr=0.7, thetacs='auto')
            assert(h_split_auto.sum() <= (h_split_auto.shape[0]+1)/2 )
            assert(h_split_auto.sum() >= (h_split_auto.shape[0]-1)/2 )
            c_split_auto = CR(A, method='concurrent', thetacr=0.7, thetacs='auto')
            assert(c_split_auto.sum() <= (c_split_auto.shape[0]+1)/2 )
            assert(c_split_auto.sum() >= (c_split_auto.shape[0]-1)/2 )
            h_split = CR(A, method='habituated', thetacr=0.7, thetacs=[0.3,0.5])
            assert(h_split.sum() <= (h_split.shape[0]+1)/2 )
            assert(h_split.sum() >= (h_split.shape[0]-1)/2 )
            c_split = CR(A, method='concurrent', thetacr=0.7, thetacs=[0.3,0.5])
            assert(c_split.sum() <= (c_split.shape[0]+1)/2 )
            assert(c_split.sum() >= (c_split.shape[0]-1)/2 )

        # 2d-tests. CR is a little more picky with parameters and relaxation
        # type in 2d. Can still bound above by (n+1)/2. Need looser lower bound,
        # say (n+1)/4.
        for i in range(10,15):
            A = self.cases[i]
            h_split_auto = CR(A, method='habituated', thetacr=0.7, thetacs='auto')
            assert(h_split_auto.sum() <= (h_split_auto.shape[0]+1)/2 )
            assert(h_split_auto.sum() >= (h_split_auto.shape[0]-1)/4 )
            c_split_auto = CR(A, method='concurrent', thetacr=0.7, thetacs='auto')
            assert(c_split_auto.sum() <= (c_split_auto.shape[0]+1)/2 )
            assert(c_split_auto.sum() >= (c_split_auto.shape[0]-1)/4 )
            h_split = CR(A, method='habituated', thetacr=0.7, thetacs=[0.3,0.5])
            assert(h_split.sum() <= (h_split.shape[0]+1)/2 )
            assert(h_split.sum() >= (h_split.shape[0]-1)/4 )
            c_split = CR(A, method='concurrent', thetacr=0.7, thetacs=[0.3,0.5])
            assert(c_split.sum() <= (c_split.shape[0]+1)/2 )
            assert(c_split.sum() >= (c_split.shape[0]-1)/4 )
Exemple #6
0
 def test_cr(self):
     A = self.cases[6]
     splitting = CR(A)
     assert (splitting.sum() < splitting.shape[0])
Exemple #7
0
 def test_cr(self):
     A = self.cases[6]
     splitting = CR(A)
     assert(splitting.sum() < splitting.shape[0])