def eigenvalues_from_eigenvectors(verts, tris, eigs, Q=None): if Q is None: Q = compute_mesh_laplacian(verts, tris, 'cotangent', return_vertex_area=False) return (eigs * (-Q * eigs)).sum(axis=0)
def manifold_harmonics(verts, tris, K, scaled=True, return_D=False, return_eigenvalues=False): Q, vertex_area = compute_mesh_laplacian(verts, tris, 'cotangent', return_vertex_area=True, area_type='lumped_mass') if scaled: D = sparse.spdiags(vertex_area, 0, len(verts), len(verts)) else: D = sparse.spdiags(np.ones_like(vertex_area), 0, len(verts), len(verts)) try: lambda_dense, Phi_dense = eigsh(-Q, M=D, k=K, sigma=0) except RuntimeError, e: if e.message == 'Factor is exactly singular': logging.warn( "factor is singular, trying some regularization and cholmod") chol_solve = factorized(-Q + sparse.eye(Q.shape[0]) * 1.e-9) OPinv = sparse.linalg.LinearOperator(Q.shape, matvec=chol_solve) lambda_dense, Phi_dense = eigsh(-Q, M=D, k=K, sigma=0, OPinv=OPinv) else: raise e
def __init__(self, verts, tris, m=1.0): self._verts = verts self._tris = tris # precompute some stuff needed later on e01 = verts[tris[:, 1]] - verts[tris[:, 0]] e12 = verts[tris[:, 2]] - verts[tris[:, 1]] e20 = verts[tris[:, 0]] - verts[tris[:, 2]] self._triangle_area = .5 * veclen(np.cross(e01, e12)) unit_normal = normalized(np.cross(normalized(e01), normalized(e12))) self._un = unit_normal self._unit_normal_cross_e01 = np.cross(unit_normal, -e01) self._unit_normal_cross_e12 = np.cross(unit_normal, -e12) self._unit_normal_cross_e20 = np.cross(unit_normal, -e20) # parameters for heat method h = np.mean(map(veclen, [e01, e12, e20])) t = m * h**2 # pre-factorize poisson systems Lc, vertex_area = compute_mesh_laplacian(verts, tris, area_type='lumped_mass') A = sparse.spdiags(vertex_area, 0, len(verts), len(verts)) #self._factored_AtLc = splu((A - t * Lc).tocsc()).solve self._factored_AtLc = cholesky((A - t * Lc).tocsc(), mode='simplicial') #self._factored_L = splu(Lc.tocsc()).solve self._factored_L = cholesky(Lc.tocsc(), mode='simplicial')
def compressed_manifold_modes(verts, tris, K, mu, init=None, scaled=False, return_info=False, return_eigenvalues=False, return_D=False, order=True, algorithm=None, **algorithm_params): Q, vertex_area = compute_mesh_laplacian(verts, tris, 'cotangent', return_vertex_area=True, area_type='lumped_mass') if scaled: D = sparse.spdiags(np.sqrt(vertex_area), 0, len(verts), len(verts)) Dinv = sparse.spdiags(1 / np.sqrt(vertex_area), 0, len(verts), len(verts)) else: D = Dinv = None if init == 'mh': Phi_init = manifold_harmonics(verts, tris, K) elif init == 'varimax': Phi_init = varimax_modes(verts, tris, K) elif type(init) == np.ndarray: Phi_init = init else: Phi_init = None if algorithm is None: algorithm = solve_compressed_splitorth Phi, info = algorithm( Q, K, mu1=mu, Phi_init=Phi_init, D=D, Dinv=Dinv, **algorithm_params) l = eigenvalues_from_eigenvectors(verts, tris, Phi, Q=Q) if order: idx = np.abs(l).argsort() Phi = Phi[:, idx] l = l[idx] result = [Phi] if return_eigenvalues: result.append(l) if return_D: if D is not None: result.append(D * D) else: result.append(None) if return_info: result.append(info) if len(result) == 1: return result[0] else: return result
def manifold_harmonics(verts, tris, K, scaled=True, return_D=False, return_eigenvalues=False): Q, vertex_area = compute_mesh_laplacian( verts, tris, 'cotangent', return_vertex_area=True, area_type='lumped_mass' ) if scaled: D = sparse.spdiags(vertex_area, 0, len(verts), len(verts)) else: D = sparse.spdiags(np.ones_like(vertex_area), 0, len(verts), len(verts)) try: lambda_dense, Phi_dense = eigsh(-Q, M=D, k=K, sigma=0) except RuntimeError, e: if e.message == 'Factor is exactly singular': logging.warn("factor is singular, trying some regularization and cholmod") chol_solve = factorized(-Q + sparse.eye(Q.shape[0]) * 1.e-9) OPinv = sparse.linalg.LinearOperator(Q.shape, matvec=chol_solve) lambda_dense, Phi_dense = eigsh(-Q, M=D, k=K, sigma=0, OPinv=OPinv) else: raise e
def __init__(self, verts, tris, m=1.0): self._verts = verts self._tris = tris # precompute some stuff needed later on e01 = verts[tris[:,1]] - verts[tris[:,0]] e12 = verts[tris[:,2]] - verts[tris[:,1]] e20 = verts[tris[:,0]] - verts[tris[:,2]] self._triangle_area = .5 * veclen(np.cross(e01, e12)) unit_normal = normalized(np.cross(normalized(e01), normalized(e12))) self._un = unit_normal self._unit_normal_cross_e01 = np.cross(unit_normal, -e01) self._unit_normal_cross_e12 = np.cross(unit_normal, -e12) self._unit_normal_cross_e20 = np.cross(unit_normal, -e20) # parameters for heat method h = np.mean(map(veclen, [e01, e12, e20])) t = m * h ** 2 # pre-factorize poisson systems Lc, vertex_area = compute_mesh_laplacian(verts, tris, area_type='lumped_mass') A = sparse.spdiags(vertex_area, 0, len(verts), len(verts)) #self._factored_AtLc = splu((A - t * Lc).tocsc()).solve self._factored_AtLc = factorized((A - t * Lc).tocsc()) #self._factored_L = splu(Lc.tocsc()).solve self._factored_L = factorized(Lc.tocsc())
def compressed_manifold_modes(verts, tris, K, mu, init=None, scaled=False, return_info=False, return_eigenvalues=False, return_D=False, order=True, algorithm=None, **algorithm_params): Q, vertex_area = compute_mesh_laplacian(verts, tris, 'cotangent', return_vertex_area=True, area_type='lumped_mass') if scaled: D = sparse.spdiags(np.sqrt(vertex_area), 0, len(verts), len(verts)) Dinv = sparse.spdiags(1 / np.sqrt(vertex_area), 0, len(verts), len(verts)) else: D = Dinv = None if init == 'mh': Phi_init = manifold_harmonics(verts, tris, K) elif init == 'varimax': Phi_init = varimax_modes(verts, tris, K) elif type(init) == np.ndarray: Phi_init = init else: Phi_init = None if algorithm is None: algorithm = solve_compressed_splitorth Phi, info = algorithm(Q, K, mu1=mu, Phi_init=Phi_init, D=D, Dinv=Dinv, **algorithm_params) l = eigenvalues_from_eigenvectors(verts, tris, Phi, Q=Q) if order: idx = np.abs(l).argsort() Phi = Phi[:, idx] l = l[idx] result = [Phi] if return_eigenvalues: result.append(l) if return_D: if D is not None: result.append(D * D) else: result.append(None) if return_info: result.append(info) if len(result) == 1: return result[0] else: return result