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)))
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
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
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
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
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
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
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