(T, P_I, I_F)
return T
Scale T with a block diagonal matrix.

    Helper function that scales T with a right multiplication by a block
    diagonal inverse, so that T is the identity at C-node rows.

    Parameters
    ----------
    T : {bsr_matrix}
        Tentative prolongator, with square blocks in the BSR data structure,
        and a non-overlapping block-diagonal structure
    P_I : {bsr_matrix}
        Interpolation operator that carries out only simple injection from the
        coarse grid to fine grid Cpts nodes
    I_F : {bsr_matrix}
        Identity operator on Fpts, i.e., the action of this matrix zeros
        out entries in a vector at all Cpts, leaving Fpts untouched

    Returns
    -------
    T : {bsr_matrix}
        Tentative prolongator scaled to be identity at C-pt nodes

    Examples
    --------
    >>> from scipy.sparse import csr_matrix, bsr_matrix
    >>> import numpy as np
    >>> from pyamg.util.utils import scale_T
    >>> T = np.array([[ 1.0,  0.,   0. ],
    ...               [ 0.5,  0.,   0. ],
    ...               [ 0. ,  1.,   0. ],
    ...               [ 0. ,  0.5,  0. ],
    ...               [ 0. ,  0.,   1. ],
    ...               [ 0. ,  0.,   0.25 ]])
    >>> P_I = np.array([[ 0.,  0.,   0. ],
    ...                 [ 1.,  0.,   0. ],
    ...                 [ 0.,  1.,   0. ],
    ...                 [ 0.,  0.,   0. ],
    ...                 [ 0.,  0.,   0. ],
    ...                 [ 0.,  0.,   1. ]])
    >>> I_F = np.array([[ 1.,  0.,  0.,  0.,  0.,  0.],
    ...                 [ 0.,  0.,  0.,  0.,  0.,  0.],
    ...                 [ 0.,  0.,  0.,  0.,  0.,  0.],
    ...                 [ 0.,  0.,  0.,  1.,  0.,  0.],
    ...                 [ 0.,  0.,  0.,  0.,  1.,  0.],
    ...                 [ 0.,  0.,  0.,  0.,  0.,  0.]])
    >>> scale_T(bsr_matrix(T), bsr_matrix(P_I), bsr_matrix(I_F)).toarray()
    array([[2. , 0. , 0. ],
           [1. , 0. , 0. ],
           [0. , 1. , 0. ],
           [0. , 0.5, 0. ],
           [0. , 0. , 4. ],
           [0. , 0. , 1. ]])

    Notes
    -----
    This routine is primarily used in
    pyamg.aggregation.smooth.energy_prolongation_smoother, where it is used to
    generate a suitable initial guess for the energy-minimization process, when
    root-node style SA is used.  This function, scale_T, takes an existing
    tentative prolongator and ensures that it injects from the coarse-grid to
    fine-grid root-nodes.

    When generating initial guesses for root-node style prolongation operators,
    this function is usually called after pyamg.uti.utils.filter_operator

    This function assumes that the eventual coarse-grid nullspace vectors
    equal coarse-grid injection applied to the fine-grid nullspace vectors.
Scale T with a block diagonal matrix.
Scale T with a block diagonal matrix .
def scale_T(T, P_I, I_F):
    """Scale T with a block diagonal matrix.

    Helper function that scales T with a right multiplication by a block
    diagonal inverse, so that T is the identity at C-node rows.

    Parameters
    ----------
    T : {bsr_matrix}
        Tentative prolongator, with square blocks in the BSR data structure,
        and a non-overlapping block-diagonal structure
    P_I : {bsr_matrix}
        Interpolation operator that carries out only simple injection from the
        coarse grid to fine grid Cpts nodes
    I_F : {bsr_matrix}
        Identity operator on Fpts, i.e., the action of this matrix zeros
        out entries in a vector at all Cpts, leaving Fpts untouched

    Returns
    -------
    T : {bsr_matrix}
        Tentative prolongator scaled to be identity at C-pt nodes

    Examples
    --------
    >>> from scipy.sparse import csr_matrix, bsr_matrix
    >>> import numpy as np
    >>> from pyamg.util.utils import scale_T
    >>> T = np.array([[ 1.0,  0.,   0. ],
    ...               [ 0.5,  0.,   0. ],
    ...               [ 0. ,  1.,   0. ],
    ...               [ 0. ,  0.5,  0. ],
    ...               [ 0. ,  0.,   1. ],
    ...               [ 0. ,  0.,   0.25 ]])
    >>> P_I = np.array([[ 0.,  0.,   0. ],
    ...                 [ 1.,  0.,   0. ],
    ...                 [ 0.,  1.,   0. ],
    ...                 [ 0.,  0.,   0. ],
    ...                 [ 0.,  0.,   0. ],
    ...                 [ 0.,  0.,   1. ]])
    >>> I_F = np.array([[ 1.,  0.,  0.,  0.,  0.,  0.],
    ...                 [ 0.,  0.,  0.,  0.,  0.,  0.],
    ...                 [ 0.,  0.,  0.,  0.,  0.,  0.],
    ...                 [ 0.,  0.,  0.,  1.,  0.,  0.],
    ...                 [ 0.,  0.,  0.,  0.,  1.,  0.],
    ...                 [ 0.,  0.,  0.,  0.,  0.,  0.]])
    >>> scale_T(bsr_matrix(T), bsr_matrix(P_I), bsr_matrix(I_F)).toarray()
    array([[2. , 0. , 0. ],
           [1. , 0. , 0. ],
           [0. , 1. , 0. ],
           [0. , 0.5, 0. ],
           [0. , 0. , 4. ],
           [0. , 0. , 1. ]])

    Notes
    -----
    This routine is primarily used in
    pyamg.aggregation.smooth.energy_prolongation_smoother, where it is used to
    generate a suitable initial guess for the energy-minimization process, when
    root-node style SA is used.  This function, scale_T, takes an existing
    tentative prolongator and ensures that it injects from the coarse-grid to
    fine-grid root-nodes.

    When generating initial guesses for root-node style prolongation operators,
    this function is usually called after pyamg.uti.utils.filter_operator

    This function assumes that the eventual coarse-grid nullspace vectors
    equal coarse-grid injection applied to the fine-grid nullspace vectors.

    """
    if not isspmatrix_bsr(T):
        raise TypeError('Expected BSR matrix T')

    if T.blocksize[0] != T.blocksize[1]:
        raise TypeError('Expected BSR matrix T with square blocks')

    if not isspmatrix_bsr(P_I):
        raise TypeError('Expected BSR matrix P_I')

    if P_I.blocksize[0] != P_I.blocksize[1]:
        raise TypeError('Expected BSR matrix P_I with square blocks')

    if not isspmatrix_bsr(I_F):
        raise TypeError('Expected BSR matrix I_F')

    if I_F.blocksize[0] != I_F.blocksize[1]:
        raise TypeError('Expected BSR matrix I_F with square blocks')

    if (I_F.blocksize[0] != P_I.blocksize[0]) or\
       (I_F.blocksize[0] != T.blocksize[0]):
        raise TypeError('Expected identical blocksize in I_F, P_I and T')

    # Only do if we have a non-trivial coarse-grid
    if P_I.nnz > 0:
        # Construct block diagonal inverse D
        D = P_I.T*T
        if D.nnz > 0:
            # changes D in place
            linalg.pinv_array(D.data)

        # Scale T to be identity at root-nodes
        T = T*D

        # Ensure coarse-grid injection
        T = I_F*T + P_I

    return T
def scale_T ( T , P_I , I_F ) : if not isspmatrix_bsr ( T ) : raise TypeError ( 'Expected BSR matrix T' ) if T . blocksize [ 0 ] != T . blocksize [ 1 ] : raise TypeError ( 'Expected BSR matrix T with square blocks' ) if not isspmatrix_bsr ( P_I ) : raise TypeError ( 'Expected BSR matrix P_I' ) if P_I . blocksize [ 0 ] != P_I . blocksize [ 1 ] : raise TypeError ( 'Expected BSR matrix P_I with square blocks' ) if not isspmatrix_bsr ( I_F ) : raise TypeError ( 'Expected BSR matrix I_F' ) if I_F . blocksize [ 0 ] != I_F . blocksize [ 1 ] : raise TypeError ( 'Expected BSR matrix I_F with square blocks' ) if ( I_F . blocksize [ 0 ] != P_I . blocksize [ 0 ] ) or ( I_F . blocksize [ 0 ] != T . blocksize [ 0 ] ) : raise TypeError ( 'Expected identical blocksize in I_F, P_I and T' ) # Only do if we have a non-trivial coarse-grid if P_I . nnz > 0 : # Construct block diagonal inverse D D = P_I . T * T if D . nnz > 0 : # changes D in place linalg . pinv_array ( D . data ) # Scale T to be identity at root-nodes T = T * D # Ensure coarse-grid injection T = I_F * T + P_I return T