def normalize_adj(adj : sp.csr_matrix): """Normalize adjacency matrix and convert it to a sparse tensor.""" if sp.isspmatrix(adj): adj = adj.tolil() adj.setdiag(1) adj = adj.tocsr() deg = np.ravel(adj.sum(1)) deg_sqrt_inv = 1 / np.sqrt(deg) adj_norm = adj.multiply(deg_sqrt_inv[:, None]).multiply(deg_sqrt_inv[None, :]) elif torch.is_tensor(adj): deg = adj.sum(1) deg_sqrt_inv = 1 / torch.sqrt(deg) adj_norm = adj * deg_sqrt_inv[:, None] * deg_sqrt_inv[None, :] return to_sparse_tensor(adj_norm)
def _assemble_neumann_common( self, g: pp.Grid, data: Dict, M: sps.csr_matrix, mass: sps.csr_matrix, bc_weight: float = None, ) -> Tuple[sps.csr_matrix, np.ndarray]: """ Impose Neumann boundary discretization on an already assembled system matrix. Common implementation for VEM and RT0. The parameter mass should be adapted to the discretization method in question """ norm = sps.linalg.norm(mass, np.inf) if bc_weight else 1 parameter_dictionary = data[pp.PARAMETERS][self.keyword] bc = parameter_dictionary["bc"] # assign the Neumann boundary conditions # For dual discretizations, internal boundaries # are handled by assigning Dirichlet conditions. THus, we remove them # from the is_neu (where they belong by default) and add them in # is_dir. is_neu = np.logical_and(bc.is_neu, np.logical_not(bc.is_internal)) if bc and np.any(is_neu): is_neu = np.hstack((is_neu, np.zeros(g.num_cells, dtype=np.bool))) is_neu = np.where(is_neu)[0] # set in an efficient way the essential boundary conditions, by # clear the rows and put norm in the diagonal for row in is_neu: M.data[M.indptr[row]:M.indptr[row + 1]] = 0.0 d = M.diagonal() d[is_neu] = norm M.setdiag(d) return M, norm
def removeEye(adj: sp.csr_matrix): adj = adj.tolil(copy=True) adj.setdiag(0) return adj.tocsr()
def addEye(adj: sp.csr_matrix): adj = adj.tolil(copy=True) adj.setdiag(1) return adj.tocsr()