示例#1
0
    def matmat(self, other):

        from PyTrilinos import Epetra
        from block.block_util import isscalar
        try:
            if isscalar(other):
                C = type(self.M)(self.M)
                if other != 1:
                    C.Scale(other)
                return matrix_op(C, self.transposed)
            other = other.down_cast()
            if hasattr(other, 'mat'):
                from PyTrilinos import EpetraExt

                # Create result matrix C. This is done in a contorted way, to
                # ensure all diagonals are present.
                A = type(self.M)(self.M)
                A.PutScalar(1.0)
                B = type(other.mat())(other.mat())
                B.PutScalar(1.0)
                C = Epetra.FECrsMatrix(Epetra.Copy, self.rowmap(), 100)
                EpetraExt.Multiply(A, self.transposed, B, other.transposed, C)
                C.OptimizeStorage()
                # C is now finalised, we can use it to store the real mat-mat product.

                assert (0 == EpetraExt.Multiply(self.M, self.transposed,
                                                other.mat(), other.transposed,
                                                C))

                result = matrix_op(C)

                # Sanity check. Cannot trust EpetraExt.Multiply always, it seems.
                from block import block_vec
                v = result.create_vec()
                block_vec([v]).randomize()
                xv = self * other * v
                err = (xv - result * v).norm('l2') / (xv).norm('l2')
                if (err > 1e-3):
                    print('++ a :', self * other)
                    print('++ a\':', result)
                    print(
                        '++ EpetraExt.Multiply computed wrong result; ||(a-a\')x||/||ax|| = %g'
                        % err)

                return result
            else:
                C = type(self.M)(self.M)
                if self.transposed:
                    C.LeftScale(other.vec())
                else:
                    C.RightScale(other.vec())
                return matrix_op(C, self.transposed)
        except AttributeError:
            raise TypeError("can't extract matrix data from type '%s'" %
                            str(type(other)))
示例#2
0
def transpose_matrix(A):
    """
    Transposes a matrix
    Parameters
    ----------
    A: Epetra Matrix

    Returns
    -------
    C: transpose of matrix A
    """
    V = Epetra.Vector(A.RangeMap())
    V.PutScalar(1.0)
    I = diagonal_matrix_from_vector(V, A.RangeMap())
    C = Epetra.CrsMatrix(Epetra.Copy, A.DomainMap(), 10)
    EpetraExt.Multiply(A, True, I, False, C)
    C.FillComplete()
    return C
示例#3
0
def mat_multiply(A, B, transpose_1=False, transpose_2=False, fill=30):
    """
    Matrix product of two matrices
    Parameters
    ----------
    A: Epetra Matrix
    B: Epetra Matrix
    transpose_1: bool, optional
        If true, then A is transposed before multiplication
    transpose_2: bool, optional
        If true, then B is transposed before multiplication
    fill: int, optional
        estimate of how many nonzeros per row

    Returns
    -------
    C: Epetra Matrix
        C = A*B
    """
    if transpose_1:
        C = Epetra.CrsMatrix(Epetra.Copy, A.DomainMap(), fill)
    else:
        C = Epetra.CrsMatrix(Epetra.Copy, A.RangeMap(), fill)

    ierr = EpetraExt.Multiply(A, transpose_1, B, transpose_2, C)
    assert ierr == 0

    if transpose_1:
        C.FillComplete(B.DomainMap(), A.DomainMap())
    else:
        C.FillComplete()

    if not (transpose_1 or transpose_2):
        assert (C.NumGlobalRows(), C.NumGlobalCols()) == (A.NumGlobalRows(), B.NumGlobalCols())

    if transpose_1 and not transpose_2:
        assert (C.NumGlobalRows(), C.NumGlobalCols()) == (A.NumGlobalCols(), B.NumGlobalCols())

    if not transpose_1 and transpose_2:
        assert (C.NumGlobalRows(), C.NumGlobalCols()) == (A.NumGlobalRows(), B.NumGlobalRows())

    return C
示例#4
0
    def pymultimat(self, A, B, nf, transpose_A=False, transpose_B=False):
        """
        Multiplica a matriz A pela matriz B ambas de mesma ordem e quadradas
        nf: ordem da matriz

        """
        if A.Filled() == False:
            A.FillComplete()
        if B.Filled() == False:
            B.FillComplete()

        nf_map = Epetra.Map(nf, 0, self.comm)

        C = Epetra.CrsMatrix(Epetra.Copy, nf_map, 3)

        EpetraExt.Multiply(A, transpose_A, B, transpose_B, C)

        # C.FillComplete()

        return C
示例#5
0
    def pymultimat(comm, A, B, transpose_A=False, transpose_B=False):
        """
        Multiplica a matriz A pela matriz B ambas de mesma ordem e quadradas
        nf: ordem da matriz

        """
        assert A.NumMyCols() == A.NumMyRows()
        assert B.NumMyCols() == B.NumMyRows()
        assert A.NumMyRows() == B.NumMyRows()
        n = A.NumMyCols()

        if A.Filled() == False:
            A.FillComplete()
        if B.Filled() == False:
            B.FillComplete()

        nf_map = Epetra.Map(n, 0, comm)

        C = Epetra.CrsMatrix(Epetra.Copy, nf_map, 3)

        EpetraExt.Multiply(A, transpose_A, B, transpose_B, C)

        return C
示例#6
0
    def __mul__(self, other):
        """
        Multiply a sparse matrix by another sparse matrix.

        >>> L1 = _TrilinosMatrixFromShape(rows=3, cols=3)
        >>> L1.addAt((3, 10, numerix.pi, 2.5), (0, 0, 1, 2), (2, 1, 1, 0))
        >>> L2 = _TrilinosIdentityMatrix(size=3)
        >>> L2.addAt((4.38, 12357.2, 1.1), (2, 1, 0), (1, 0, 2))

        >>> tmp = numerix.array(((1.23572000e+05, 2.31400000e+01, 3.00000000e+00),
        ...                      (3.88212887e+04, 3.14159265e+00, 0.00000000e+00),
        ...                      (2.50000000e+00, 0.00000000e+00, 2.75000000e+00)))

        >>> L = (L1 * L2).numpyArray

        >>> print(numerix.allclose(tmp, L)) # doctest: +SERIAL
        True

        or a sparse matrix by a vector

        >>> tmp = numerix.array((29., 6.28318531, 2.5))
        >>> print(numerix.allclose(L1 * numerix.array((1, 2, 3), 'd'), tmp)) # doctest: +SERIAL
        True

        or a vector by a sparse matrix

        >>> tmp = numerix.array((7.5, 16.28318531,  3.))
        >>> print(numerix.allclose(numerix.array((1, 2, 3), 'd') * L1, tmp))  # doctest: +SERIAL
        True


        """
        N = self.matrix.NumMyCols()

        if isinstance(other, _TrilinosMatrix):
            if isinstance(other.matrix, Epetra.RowMatrix):
                self.fillComplete()
                other.fillComplete()

                result = Epetra.CrsMatrix(Epetra.Copy, self.rowMap, 0)

                EpetraExt.Multiply(self.matrix, False, other.matrix, False,
                                   result)
                copy = self.copy()
                copy.matrix = result
                return copy
            else:
                raise TypeError

        else:
            shape = numerix.shape(other)
            if shape == ():
                result = self.copy()
                result.matrix.Scale(other)
                return result
            elif shape == (N, ):
                self.fillComplete()

                y = Epetra.Vector(self.domainMap, other)
                result = Epetra.Vector(self.rangeMap)
                self.matrix.Multiply(False, y, result)
                return numerix.array(result)
            else:
                raise TypeError
示例#7
0
    def __mul__(self, other):
        """
        Multiply a sparse matrix by another sparse matrix.

            >>> L1 = _TrilinosMatrix(size=3)
            >>> L1.addAt((3,10,numerix.pi,2.5), (0,0,1,2), (2,1,1,0))
            >>> L2 = _TrilinosIdentityMatrix(size=3)
            >>> L2.addAt((4.38,12357.2,1.1), (2,1,0), (1,0,2))

            >>> tmp = numerix.array(((1.23572000e+05, 2.31400000e+01, 3.00000000e+00),
            ...                      (3.88212887e+04, 3.14159265e+00, 0.00000000e+00),
            ...                      (2.50000000e+00, 0.00000000e+00, 2.75000000e+00)))

            >>> for i in range(0,3):
            ...     for j in range(0,3):
            ...         numerix.allclose(((L1*L2)[i,j],), tmp[i,j])
            True
            True
            True
            True
            True
            True
            True
            True
            True

        or a sparse matrix by a vector

            >>> tmp = numerix.array((29., 6.28318531, 2.5))
            >>> numerix.allclose(L1 * numerix.array((1,2,3),'d'), tmp)
            1

        or a vector by a sparse matrix

            >>> tmp = numerix.array((7.5, 16.28318531,  3.))
            >>> numerix.allclose(numerix.array((1,2,3),'d') * L1, tmp)
            1


        """
        N = self._getMatrix().NumMyCols()

        if isinstance(other, _TrilinosMatrixBase):
            if isinstance(other._getMatrix(), Epetra.RowMatrix):

                if not self._getMatrix().Filled():
                    self._getMatrix().FillComplete()

                if not other._getMatrix().Filled():
                    other._getMatrix().FillComplete()

                result = Epetra.CrsMatrix(Epetra.Copy, self.nonOverlappingMap, 0)

                EpetraExt.Multiply(self._getMatrix(), False, other._getMatrix(), False, result)
                copy = self.copy()
                copy.matrix = result
                return copy
            else:
                raise TypeError

        else:
            shape = numerix.shape(other)
            if shape == ():
                result = self.copy()
                result._getMatrix().Scale(other)
                return result
            elif shape == (N,):

                if not self._getMatrix().Filled():
                    self._getMatrix().FillComplete()

                y = _numpyToTrilinosVector(other, self.nonOverlappingMap)
                result = Epetra.Vector(self.nonOverlappingMap)
                self._getMatrix().Multiply(False, y, result)
                return _trilinosToNumpyVector(result)
            else:
                raise TypeError
示例#8
0
    def smooth_prolongation_operator(self,
                                     A,
                                     max_iter=1000,
                                     tol=1.e-2,
                                     verbose=False):
        """
        Parameters
        ----------
        A: Epetra matrix

        max_iter: integer
            Number of smoothing steps

        verbose: bool
            Flag to output convergence information

        Notes
        -----
        See  Algorithm 2 in Mandel et al 1999. However Jacobi iteration is used for smoothing as opposed to
        gradient descent.
        """

        support_matrix_copy = Epetra.CrsMatrix(self.N)
        tau = Epetra.Vector(A.RangeMap())
        J = DinvA(A)
        ierr = 0
        delta_P_temp = Epetra.CrsMatrix(Epetra.Copy, A.RangeMap(), 40)

        for iter_n in xrange(max_iter):
            sum_cols_P = sum_of_columns(self.P)
            assert np.allclose(sum_cols_P[:], 1.0)

            ierr += EpetraExt.Multiply(J, False, self.P, False, delta_P_temp)

            # Drop entries of delta_P_temp not matching the structure of delta_P
            self.delta_P.PutScalar(0.0)
            ierr += EpetraExt.Add(delta_P_temp, False, 1.0, self.delta_P,
                                  1.0)  # delta_P = N*(D^-1 AP)

            sum_cols_delta_P = sum_of_columns(self.delta_P)

            assert np.all(self.num_overlaps[:] >= 1)

            tau[:] = sum_cols_delta_P[:] / self.num_overlaps[:]
            support_matrix_copy.PutScalar(1.0)
            support_matrix_copy.LeftScale(tau)  # last term in Equation (19)

            ierr += EpetraExt.Add(support_matrix_copy, False, -1.0,
                                  self.delta_P, 1.0)  # delta_P = Z(N*D^-1AP)

            sum_cols_delta_P = sum_of_columns(self.delta_P)
            assert np.allclose(sum_cols_delta_P[:], 0.0)
            ierr += EpetraExt.Add(self.delta_P, False, -0.5, self.P, 1.0)

            error = self.delta_P.NormInf()
            if error < tol:
                break

        logger.debug(
            "Basis function error: %g. Number of iterations required: %d",
            error, iter_n)

        if verbose:
            print "Basis function error: %g. Number of iterations required: %d" % (
                error, iter_n)

        sum_cols_P = sum_of_columns(self.P)

        assert np.allclose(sum_cols_P[:], 1.0, atol=1.e-1000, rtol=1e-12)

        # Important numerical  step to ensure that mass is exactly conserved to machine zero
        """
        tau[:] = 1./sum_cols_P[:]
        self.P.LeftScale(tau)
        sum_cols_P = sum_of_columns(self.P)

        assert np.allclose(sum_cols_P[:], 1.0, atol=1.e-1000, rtol=1.e-15)
        """
        assert ierr == 0