def computeMatrixKorn(self, mucell): ncomp = self.ncomp dimension, dV, ndofs = self.mesh.dimension, self.mesh.dV, self.nunknowns( ) nloc, dofspercell, nall = self.nlocal(), self.dofspercell( ), ncomp * ndofs ci0 = self.mesh.cellsOfInteriorFaces[:, 0] ci1 = self.mesh.cellsOfInteriorFaces[:, 1] assert np.all(ci1 >= 0) normalsS = self.mesh.normals[self.mesh.innerfaces] dS = linalg.norm(normalsS, axis=1) faces = self.mesh.faces[self.mesh.innerfaces] # fi0, fi1 = self.mesh.facesOfCellsNotOnInnerFaces(faces, ci0, ci1) fi0, fi1 = self.mesh.facesOfCellsNotOnInnerFaces(ci0, ci1) massloc = barycentric.crbdryothers(dimension) if isinstance(mucell, (int, float)): scale = mucell * dS / (dV[ci0] + dV[ci1]) else: scale = (mucell[ci0] + mucell[ci1]) * dS / (dV[ci0] + dV[ci1]) scale *= 8 A = sparse.coo_matrix((nall, nall)) mat = np.einsum('n,kl->nkl', dS * scale, massloc).reshape(-1) for icomp in range(ncomp): d0 = ncomp * fi0 + icomp d1 = ncomp * fi1 + icomp rows0 = d0.repeat(nloc - 1) cols0 = np.tile(d0, nloc - 1).ravel() rows1 = d1.repeat(nloc - 1) cols1 = np.tile(d1, nloc - 1).ravel() A += sparse.coo_matrix((mat, (rows0, cols0)), shape=(nall, nall)) A += sparse.coo_matrix((-mat, (rows0, cols1)), shape=(nall, nall)) A += sparse.coo_matrix((-mat, (rows1, cols0)), shape=(nall, nall)) A += sparse.coo_matrix((mat, (rows1, cols1)), shape=(nall, nall)) return A
def computeBdryMassMatrix(self, colors=None, coeff=1, lumped=False): nfaces, dim = self.mesh.nfaces, self.mesh.dimension massloc = barycentric.crbdryothers(dim) # lumped = False if colors is None: colors = self.mesh.bdrylabels.keys() if not isinstance(coeff, dict): faces = self.mesh.bdryFaces(colors) normalsS = self.mesh.normals[faces] dS = linalg.norm(normalsS, axis=1) if isinstance(coeff, (int, float)): dS *= coeff elif coeff.shape[0] == self.mesh.nfaces: dS *= coeff[faces] elif coeff.shape[0] == dS.shape[0]: dS *= coeff else: raise ValueError(f"cannot handle {coeff=}") AD = sparse.coo_matrix((dS, (faces, faces)), shape=(nfaces, nfaces)) if lumped: return AD ci = self.mesh.cellsOfFaces[faces][:, 0] foc = self.mesh.facesOfCells[ci] mask = foc != faces[:, np.newaxis] # print(f"{mask=}") fi = foc[mask].reshape(foc.shape[0], foc.shape[1] - 1) # print(f"{massloc=}") cols = np.tile(fi, dim).ravel() rows = np.repeat(fi, dim).ravel() mat = np.einsum('n,kl->nkl', dS, massloc).ravel() return AD + sparse.coo_matrix( (mat, (rows, cols)), shape=(nfaces, nfaces)) assert (isinstance(coeff, dict)) rows = np.empty(shape=(0), dtype=int) cols = np.empty(shape=(0), dtype=int) mat = np.empty(shape=(0), dtype=float) for color in colors: faces = self.mesh.bdrylabels[color] normalsS = self.mesh.normals[faces] dS = linalg.norm(normalsS, axis=1) * coeff[color] cols = np.append(cols, faces) rows = np.append(rows, faces) mat = np.append(mat, dS) if not lumped: ci = self.mesh.cellsOfFaces[faces][:, 0] foc = self.mesh.facesOfCells[ci] mask = foc != faces[:, np.newaxis] fi = foc[mask].reshape(foc.shape[0], foc.shape[1] - 1) # print(f"{massloc=}") cols = np.append(cols, np.tile(fi, dim).ravel()) rows = np.append(rows, np.repeat(fi, dim).ravel()) mat = np.append(mat, np.einsum('n,kl->nkl', dS, massloc).ravel()) # print(f"{mat=}") return sparse.coo_matrix((mat, (rows, cols)), shape=(nfaces, nfaces)).tocsr()
def computeMatrixJump(self, betart, mode='primal', monotone=False): dim, dV, nfaces, ndofs = self.mesh.dimension, self.mesh.dV, self.mesh.nfaces, self.nunknowns( ) nloc, dofspercell = self.nlocal(), self.dofspercell() innerfaces = self.mesh.innerfaces ci0 = self.mesh.cellsOfInteriorFaces[:, 0] ci1 = self.mesh.cellsOfInteriorFaces[:, 1] normalsS = self.mesh.normals[innerfaces] dS = linalg.norm(normalsS, axis=1) faces = self.mesh.faces[self.mesh.innerfaces] # ind0 = npext.positionin(faces, self.mesh.simplices[ci0]) # ind1 = npext.positionin(faces, self.mesh.simplices[ci1]) # fi0 = np.take_along_axis(self.mesh.facesOfCells[ci0], ind0, axis=1) # fi1 = np.take_along_axis(self.mesh.facesOfCells[ci1], ind1, axis=1) fi0, fi1 = self.mesh.facesOfCellsNotOnInnerFaces(ci0, ci1) ifaces = np.arange(nfaces)[innerfaces] A = sparse.coo_matrix((ndofs, ndofs)) rows0 = np.repeat(fi0, nloc - 1).ravel() cols0 = np.tile(fi0, nloc - 1).ravel() rows1 = np.repeat(fi1, nloc - 1).ravel() cols1 = np.tile(fi1, nloc - 1).ravel() massloc = barycentric.crbdryothers(self.mesh.dimension) if mode == 'primal': mat = np.einsum('n,kl->nkl', np.minimum(betart[innerfaces], 0) * dS, massloc).ravel() A -= sparse.coo_matrix((mat, (rows0, cols0)), shape=(ndofs, ndofs)) A += sparse.coo_matrix((mat, (rows0, cols1)), shape=(ndofs, ndofs)) mat = np.einsum('n,kl->nkl', np.maximum(betart[innerfaces], 0) * dS, massloc).ravel() A -= sparse.coo_matrix((mat, (rows1, cols0)), shape=(ndofs, ndofs)) A += sparse.coo_matrix((mat, (rows1, cols1)), shape=(ndofs, ndofs)) elif mode == 'dual': mat = np.einsum('n,kl->nkl', np.minimum(betart[innerfaces], 0) * dS, massloc).ravel() A += sparse.coo_matrix((mat, (rows0, cols1)), shape=(ndofs, ndofs)) A -= sparse.coo_matrix((mat, (rows1, cols1)), shape=(ndofs, ndofs)) mat = np.einsum('n,kl->nkl', np.maximum(betart[innerfaces], 0) * dS, massloc).ravel() A += sparse.coo_matrix((mat, (rows0, cols0)), shape=(ndofs, ndofs)) A -= sparse.coo_matrix((mat, (rows1, cols0)), shape=(ndofs, ndofs)) elif mode == 'centered': mat = np.einsum('n,kl->nkl', betart[innerfaces] * dS, massloc).ravel() A += sparse.coo_matrix((mat, (rows0, cols0)), shape=(ndofs, ndofs)) A -= sparse.coo_matrix((mat, (rows1, cols1)), shape=(ndofs, ndofs)) else: raise ValueError(f"unknown {mode=}") return A
def massDotBoundary(self, b=None, f=None, colors=None, coeff=1, lumped=None): #TODO CR1 boundary integrals: can do at ones since last index in facesOfCells is the bdry side: # assert np.all(faces == foc[:,-1]) if lumped is None: lumped = self.params_bool['masslumpedbdry'] if colors is None: colors = self.mesh.bdrylabels.keys() massloc = barycentric.crbdryothers(self.mesh.dimension) if not isinstance(coeff, dict): faces = self.mesh.bdryFaces(colors) normalsS = self.mesh.normals[faces] dS = linalg.norm(normalsS, axis=1) if isinstance(coeff, (int, float)): dS *= coeff elif coeff.shape[0] == self.mesh.nfaces: dS *= coeff[faces] else: dS *= coeff if b is None: bsum = np.sum(dS * f[faces]) else: b[faces] += dS * f[faces] if lumped: if b is None: return bsum else: return b else: ci = self.mesh.cellsOfFaces[faces][:, 0] foc = self.mesh.facesOfCells[ci] mask = foc != faces[:, np.newaxis] fi = foc[mask].reshape(foc.shape[0], foc.shape[1] - 1) r = np.einsum('n,kl,nl->nk', dS, massloc, f[fi]) if b is None: return bsum + np.sum(r) # print(f"{np.linalg.norm(f[fi])=}") np.add.at(b, fi, r) return b assert (isinstance(coeff, dict)) for color in colors: faces = self.mesh.bdrylabels[color] normalsS = self.mesh.normals[faces] dS = linalg.norm(normalsS, axis=1) dS *= coeff[color] b[faces] += dS * f[faces] if lumped: continue ci = self.mesh.cellsOfFaces[faces][:, 0] foc = self.mesh.facesOfCells[ci] mask = foc != faces[:, np.newaxis] fi = foc[mask].reshape(foc.shape[0], foc.shape[1] - 1) r = np.einsum('n,kl,nl->nk', dS, massloc, f[fi]) # print(f"{np.linalg.norm(f[fi])=}") np.add.at(b, fi, r) return b
def computeMatrixHdivPenaly(self, coef=1): ncomp = self.ncomp dim, dV, ndofs, nloc = self.mesh.dimension, self.mesh.dV, self.nunknowns( ), self.nlocal() nall = ncomp * ndofs ci0 = self.mesh.cellsOfInteriorFaces[:, 0] ci1 = self.mesh.cellsOfInteriorFaces[:, 1] assert np.all(ci1 >= 0) normalsS = self.mesh.normals[self.mesh.innerfaces, :dim] dS = linalg.norm(normalsS, axis=1) fi0, fi1 = self.mesh.facesOfCellsNotOnInnerFaces(ci0, ci1) massloc = barycentric.crbdryothers(dim) if isinstance(coef, (int, float)): scale = coef / (dV[ci0] + dV[ci1]) else: assert coef.shape == (self.mesh.ncells) scale = (coef[ci0] + coef[ci1]) / (dV[ci0] + dV[ci1]) A = sparse.coo_matrix((nall, nall)) for icomp in range(ncomp): d0i = ncomp * fi0 + icomp d1i = ncomp * fi1 + icomp rows0i = d0i.repeat(nloc - 1) rows1i = d1i.repeat(nloc - 1) for jcomp in range(ncomp): d0j = ncomp * fi0 + jcomp d1j = ncomp * fi1 + jcomp cols0j = np.tile(d0j, nloc - 1).ravel() cols1j = np.tile(d1j, nloc - 1).ravel() mat = np.einsum( 'n,kl->nkl', normalsS[:, icomp] * normalsS[:, jcomp] * scale, massloc).ravel() # print(f"{mat=}") A += sparse.coo_matrix((mat, (rows0i, cols0j)), shape=(nall, nall)) A += sparse.coo_matrix((-mat, (rows0i, cols1j)), shape=(nall, nall)) A += sparse.coo_matrix((-mat, (rows1i, cols0j)), shape=(nall, nall)) A += sparse.coo_matrix((mat, (rows1i, cols1j)), shape=(nall, nall)) # print(f"{A.A=}") return A
def computeFormJump(self, du, u, betart, mode='primal'): dim, dV, nfaces, ndofs = self.mesh.dimension, self.mesh.dV, self.mesh.nfaces, self.nunknowns( ) nloc, dofspercell = self.nlocal(), self.dofspercell() innerfaces = self.mesh.innerfaces ci0 = self.mesh.cellsOfInteriorFaces[:, 0] ci1 = self.mesh.cellsOfInteriorFaces[:, 1] normalsS = self.mesh.normals[innerfaces] dS = linalg.norm(normalsS, axis=1) faces = self.mesh.faces[self.mesh.innerfaces] # ind0 = npext.positionin(faces, self.mesh.simplices[ci0]) # ind1 = npext.positionin(faces, self.mesh.simplices[ci1]) # fi0 = np.take_along_axis(self.mesh.facesOfCells[ci0], ind0, axis=1) # fi1 = np.take_along_axis(self.mesh.facesOfCells[ci1], ind1, axis=1) fi0, fi1 = self.mesh.facesOfCellsNotOnInnerFaces(ci0, ci1) # fi0, fi1 = self.mesh.facesOfCellsNotOnFaces(faces, ci0, ci1) # ifaces = np.arange(nfaces)[innerfaces] # A = sparse.coo_matrix((ndofs, ndofs)) # rows0 = np.repeat(fi0, nloc-1).ravel() # cols0 = np.tile(fi0,nloc-1).ravel() # rows1 = np.repeat(fi1, nloc-1).ravel() # cols1 = np.tile(fi1,nloc-1).ravel() massloc = barycentric.crbdryothers(self.mesh.dimension) if mode == 'primal': mat = np.einsum('n,kl,nl->nk', np.minimum(betart[innerfaces], 0) * dS, massloc, u[fi1] - u[fi0]) np.add.at(du, fi0, mat) mat = np.einsum('n,kl,nl->nk', np.maximum(betart[innerfaces], 0) * dS, massloc, u[fi1] - u[fi0]) np.add.at(du, fi1, mat) elif mode == 'dual': assert 0 elif mode == 'centered': assert 0 else: raise ValueError(f"unknown {mode=}")
def computeFormHdivPenaly(self, du, u, coef=1): ncomp = self.ncomp dim, dV, ndofs = self.mesh.dimension, self.mesh.dV, self.nunknowns() ci0 = self.mesh.cellsOfInteriorFaces[:, 0] ci1 = self.mesh.cellsOfInteriorFaces[:, 1] assert np.all(ci1 >= 0) normalsS = self.mesh.normals[self.mesh.innerfaces, :dim] dS = linalg.norm(normalsS, axis=1) faces = self.mesh.faces[self.mesh.innerfaces] fi0, fi1 = self.mesh.facesOfCellsNotOnInnerFaces(ci0, ci1) massloc = barycentric.crbdryothers(dim) if isinstance(coef, (int, float)): scale = coef / (dV[ci0] + dV[ci1]) else: assert coef.shape == (self.mesh.ncells) scale = (coef[ci0] + coef[ci1]) / (dV[ci0] + dV[ci1]) for icomp in range(ncomp): u = u.reshape((dim, ndofs), order='F') # print(f"{normalsS.shape} {u[:,fi0].shape=}") r = np.einsum('n,nj,kl,jnl->nk', normalsS[:, icomp] * scale, normalsS, massloc, u[:, fi0] - u[:, fi1]) np.add.at(du, ncomp * fi0 + icomp, r) np.add.at(du, ncomp * fi1 + icomp, -r)