def jacobian(self, state): '''Jacobian J of F in M * du / dt = F(u) defined on the domain map used by HYMLS.''' state_ass = Vector(self.assembly_map) state_ass.Import(state, self.assembly_importer, Epetra.Insert) local_jac = fvm.Interface.jacobian(self, state_ass) if self.jac is None: self.jac = Epetra.FECrsMatrix(Epetra.Copy, self.solve_map, 27) else: self.jac.PutScalar(0.0) for i in range(len(local_jac.begA)-1): if self.is_ghost(i): continue row = self.assembly_map.GID64(i) for j in range(local_jac.begA[i], local_jac.begA[i+1]): # __setitem__ automatically calls ReplaceGlobalValues if the matrix is filled, # InsertGlobalValues otherwise self.jac[row, self.assembly_map.GID64(local_jac.jcoA[j])] = local_jac.coA[j] self.jac.GlobalAssemble(True, Epetra.Insert) return self.jac
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 matmat(self, other): from PyTrilinos import Epetra try: from block.block_util import isscalar if isscalar(other): x = Epetra.Vector(self.v) x.Scale(other) return diag_op(x) other = other.down_cast() if hasattr(other, 'mat'): C = Epetra.FECrsMatrix(other.mat()) C.LeftScale(self.v) return matrix_op(C) else: x = Epetra.Vector(self.v.Map()) x.Multiply(1.0, self.v, other.vec(), 0.0) return diag_op(x) except AttributeError: raise TypeError("can't extract matrix data from type '%s'"%str(type(other)))
def add(self, other, lscale=1.0, rscale=1.0): try: other = other.down_cast() except AttributeError: #raise TypeError("can't extract matrix data from type '%s'"%str(type(other))) pass if hasattr(other, 'mat'): from PyTrilinos import Epetra, EpetraExt C = Epetra.FECrsMatrix(Epetra.Copy, self.rowmap(), 100) assert (0 == EpetraExt.Add(self.M, self.transposed, lscale, C, 0.0)) assert (0 == EpetraExt.Add(other.mat(), other.transposed, rscale, C, 1.0)) C.FillComplete() C.OptimizeStorage() return matrix_op(C) else: lhs = self.matmat(lscale) D = Diag(lhs).add(other, rscale=rscale) lhs.M.ReplaceDiagonalValues(D.vec()) return lhs
def mass_matrix(self): '''Mass matrix M in M * du / dt = F(u) defined on the domain map used by HYMLS.''' local_mass = fvm.Interface.mass_matrix(self) if self.mass is None: self.mass = Epetra.FECrsMatrix(Epetra.Copy, self.solve_map, 1) else: self.mass.PutScalar(0.0) for i in range(len(local_mass.begA)-1): if self.is_ghost(i): continue row = self.assembly_map.GID64(i) for j in range(local_mass.begA[i], local_mass.begA[i+1]): # __setitem__ automatically calls ReplaceGlobalValues if the matrix is filled, # InsertGlobalValues otherwise self.mass[row, self.assembly_map.GID64(local_mass.jcoA[j])] = local_mass.coA[j] self.mass.GlobalAssemble(True, Epetra.Insert) return self.mass