def solve(self, rhs, autoTranspose=False): """ If autoTranspose == False, solves the system of equations L^Tx = rhs, otherwise solves the system Lx = rhs. Here L denotes the discrete Laplacian matrix with the boundary row and column vectors extracted. """ # Both UMFPACK and SuperLU internally use CSC format, while L uses CSR # format. Thus, passing L's data `as is' into those routines would give # us the solution to L^Tx = rhs. When autoTranspose is set to True, we # first have to convert L to CSR and then pass it on. We will use _left # to label the structures for solving L^Tx = rhs (since x multiplies L # on the left) and right for those that enable solving Lx = rhs (since # x in this case multiplies L on the right). Thus, autoTranspose set # really means that `left' structures are used. if not autoTranspose: if self.solve_left is None: A = self.L.transpose() # a CSC matrix - no copy self.solve_left = dsolve.factorized(A) solve = self.solve_left else: if self.solve_right is None: A = self.L.tocsc() # requires a copy self.solve_right = dsolve.factorized(A) solve = self.solve_right x = solve(rhs) return x
def geodesic_distance(pts, polys, verts): """ Computes the geodesic distance using the heat method (Crane et al, 2012) :param pts: arrays of vertices :param polys: arrays of faces :param verts: array of :return: """ num_pt = len(pts) C, M = laplace_operator(pts, polys) # Step 1: Solve the heat values u # time of heat evolution h = avg_edge_length(pts, polys) t = h**2 # use backward Euler step lfac = M - t * C # Exclude rows with zero weight (these break the sparse LU) goodrows = np.nonzero(~np.array(lfac.sum(0) == 0).ravel())[0] # Prefactor matrices _rlfac_solvers = factorized(lfac[goodrows][:, goodrows]) _nLC_solvers = factorized(C[goodrows][:, goodrows]) # Compute u u0 = np.zeros((num_pt)) # initial heat values u0[verts] = 1.0 goodu = _rlfac_solvers(u0[goodrows]) u = np.zeros((num_pt, )) u[goodrows] = goodu # Step 2: Compute X (normalized gradient) # Compute gradients at each face gradu = surface_gradient(pts, polys, u) # Compute X graduT = gradu.T gusum = ne.evaluate("sum(gradu ** 2, 1)") X = np.nan_to_num(ne.evaluate("-graduT / sqrt(gusum)").T) # Step 3: Solve the poisson equation # Compute integrated divergence of X at each vertex divx = integrated_divergence(pts, polys, X) # Compute phi (distance) goodphi = _nLC_solvers(divx[goodrows]) phi = np.zeros((num_pt, )) phi[goodrows] = goodphi - goodphi.min() # Ensure that distance is zero for selected verts phi[verts] = 0.0 return phi
def test_call_with_cast_to_complex_without_umfpack(self): use_solver(useUmfpack=False) solve = factorized(self.A) b = random.rand(4) for t in [np.complex64, np.complex128]: with assert_raises(TypeError, match="Cannot cast array data"): solve(b.astype(t))
def test_call_with_cast_to_complex_without_umfpack(self): use_solver(useUmfpack=False) solve = factorized(self.A) b = random.rand(4) for t in [np.complex64, np.complex128]: with assert_raises(TypeError, message="Cannot cast array data"): solve(b.astype(t))
def test_bug_8278(self): check_free_memory(8000) use_solver(useUmfpack=True) A, b = setup_bug_8278() A = A.tocsc() f = factorized(A) x = f(b) assert_array_almost_equal(A @ x, b)
def _check_non_singular(self): # Make a diagonal dominant, to make sure it is not singular n = 5 a = csc_matrix(random.rand(n, n)) b = ones(n) expected = splu(a).solve(b) assert_array_almost_equal(factorized(a)(b), expected)
def test_call_with_incorrectly_sized_matrix_without_umfpack(self): use_solver(useUmfpack=False) solve = factorized(self.A) b = random.rand(4) B = random.rand(4, 3) BB = random.rand(self.n, 3, 9) assert_raises_regex(ValueError, "is of incompatible size", solve, b) assert_raises_regex(ValueError, "is of incompatible size", solve, B) assert_raises_regex(ValueError, "object too deep for desired array", solve, BB)
def test_assume_sorted_indices_flag(self): # a sparse matrix with unsorted indices unsorted_inds = np.array([2, 0, 1, 0]) data = np.array([10, 16, 5, 0.4]) indptr = np.array([0, 1, 2, 4]) A = csc_matrix((data, unsorted_inds, indptr), (3, 3)) b = ones(3) # should raise when incorrectly assuming indices are sorted use_solver(useUmfpack=True, assumeSortedIndices=True) with assert_raises(RuntimeError, match="UMFPACK_ERROR_invalid_matrix"): factorized(A) # should sort indices and succeed when not assuming indices are sorted use_solver(useUmfpack=True, assumeSortedIndices=False) expected = splu(A.copy()).solve(b) assert_equal(A.has_sorted_indices, 0) assert_array_almost_equal(factorized(A)(b), expected)
def test_call_with_incorrectly_sized_matrix_with_umfpack(self): use_solver(useUmfpack=True) solve = factorized(self.A) b = random.rand(4) B = random.rand(4, 3) BB = random.rand(self.n, 3, 9) # does not raise solve(b) assert_raises_regex(ValueError, "object too deep for desired array", solve, B) assert_raises_regex(ValueError, "object too deep for desired array", solve, BB)
def uzawa(A, B, f, g): Asolve = ssld.factorized(A) p = np.zeros(B.shape[0]) r = 0.0001 while True: u = Asolve(f.flatten() - B.transpose() * p) pd = B * u - g.flatten() p += r * pd pdl2 = math.sqrt(np.sum(pd * pd)) print pdl2 if pdl2 < 1E-6: break return u, p
def test_assume_sorted_indices_flag(self): # a sparse matrix with unsorted indices unsorted_inds = np.array([2, 0, 1, 0]) data = np.array([10, 16, 5, 0.4]) indptr = np.array([0, 1, 2, 4]) A = csc_matrix((data, unsorted_inds, indptr), (3, 3)) b = ones(3) # should raise when incorrectly assuming indices are sorted use_solver(useUmfpack=True, assumeSortedIndices=True) with assert_raises(RuntimeError, message="UMFPACK_ERROR_invalid_matrix"): factorized(A) # should sort indices and succeed when not assuming indices are sorted use_solver(useUmfpack=True, assumeSortedIndices=False) expected = splu(A.copy()).solve(b) assert_equal(A.has_sorted_indices, 0) assert_array_almost_equal(factorized(A)(b), expected) assert_equal(A.has_sorted_indices, 1)
def mixedcg(A, B, f, g): Asolve = ssld.factorized(A) Aif = Asolve(f.flatten()) BAf = B * Aif def BAiBt(p): return B * Asolve(B.transpose() * p) p, info = ssl.bicgstab(ssl.LinearOperator((B.shape[0],)*2, matvec = BAiBt, dtype=float), BAf - g.flatten()) print "bicgstab result ",info u = Aif - Asolve(B.transpose() * p) return u,p
def test_call_with_incorrectly_sized_matrix_with_umfpack(self): use_solver(useUmfpack=True) solve = factorized(self.A) b = random.rand(4) B = random.rand(4, 3) BB = random.rand(self.n, 3, 9) # does not raise solve(b) msg = "object too deep for desired array" with assert_raises(ValueError, message=msg): solve(B) with assert_raises(ValueError, message=msg): solve(BB)
def test_call_with_incorrectly_sized_matrix_without_umfpack(self): use_solver(useUmfpack=False) solve = factorized(self.A) b = random.rand(4) B = random.rand(4, 3) BB = random.rand(self.n, 3, 9) with assert_raises(ValueError, match="is of incompatible size"): solve(b) with assert_raises(ValueError, match="is of incompatible size"): solve(B) with assert_raises(ValueError, match="object too deep for desired array"): solve(BB)
def test_call_with_incorrectly_sized_matrix_with_umfpack(self): use_solver(useUmfpack=True) solve = factorized(self.A) b = random.rand(4) B = random.rand(4, 3) BB = random.rand(self.n, 3, 9) # does not raise solve(b) msg = "object too deep for desired array" with assert_raises(ValueError, match=msg): solve(B) with assert_raises(ValueError, match=msg): solve(BB)
def test_call_with_incorrectly_sized_matrix_without_umfpack(self): use_solver(useUmfpack=False) solve = factorized(self.A) b = random.rand(4) B = random.rand(4, 3) BB = random.rand(self.n, 3, 9) with assert_raises(ValueError, message="is of incompatible size"): solve(b) with assert_raises(ValueError, message="is of incompatible size"): solve(B) with assert_raises(ValueError, message="object too deep for desired array"): solve(BB)
def _check_singular(self): A = csc_matrix((5,5), dtype='d') b = ones(5) assert_array_almost_equal(0. * b, factorized(A)(b))
def test_factorizes_nonsquare_matrix_with_umfpack(self): use_solver(useUmfpack=True) # does not raise factorized(self.A[:, :4])
def test_cannot_factorize_nonsquare_matrix_without_umfpack(self): use_solver(useUmfpack=False) msg = "can only factor square matrices" with assert_raises(ValueError, match=msg): factorized(self.A[:, :4])
def fitGlobal(self): """ Perform a global B-spline surface fit to determine the coefficients of each patch. This is only used with an plot3D init type """ print("Global Fitting") nCtl = self.topo.nGlobal print(" -> Copying Topology") origTopo = copy.deepcopy(self.topo) print(" -> Creating global numbering") sizes = [] for isurf in range(self.nSurf): sizes.append([self.surfs[isurf].Nu, self.surfs[isurf].Nv]) # Get the Global number of the original data origTopo.calcGlobalNumbering(sizes) N = origTopo.nGlobal print(" -> Creating global point list") pts = np.zeros((N, 3)) for ii in range(N): pts[ii] = self.surfs[origTopo.gIndex[ii][0][0]].X[origTopo.gIndex[ii][0][1], origTopo.gIndex[ii][0][2]] # Get the maximum k (ku, kv for each surf) kmax = 2 for isurf in range(self.nSurf): if self.surfs[isurf].ku > kmax: kmax = self.surfs[isurf].ku if self.surfs[isurf].kv > kmax: kmax = self.surfs[isurf].kv nnz = N * kmax * kmax vals = np.zeros(nnz) rowPtr = [0] colInd = np.zeros(nnz, "intc") for ii in range(N): isurf = origTopo.gIndex[ii][0][0] i = origTopo.gIndex[ii][0][1] j = origTopo.gIndex[ii][0][2] u = self.surfs[isurf].U[i, j] v = self.surfs[isurf].V[i, j] vals, colInd = self.surfs[isurf].getBasisPt(u, v, vals, rowPtr[ii], colInd, self.topo.lIndex[isurf]) kinc = self.surfs[isurf].ku * self.surfs[isurf].kv rowPtr.append(rowPtr[-1] + kinc) # Now we can crop out any additional values in col_ptr and vals vals = vals[: rowPtr[-1]] colInd = colInd[: rowPtr[-1]] # Now make a sparse matrix NN = sparse.csr_matrix((vals, colInd, rowPtr)) print(" -> Multiplying N^T * N") NNT = NN.T NTN = NNT * NN print(" -> Factorizing...") solve = factorized(NTN) print(" -> Back Solving...") self.coef = np.zeros((nCtl, 3)) for idim in range(3): self.coef[:, idim] = solve(NNT * pts[:, idim]) print(" -> Setting Surface Coefficients...") self._updateSurfaceCoef()
def _check_singular(self): A = csc_matrix((5, 5), dtype='d') b = ones(5) assert_array_almost_equal(0. * b, factorized(A)(b))
def test_call_with_cast_to_complex_with_umfpack(self): use_solver(useUmfpack=True) solve = factorized(self.A) b = random.rand(4) for t in [np.complex64, np.complex128]: assert_warns(np.ComplexWarning, solve, b.astype(t))
def test_factorizes_nonsquare_matrix_with_umfpack(self): use_solver(useUmfpack=True) # does not raise factorized(self.A[:,:4])
def test_cannot_factorize_nonsquare_matrix_without_umfpack(self): use_solver(useUmfpack=False) msg = "can only factor square matrices" with assert_raises(ValueError, message=msg): factorized(self.A[:, :4])