def test_shape_compatibility(self): use_solver(useUmfpack=True) A = csc_matrix([[1., 0], [0, 2]]) bs = [ [1, 6], array([1, 6]), [[1], [6]], array([[1], [6]]), csc_matrix([[1], [6]]), csr_matrix([[1], [6]]), dok_matrix([[1], [6]]), bsr_matrix([[1], [6]]), array([[1., 2., 3.], [6., 8., 10.]]), csc_matrix([[1., 2., 3.], [6., 8., 10.]]), csr_matrix([[1., 2., 3.], [6., 8., 10.]]), dok_matrix([[1., 2., 3.], [6., 8., 10.]]), bsr_matrix([[1., 2., 3.], [6., 8., 10.]]), ] for b in bs: x = np.linalg.solve(A.toarray(), toarray(b)) for spmattype in [csc_matrix, csr_matrix, dok_matrix, lil_matrix]: x1 = spsolve(spmattype(A), b, use_umfpack=True) x2 = spsolve(spmattype(A), b, use_umfpack=False) # check solution if x.ndim == 2 and x.shape[1] == 1: # interprets also these as "vectors" x = x.ravel() assert_array_almost_equal(toarray(x1), x, err_msg=repr((b, spmattype, 1))) assert_array_almost_equal(toarray(x2), x, err_msg=repr((b, spmattype, 2))) # dense vs. sparse output ("vectors" are always dense) if isspmatrix(b) and x.ndim > 1: assert_(isspmatrix(x1), repr((b, spmattype, 1))) assert_(isspmatrix(x2), repr((b, spmattype, 2))) else: assert_(isinstance(x1, np.ndarray), repr( (b, spmattype, 1))) assert_(isinstance(x2, np.ndarray), repr( (b, spmattype, 2))) # check output shape if x.ndim == 1: # "vector" assert_equal(x1.shape, (A.shape[1], )) assert_equal(x2.shape, (A.shape[1], )) else: # "matrix" assert_equal(x1.shape, x.shape) assert_equal(x2.shape, x.shape) A = csc_matrix((3, 3)) b = csc_matrix((1, 3)) assert_raises(ValueError, spsolve, A, b)
def fit_model(phi, eps=0.): assert phi.ndim == 2, 'data has to be two-dimensional' assert phi.shape[1] > phi.shape[0], 'data samples have to be in columns' d, nsamples = phi.shape nij = d**2 - d # number of coupling terms adata, arow, acol, b = fill_model_matrix(phi) a = sparse.coo_matrix((adata, (arow, acol)), (nij, nij)) tic('matrix inversion') if eps > 0: a2 = np.dot(a.T, a) + eps * nsamples * sparse.eye(nij, nij, format='coo') b2 = np.dot(a.todense().T, np.atleast_2d(b).T) # this sparse multiplication is buggy !!!!, I can't get the shape of b2 to be = (b.size,) b3 = b2.copy().flatten().T b3.shape = (b3.size, ) k_vec = dsolve.spsolve(a2.tocsr(), b3) k_mat = np.zeros((d, d), complex) k_mat.T[np.where(np.diag(np.ones(d)) - 1)] = k_vec.ravel() else: k_vec = dsolve.spsolve(a.tocsr(), b) k_mat = np.zeros((d, d), complex) k_mat.T[np.where(np.diag(np.ones(d)) - 1)] = k_vec toc('matrix inversion') return k_mat
def fit_model(phi, eps=0.): assert phi.ndim == 2, 'data has to be two-dimensional' assert phi.shape[1] > phi.shape[0], 'data samples have to be in columns' d, nsamples = phi.shape nij = d**2-d # number of coupling terms adata, arow, acol, b = fill_model_matrix(phi) a = sparse.coo_matrix((adata,(arow,acol)), (nij,nij)) tic('matrix inversion') if eps > 0: a2 = np.dot(a.T,a) + eps*nsamples*sparse.eye(nij,nij,format='coo') b2 = np.dot(a.todense().T,np.atleast_2d(b).T) # this sparse multiplication is buggy !!!!, I can't get the shape of b2 to be = (b.size,) b3 = b2.copy().flatten().T b3.shape = (b3.size,) k_vec = dsolve.spsolve(a2.tocsr(),b3) k_mat = np.zeros((d,d),complex) k_mat.T[np.where(np.diag(np.ones(d))-1)] = k_vec.ravel() else: k_vec = dsolve.spsolve(a.tocsr(),b) k_mat = np.zeros((d,d),complex) k_mat.T[np.where(np.diag(np.ones(d))-1)] = k_vec toc('matrix inversion') return k_mat
def test_shape_compatibility(self): use_solver(useUmfpack=True) A = csc_matrix([[1., 0], [0, 2]]) bs = [ [1, 6], array([1, 6]), [[1], [6]], array([[1], [6]]), csc_matrix([[1], [6]]), csr_matrix([[1], [6]]), dok_matrix([[1], [6]]), bsr_matrix([[1], [6]]), array([[1., 2., 3.], [6., 8., 10.]]), csc_matrix([[1., 2., 3.], [6., 8., 10.]]), csr_matrix([[1., 2., 3.], [6., 8., 10.]]), dok_matrix([[1., 2., 3.], [6., 8., 10.]]), bsr_matrix([[1., 2., 3.], [6., 8., 10.]]), ] for b in bs: x = np.linalg.solve(A.toarray(), toarray(b)) for spmattype in [csc_matrix, csr_matrix, dok_matrix, lil_matrix]: x1 = spsolve(spmattype(A), b, use_umfpack=True) x2 = spsolve(spmattype(A), b, use_umfpack=False) # check solution if x.ndim == 2 and x.shape[1] == 1: # interprets also these as "vectors" x = x.ravel() assert_array_almost_equal(toarray(x1), x, err_msg=repr((b, spmattype, 1))) assert_array_almost_equal(toarray(x2), x, err_msg=repr((b, spmattype, 2))) # dense vs. sparse output ("vectors" are always dense) if isspmatrix(b) and x.ndim > 1: assert_(isspmatrix(x1), repr((b, spmattype, 1))) assert_(isspmatrix(x2), repr((b, spmattype, 2))) else: assert_(isinstance(x1, np.ndarray), repr((b, spmattype, 1))) assert_(isinstance(x2, np.ndarray), repr((b, spmattype, 2))) # check output shape if x.ndim == 1: # "vector" assert_equal(x1.shape, (A.shape[1],)) assert_equal(x2.shape, (A.shape[1],)) else: # "matrix" assert_equal(x1.shape, x.shape) assert_equal(x2.shape, x.shape) A = csc_matrix((3, 3)) b = csc_matrix((1, 3)) assert_raises(ValueError, spsolve, A, b)
def test_dtype_cast(self): A_real = scipy.sparse.csr_matrix([[1, 2, 0], [0, 0, 3], [4, 0, 5]]) A_complex = scipy.sparse.csr_matrix([[1, 2, 0], [0, 0, 3], [4, 0, 5 + 1j]]) b_real = np.array([1, 1, 1]) b_complex = np.array([1, 1, 1]) + 1j * np.array([1, 1, 1]) x = spsolve(A_real, b_real) assert_(np.issubdtype(x.dtype, np.floating)) x = spsolve(A_real, b_complex) assert_(np.issubdtype(x.dtype, np.complexfloating)) x = spsolve(A_complex, b_real) assert_(np.issubdtype(x.dtype, np.complexfloating)) x = spsolve(A_complex, b_complex) assert_(np.issubdtype(x.dtype, np.complexfloating))
def n_springs(N, mu, f_vec): """ Compute the ratio $u_N/f_0$ for a chain of $N$ springs. The range of frequencies is given by $[f_{\min}, f_{\max}]$. $\mu$ is the ratio of masses $\mu = m_2/m_1$. """ nfreq = len(f_vec) uf_ratio = np.zeros(nfreq) force = np.zeros(2 * N + 1) force[0] = -1.0 for k, freq in enumerate(f_vec): d_main = np.zeros(2 * N + 1) d_main[1:-1:2] = -2. + mu * freq**2 d_main[2:-1:2] = -2. + freq**2 d_main[0] = -1.0 + freq**2 d_main[-1] = -1.0 + freq**2 d_low = np.ones(2 * N + 1) data = [d_low, d_main, d_low] diags = [-1, 0, 1] A = sparse.spdiags(data, diags, 2 * N + 1, 2 * N + 1, format='csc') x = dsolve.spsolve(A, force) uf_ratio[k] = x[-1] return uf_ratio
def Solve(self,fext,spcs): if ( self.Kmat==None ): print 'Kmat not set in FeSolver' return n=np.shape(self.Kmat)[0] tr=0.0 for i in xrange(n): tr += self.Kmat[i,i] beta=tr/(1.0*n) #nspc=len(spcs) Kreac=self.Kmat.diagonal() kappa = self.penfact*beta for ispc in spcs: ii = ispc.gid iv = ispc.dval for jj in xrange(n): fext[jj] = fext[jj] - self.Kmat[jj,ii]*iv for ispc in spcs: ii = ispc.gid self.Kmat[ii,ii] = kappa fext[ii] = kappa*ispc.dval self.Kmat=self.Kmat.tocsr() d = dsolve.spsolve(self.Kmat, fext, use_umfpack=True) for ii in xrange(n): self.Kmat[ii,ii] = Kreac[ii] freac = self.Kmat.dot(d) return [d,freac]
def fesolve2(Kmat,fext,ispc,vspc=None): n=np.shape(Kmat)[0] tr=0.0 for i in xrange(n): tr += Kmat[i,i] beta=tr/(1.0*n) nspc=len(ispc) Kreac=Kmat[ispc,:].tocsr() if vspc==None: vspc=np.zeros((nspc,1)) else: # inhomogenious bc for i in xrange(nspc): ii = ispc[i] iv = vspc[i] for jj in xrange(Kmat.shape[0]): fext[jj] = fext[jj] - Kmat[jj,ii]*iv for i in xrange(nspc): ii = ispc[i] for jj in xrange(n): if ( not(Kmat[ii,jj]==0) ): Kmat[ii,jj] = 0.0 if ( not(Kmat[jj,ii]==0) ): Kmat[jj,ii] = 0.0 Kmat[ii,ii] = beta fext[ii] = beta*vspc[i] Kmat=Kmat.tocsr() d = dsolve.spsolve(Kmat, fext, use_umfpack=True) freac = Kreac.dot(d) return [d,freac]
def n_springs(N, mu, f_vec): """ Compute the ratio $u_N/f_0$ for a chain of $N$ springs. The range of frequencies is given by $[f_{\min}, f_{\max}]$. $\mu$ is the ratio of masses $\mu = m_2/m_1$. """ nfreq = len(f_vec) uf_ratio = np.zeros(nfreq) force = np.zeros(2*N + 1) force[0] = -1.0 for k, freq in enumerate(f_vec): d_main = np.zeros(2*N + 1) d_main[1:-1:2] = -2. + mu*freq**2 d_main[2:-1:2] = -2. + freq**2 d_main[0] = -1.0 + freq**2 d_main[-1] = -1.0 + freq**2 d_low = np.ones(2*N + 1) data = [d_low, d_main, d_low] diags = [-1,0,1] A = sparse.spdiags(data, diags, 2*N+1, 2*N+1, format='csc') x = dsolve.spsolve(A, force) uf_ratio[k] = x[-1] return uf_ratio
def step_elliptical_1d(dx, W, alpha, beta, gamma, left_boundary_condition, left_boundary_condition_value, right_boundary_condition, right_boundary_condition_value): # # Solves 1D elliptical equation on staggered grid # (W(x) u_x)_x - alpha(x) u + gamma(x)*u_x = beta(x) # def boundary_modifier(x, val): return {'Dirichlet': [val, 0, val], 'vonNeuman': [-val, val, -val]}[x] N_intervals = np.size(alpha) - 1 val = np.mean(np.abs(2 * W + dx**2.0 * alpha - gamma * dx)) left_modifier = boundary_modifier(left_boundary_condition, val) right_modifier = boundary_modifier(right_boundary_condition, val) rhs = dx * dx * beta rhs[0] = left_modifier[2] * left_boundary_condition_value rhs[np.size(rhs) - 1] = right_modifier[2] * right_boundary_condition_value A = csc_matrix( spdiags([ np.hstack((W[0:N_intervals - 1], right_modifier[1], 0)), np.hstack( (left_modifier[0], -(W[0:N_intervals - 1] + W[1:N_intervals] + alpha[1:N_intervals] * dx * dx) - (gamma[1:N_intervals] + gamma[0:N_intervals - 1]) / 2.0 * dx, right_modifier[0])), np.hstack( (0, left_modifier[1], W[1:N_intervals] + (gamma[1:N_intervals] + gamma[0:N_intervals - 1]) / 2.0 * dx)) ], [-1, 0, 1], N_intervals + 1, N_intervals + 1)) u = dsolve.spsolve(A, rhs, use_umfpack=True) return u
def step_diffusion_1d(dt, dx, phi, sourceTerm, D, left_boundary_condition, left_boundary_condition_value, right_boundary_condition, right_boundary_condition_value): # # Solves 1D diffusion on staggered grid; give the midpotins only, not the artificial points outside the boundary, they are specified by the given boundary condition. # Input values are dt, dx, phi (solution in the previous time-step) on the nodes, source term on the nodes, diffusion coefficient vector on midpoints (size N+1) # Boundary conditions can be vonNeuman or Dirichlet # def boundary_modifier(x, dx): return {'Dirichlet': [1, 0, 1], 'vonNeuman': [1, -1, dx]}[x] N_intervals = np.size(phi) - 1 rhs = -dx * dx * (phi / dt + sourceTerm) left_modifier = boundary_modifier(left_boundary_condition, dt) right_modifier = boundary_modifier(right_boundary_condition, dt) if left_boundary_condition == 'vonNeuman': rhs[0] = -left_modifier[2] * left_boundary_condition_value elif left_boundary_condition == 'Dirichlet': rhs[0] = left_modifier[2] * left_boundary_condition_value rhs[-1] = right_modifier[2] * right_boundary_condition_value A = csc_matrix( spdiags([ np.hstack((D[0:N_intervals - 1], right_modifier[1], 0)), np.hstack( (left_modifier[0], -(D[0:N_intervals - 1] + D[1:N_intervals] + dx * dx / dt), right_modifier[0])), np.hstack((0, left_modifier[1], D[1:N_intervals])) ], [-1, 0, 1], N_intervals + 1, N_intervals + 1)) phi = dsolve.spsolve(A, rhs, use_umfpack=True) return phi
def Solve(self, fext, spcs): if (self.Kmat == None): print 'Kmat not set in FeSolver' return n = np.shape(self.Kmat)[0] tr = 0.0 for i in xrange(n): tr += self.Kmat[i, i] beta = tr / (1.0 * n) #nspc=len(spcs) Kreac = self.Kmat.diagonal() kappa = self.penfact * beta for ispc in spcs: ii = ispc.gid iv = ispc.dval for jj in xrange(n): fext[jj] = fext[jj] - self.Kmat[jj, ii] * iv for ispc in spcs: ii = ispc.gid self.Kmat[ii, ii] = kappa fext[ii] = kappa * ispc.dval self.Kmat = self.Kmat.tocsr() d = dsolve.spsolve(self.Kmat, fext, use_umfpack=True) for ii in xrange(n): self.Kmat[ii, ii] = Kreac[ii] freac = self.Kmat.dot(d) return [d, freac]
def fesolve2(Kmat, fext, ispc, vspc=None): n = np.shape(Kmat)[0] tr = 0.0 for i in xrange(n): tr += Kmat[i, i] beta = tr / (1.0 * n) nspc = len(ispc) Kreac = Kmat[ispc, :].tocsr() if vspc == None: vspc = np.zeros((nspc, 1)) else: # inhomogenious bc for i in xrange(nspc): ii = ispc[i] iv = vspc[i] for jj in xrange(Kmat.shape[0]): fext[jj] = fext[jj] - Kmat[jj, ii] * iv for i in xrange(nspc): ii = ispc[i] for jj in xrange(n): if (not (Kmat[ii, jj] == 0)): Kmat[ii, jj] = 0.0 if (not (Kmat[jj, ii] == 0)): Kmat[jj, ii] = 0.0 Kmat[ii, ii] = beta fext[ii] = beta * vspc[i] Kmat = Kmat.tocsr() d = dsolve.spsolve(Kmat, fext, use_umfpack=True) freac = Kreac.dot(d) return [d, freac]
def test_singular(self): A = csc_matrix((5,5), dtype='d') b = array([1, 2, 3, 4, 5],dtype='d') with suppress_warnings() as sup: sup.filter(MatrixRankWarning, "Matrix is exactly singular") x = spsolve(A, b) assert_(not np.isfinite(x).any())
def test_singular(self): A = csc_matrix((5, 5), dtype='d') b = array([1, 2, 3, 4, 5], dtype='d') with suppress_warnings() as sup: sup.filter(MatrixRankWarning, "Matrix is exactly singular") x = spsolve(A, b) assert_(not np.isfinite(x).any())
def solve(self): self.populate_matrix_6th_order() if self.uniform else self.populate_matrix() self.populate_vector() self.apply_boundary_conditions() self.mtx = sparse.csr_matrix(self.mtx) self.mtx = self.mtx.astype(np.float64) self.U = dsolve.spsolve(self.mtx, np.array(self.vec), use_umfpack=True)
def test_singular(self): with warnings.catch_warnings(): warnings.simplefilter("ignore", category=MatrixRankWarning) A = csc_matrix((5,5), dtype='d') b = array([1, 2, 3, 4, 5],dtype='d') x = spsolve(A, b, use_umfpack=False) assert_(not np.isfinite(x).any())
def test_sparsity_preservation(self): ident = csc_matrix([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) b = csc_matrix([[0, 1], [1, 0], [0, 0]]) x = spsolve(ident, b) assert_equal(ident.nnz, 3) assert_equal(b.nnz, 2) assert_equal(x.nnz, 2) assert_allclose(x.A, b.A, atol=1e-12, rtol=1e-12)
def test_dtype_cast(self): A_real = scipy.sparse.csr_matrix([[1, 2, 0], [0, 0, 3], [4, 0, 5]]) A_complex = scipy.sparse.csr_matrix([[1, 2, 0], [0, 0, 3], [4, 0, 5 + 1j]]) b_real = np.array([1,1,1]) b_complex = np.array([1,1,1]) + 1j*np.array([1,1,1]) x = spsolve(A_real, b_real) assert_(np.issubdtype(x.dtype, np.floating)) x = spsolve(A_real, b_complex) assert_(np.issubdtype(x.dtype, np.complexfloating)) x = spsolve(A_complex, b_real) assert_(np.issubdtype(x.dtype, np.complexfloating)) x = spsolve(A_complex, b_complex) assert_(np.issubdtype(x.dtype, np.complexfloating))
def test_bmatrix_smoketest(self): Adense = array([[0., 1., 1.], [1., 0., 1.], [0., 0., 1.]]) As = csc_matrix(Adense) random.seed(1234) x = random.randn(3, 4) Bdense = As.dot(x) Bs = csc_matrix(Bdense) x2 = spsolve(As, Bs) assert_array_almost_equal(x, x2.todense())
def test_bvector_smoketest(self): Adense = array([[0., 1., 1.], [1., 0., 1.], [0., 0., 1.]]) As = csc_matrix(Adense) random.seed(1234) x = random.randn(3) b = As * x x2 = spsolve(As, b) assert_array_almost_equal(x, x2)
def start_solving_newton(self): """ Starts solving the problem. """ self.mesh.output_vtk_mesh(self.model_name + "0", [self.current_pressure, self.mesh.get_cell_domain_all()], ["pressure", "domain"]) self.time_step_output(0., 0) m_multipliers = np.ones(self.mesh.get_number_of_cells(), dtype=np.dtype('d')) for time_step in range(1,self.number_of_time_steps+1): current_time = time_step*self.delta_t print(time_step) print("\n") for i in range(100): rhs_current = np.zeros(self.mfd.get_number_of_dof(), dtype=np.dtype('d')) rhs_current += self.rhs_mfd for cell_index in range(self.mesh.get_number_of_cells()): density = -self.ref_pressure density += self.current_pressure[cell_index] density *= self.compressibility density += 1. density *= self.ref_density # We multiply by the inverse of \frac{\rho}{\mu} m_multipliers[cell_index] = self.viscosity/density c_entry = self.compressibility c_entry *= self.porosities[cell_index] c_entry /= self.delta_t c_entry *= self.mesh.get_cell_volume(cell_index) rhs_current[self.mfd.flux_dof+ cell_index] += c_entry*self.current_pressure[cell_index] self.lhs_coo.data[self.c_start+cell_index] = c_entry for [index, cell_index] in enumerate(self.rate_wells): rhs_current[self.mfd.flux_dof+cell_index] += \ self.rate_wells_rate[index] self.mfd.update_m(self.lhs_coo.data[:self.m_x_coo_length], m_multipliers) solution = dsolve.spsolve(self.lhs_coo.tocsr(), rhs_current) print(np.linalg.norm(self.current_pressure-solution[self.mfd.flux_dof:])) self.current_pressure = solution[self.mfd.flux_dof:] self.current_velocity = solution[:self.mfd.flux_dof] if time_step%self.output_frequency == 0: self.mesh.output_vtk_mesh(self.model_name+str(time_step), [self.current_pressure, self.mesh.get_cell_domain_all()], ["pressure", "domain"]) self.time_step_output(current_time, time_step)
def test_bvector_smoketest(self): Adense = matrix([[0.0, 1.0, 1.0], [1.0, 0.0, 1.0], [0.0, 0.0, 1.0]]) As = csc_matrix(Adense) random.seed(1234) x = random.randn(3) b = As * x x2 = spsolve(As, b) assert_array_almost_equal(x, x2)
def test_bmatrix_smoketest(self): Adense = matrix([[0.0, 1.0, 1.0], [1.0, 0.0, 1.0], [0.0, 0.0, 1.0]]) As = csc_matrix(Adense) random.seed(1234) x = random.randn(3, 4) Bdense = As.dot(x) Bs = csc_matrix(Bdense) x2 = spsolve(As, Bs) assert_array_almost_equal(x, x2.todense())
def FDM_implicit(self, bc0=[-1.5, 2., -.5, 0.], bcn=[1.5, -2., .5, 0.], lowerbound=0): """ Calculate one step of the implicit Finite Elements Method for Fick's second law equation. Parameters ---------- bc0 : array_like Parameters for the boundary condition at the 0-th node bcn : array_like Parameters for the boundary condition at the n-th node At the 0-th node, the correspondent linear equation is given by bc0[0]*c[0] + bc0[1]*c[1] + bc0[1]*c[2] = bc0[3]. At the n-th node, the correspondent linear equation is given by bcn[0]*c[-1] + bcn[1]*c[-2] + bcn[2]*c[-3] = bcn[3]. Dirichlet boundary condition is given by bc0/bcn = (1.,0.,0.,c_i). Neumann boundary condition (flux = 0) can be defined either by bc0 (bcn) = [1.5,-2.,.5,0.] or bc0 (bcn) = [1.,-1.,0.,0.] """ self.get_r() self.get_g() dia1_, dia1 = np.zeros(self.n), np.zeros(self.n) dia2_, dia2 = np.zeros(self.n), np.zeros(self.n) dia0 = 1. + 2. * self.r dia1_[:-1], dia1[1:] = -(self.r[1:] - self.g[1:]), -(self.r[:-1] + self.g[:-1]) self._b[:] = self.c # First row of the matrix. Determines the boundary condition at i=0 dia0[0], dia1[1], dia2[2] = bc0[0], bc0[1], bc0[2] # Determines the boundary condition at i=0 self._b[0] = bc0[3] # Last row of the matrix. Determines the boundary condition at i=n dia0[-1], dia1_[-2], dia2_[-3] = bcn[0], bcn[1], bcn[2] # Determines the boundary condition at i=n self._b[-1] = bcn[3] mtx = spdiags([dia2_, dia1_, dia0, dia1, dia2], [-2, -1, 0, 1, 2], self.n, self.n) A = csc_matrix(mtx, dtype=np.float64) # Solve the linear system A*c = b self._c = dsolve.spsolve(A, self._b, use_umfpack=True) if self._c[0] < lowerbound or self._c[-1] < lowerbound: return True self.c[:] = self._c
def tick_fem_sparse(self,dt): """ tick Finite Element Model simulation by dt hours using sparse stiffness matrix """ # initialise stiffness matrix self.stiffness=sparse.lil_matrix((self.numnodes*self.NUMDOF,self.numnodes*self.NUMDOF)) #self.stiffness=numpy.zeros((self.numnodes*self.NUMDOF,self.numnodes*self.NUMDOF)) # for each wall, add a component to the stiffness matrix for wall in self.walls: L=wall.get_length() Ra = self.FEM_E*self.FEM_S/L/dt Rf = self.FEM_E*self.FEM_I/(L**3)/dt M =numpy.array(((Ra , 0 , 0 , -Ra , 0 , 0 ), (0 , Rf*12 , -Rf*6*L , 0 , -Rf*12 , -Rf*6*L ), (0 , -Rf*6*L , Rf*4*L**2 , 0 , Rf*6*L , Rf*2*L**2 ), (-Ra , 0 , 0 , Ra , 0 , 0 ), (0 , -Rf*12 , Rf*6*L , 0 , Rf*12 , Rf*6*L ), (0 , -Rf*6*L , Rf*2*L**2 , 0 , Rf*6*L , Rf*4*L**2 ))) # rotate from local coord frame to global theta=wall.get_angle() c=wall.get_cosine() #math.cos(theta) s=wall.get_sine() #math.sin(theta) R=numpy.array(((c,-s,0), (s,c,0), (0,0,1))) R=numpy.hstack((R,R)) R=numpy.vstack((R,R)) MR=R*M*R.transpose() # add component to stiffness matrix self.stiffness[wall.node0.id*3:wall.node0.id*3+3,wall.node0.id*3:wall.node0.id*3+3]+=sparse.lil_matrix(MR[0:3,0:3]) self.stiffness[wall.node1.id*3:wall.node1.id*3+3,wall.node1.id*3:wall.node1.id*3+3]+=sparse.lil_matrix(MR[3:6,3:6]) self.stiffness[wall.node0.id*3:wall.node0.id*3+3,wall.node1.id*3:wall.node1.id*3+3]+=sparse.lil_matrix(MR[0:3,3:6]) self.stiffness[wall.node1.id*3:wall.node1.id*3+3,wall.node0.id*3:wall.node0.id*3+3]+=sparse.lil_matrix(MR[3:6,0:3]) #print_mat(self.stiffness) # apply turgor force self.nodeforcearray=numpy.zeros(self.nodeforcearray.shape) for cell in self.cells.values(): cell.apply_turgor(0.01) #self.cells.values()[0].apply_turgor(0.001) # solve for displacement (find d in S.d=f) # fixing first node f=self.nodeforcearray[3:] s=self.stiffness[3:,3:] #d=linalg.solve(s,f) d=linsolve.spsolve(s.tocsr(),f) self.nodedisparray[3:]+=d.reshape(d.shape[0],1)
def ResoLpl(f22D,N,M): global dx global dy global LAP2 f2 = f22D.reshape(N*M) T = spsolve(LAP2,f2) # Solving the linear system u2D=T.reshape(N,M) return u2D
def ResoLpl(f22D, N, M): global dx global dy global LAP2 f2 = f22D.reshape(N * M) T = spsolve(LAP2, f2) # Solving the linear system u2D = T.reshape(N, M) return u2D
def solveHJB(mu1, mu2, sigma, lambda1, lambda2, Kb, Ks, rho, T): Ny = 1000 Nt = 200 beta = 1e7 tol = 1e-8 psell = [] pbuy = [] h = 1.0/Ny dt = T*1.0/Nt y = np.array([h*i for i in range(Ny+1)]) v = np.array([np.log(1-Ks) for i in range(Ny+1)]) vnew = [1 for i in range(Ny+1)] c2 = 0.5*np.array([((mu1-mu2)*x*(1-x)/sigma)**2 for x in y])/h/h c1 = (-(lambda1+lambda2)*y+lambda2)/h c0 = 0 f0= (mu1-mu2)*y+(mu2-rho-sigma**2/2) left = -c2+c1*(c1<0) middle = 1/dt+2*c2+np.abs(c1)-c0; right = -c2-c1*(c1>0) for t in range(int(T/dt)): counter = 0 vn = v while True: counter = counter+1 Indi1 = beta*(v-(np.log(1+Kb))>0); Indi2 = beta*((np.log(1-Ks))-v>0); b = vn/dt+(np.log(1+Kb))*Indi1+(np.log(1-Ks))*Indi2+f0; A = scipy.sparse.spdiags(np.array([right, middle+Indi1+Indi2, left]),[-1,0,1],Ny+1,Ny+1).T b[0] = A[0,0]*np.log(1-Ks) A[0,1] = 0 b[Ny] = A[Ny,Ny]*np.log(1+Kb) A[Ny,Ny-1]=0 vnew = dsolve.spsolve(A,b,use_umfpack=False) if (np.linalg.norm(vnew-v)*1.0/np.linalg.norm(v))<tol: break v = vnew uu = vnew temp = np.where(uu-(np.log(1+Kb))>=0)[0] pbuy.append(y[temp[0]]) temp = np.where(uu-(np.log(1-Ks))<=0)[0] psell.append(y[temp[len(temp)-1]]) return [pbuy[Nt-1], psell[Nt-1]]
def solve_linear_system(self, A=None, use_Wendland_compsupp=True, regularisation=None, save_Gram_rows=[False,None], verbose=False): """ Solves the linear system defined by generalised interpolation problem :param A: Interpolation matrix :param use_Wendland_compsupp: When A is not given and the kernel is Wendland kernel, use the compact support to speed up population of interpolation matrix. :param save_Gram_rows: Option to save Gram matrix row-by-row - 2nd list element is for path (currently only for gram_Wendland()) :return: solution vector stored in self.coefficients """ #TODO: Implement save_Gram_rows for other gram functions if regularisation!=None: self.regularisation=regularisation # Check the Data list is not empty data_empty = True for data_object in self.data_points: if data_object.numpoints > 0: data_empty = False if data_empty == True: print("ERROR: Cannot solve linear system - no data points") exit(1) self._check_for_empty_Data() if A==None: if verbose: print('making Gram matrix') if use_Wendland_compsupp==False or not isinstance(self.K, Wendland): if verbose: print('using gram') self.gram = gram(self) else: if verbose: print('using gram_Wendland') self.gram = gram_Wendland(self, save_rows=save_Gram_rows) if verbose: print('finished making Gram matrix') else: self._check_gram(A) self.gram = A #if self.regularisation != 0: # print('Adding regularisation: ', self.regularisation) # self.gram = self.gram + (self.regularisation * sparse.identity(self.gram.shape[0])) if verbose: print('solving linear system') self.beta = np.array([]) for data_object in self.data_points: #self.dim = data_object.points.shape[0] self.beta = np.hstack((self.beta, data_object.targets)) if sparse.issparse(self.gram): if not isinstance(self.gram, sparse.csr.csr_matrix): self.gram = sparse.csr_matrix(self.gram) self.coefficients = spsolve(self.gram + (self.regularisation * sparse.identity(self.gram.shape[0])), self.beta) else: self.coefficients = np.linalg.solve(self.gram + (self.regularisation * sparse.identity(self.gram.shape[0])), self.beta) if verbose: print('finished linear system')
def test_sparsity_preservation(self): ident = csc_matrix([ [1, 0, 0], [0, 1, 0], [0, 0, 1]]) b = csc_matrix([ [0, 1], [1, 0], [0, 0]]) x = spsolve(ident, b) assert_equal(ident.nnz, 3) assert_equal(b.nnz, 2) assert_equal(x.nnz, 2) assert_allclose(x.A, b.A, atol=1e-12, rtol=1e-12)
def solvePoissonProblem_sparse(mesh, densityValues): """ Solve a Poisson problem on the mesh, using sparse matrix operations. This will be nearly identical to the dense method. The results should be stored on the vertices in a variable named 'solutionVal'. densityValues is a dictionary mapping {vertex ==> value} that specifies any densities. The density is implicitly zero at every vertex not in this dictionary. Note: Be sure to look at the notes on the github wiki about sparse matrix computation in Python. When you run this program with 'python Assignment3.py part2 path/to/your/mesh.obj', you will get to click on vertices to specify density conditions. See the assignment document for more details. """ index_map = enumerateVertices(mesh) L = buildLaplaceMatrix_sparse(mesh, index_map) M = buildMassMatrix_dense(mesh, index_map) #M <= 2D rho = np.zeros((len(mesh.verts)), float) for key in densityValues: #index_val = index_map[key] print 'key dual area = ', key.dualArea rho[index_map[key]] = densityValues[key] #*key.dualArea # convert to sparse matrix (CSR method) #Lsparse = csr_matrix(L) #iL = np.linalg.inv(L) #sol_vec = np.dot(iL,rho) #sol_vec = np.linalg.solve(L, rho) #sol_vec = linsolve.spsolve(L, rho) #sol_vec = linsolve.spsolve(L, np.dot(M,rho) ) #sol_vec = dsolve.spsolve(L, rho, use_umfpack=False) sol_vec = dsolve.spsolve(L, np.dot(M, rho), use_umfpack=True) for vert in mesh.verts: key = index_map[vert] #print 'TLM sol_vec = ',sol_vec[key] vert.solutionVal = sol_vec[key] if rho[key]: vert.densityVal = rho[key] else: vert.densityVal = 0. return
def computeCoExactComponent(self, omega): print 'system 2, Beta' #solve system 2 for delta Beta # page 117-118-119 # scipy.linalg.lu print 'build LHS...' t0 = time.time() LHS = self.d1.dot(self.ihodge1) #ss = np.shape(LHS)[0] LHS = csc_matrix(LHS) LHS = LHS.dot(self.d1T) #LHS = LHS + 1.e-8 * csc_matrix(np.identity(ss,float)) # tSolve = time.time() - t0 print("...sparse Beta LHS build completed.") print("Beta LHS build took {:.5f} seconds.".format(tSolve)) print 'build RHS...' t0 = time.time() #RHS = np.matmul(d1,omega) RHS = self.d1.dot(omega) tSolve = time.time() - t0 print("...sparse Beta RHS completed.") print("Beta RHS build took {:.5f} seconds.".format(tSolve)) print 'solve' Beta = dsolve.spsolve(LHS, RHS, use_umfpack=True) #LU decomposition: #DLU = scipy.sparse.linalg.splu(LHS) #Beta = DLU.solve(RHS) # print 'solve complete, transform' # Beta = np.dot(ihodge2,Beta) # print 'transform complete, Beta complete' # # store exact, coexact, harmonic components on the mesh edges. print 'decomposition field to mesh' #now pull back to a 1 form using the codifferential *d* # *d* Beta => *d0* #Beta = np.dot(hodge0,np.dot(d0, # np.dot(hodge2,Beta))) # the easy way: Beta = self.d1T.dot(Beta) print 'solve complete, transform Beta' Beta = np.dot(self.ihodge1, Beta) print 'transform complete, Beta complete' return Beta
def test_singular_gh_3312(self): # "Bad" test case that leads SuperLU to call LAPACK with invalid # arguments. Check that it fails moderately gracefully. ij = np.array([(17, 0), (17, 6), (17, 12), (10, 13)], dtype=np.int32) v = np.array([0.284213, 0.94933781, 0.15767017, 0.38797296]) A = csc_matrix((v, ij.T), shape=(20, 20)) b = np.arange(20) try: # should either raise a runtimeerror or return value # appropriate for singular input x = spsolve(A, b) assert_(not np.isfinite(x).any()) except RuntimeError: pass
def test_example_comparison(self): row = array([0, 0, 1, 2, 2, 2]) col = array([0, 2, 2, 0, 1, 2]) data = array([1, 2, 3, -4, 5, 6]) sM = csr_matrix((data, (row, col)), shape=(3, 3), dtype=float) M = sM.todense() row = array([0, 0, 1, 1, 0, 0]) col = array([0, 2, 1, 1, 0, 0]) data = array([1, 1, 1, 1, 1, 1]) sN = csr_matrix((data, (row, col)), shape=(3, 3), dtype=float) N = sN.todense() sX = spsolve(sM, sN) X = scipy.linalg.solve(M, N) assert_array_almost_equal(X, sX.todense())
def test_twodiags(self): A = spdiags([[1, 2, 3, 4, 5], [6, 5, 8, 9, 10]], [0, 1], 5, 5) b = array([1, 2, 3, 4, 5]) # condition number of A cond_A = norm(A.todense(), 2) * norm(inv(A.todense()), 2) for t in ['f', 'd', 'F', 'D']: eps = finfo(t).eps # floating point epsilon b = b.astype(t) for format in ['csc', 'csr']: Asp = A.astype(t).asformat(format) x = spsolve(Asp, b) assert_(norm(b - Asp * x) < 10 * cond_A * eps)
def test_example_comparison(self): row = array([0,0,1,2,2,2]) col = array([0,2,2,0,1,2]) data = array([1,2,3,-4,5,6]) sM = csr_matrix((data,(row,col)), shape=(3,3), dtype=float) M = sM.todense() row = array([0,0,1,1,0,0]) col = array([0,2,1,1,0,0]) data = array([1,1,1,1,1,1]) sN = csr_matrix((data, (row,col)), shape=(3,3), dtype=float) N = sN.todense() sX = spsolve(sM, sN) X = scipy.linalg.solve(M, N) assert_array_almost_equal(X, sX.todense())
def test_twodiags(self): A = spdiags([[1, 2, 3, 4, 5], [6, 5, 8, 9, 10]], [0, 1], 5, 5) b = array([1, 2, 3, 4, 5]) # condition number of A cond_A = norm(A.todense(),2) * norm(inv(A.todense()),2) for t in ['f','d','F','D']: eps = finfo(t).eps # floating point epsilon b = b.astype(t) for format in ['csc','csr']: Asp = A.astype(t).asformat(format) x = spsolve(Asp,b) assert_(norm(b - Asp*x) < 10 * cond_A * eps)
def test_example_comparison(self): with warnings.catch_warnings(): warnings.simplefilter("ignore", category=SparseEfficiencyWarning) row = array([0,0,1,2,2,2]) col = array([0,2,2,0,1,2]) data = array([1,2,3,-4,5,6]) sM = csr_matrix((data,(row,col)), shape=(3,3), dtype=float) M = sM.todense() row = array([0,0,1,1,0,0]) col = array([0,2,1,1,0,0]) data = array([1,1,1,1,1,1]) sN = csr_matrix((data, (row,col)), shape=(3,3), dtype=float) N = sN.todense() sX = spsolve(sM, sN) X = scipy.linalg.solve(M, N) assert_array_almost_equal(X, sX.todense())
def SchurPCD2(Mass,L,F, backend): Mass = Mass.sparray() F = F.sparray() L = L.sparray() X = np.empty_like(Mass.todense()) print X.shape Mass = Mass+ 1e-4*sp.identity(Mass.shape[0]) Mass = Mass.toarray() print np.array(Mass[:,0]).T for i in range(X.shape[1]): print Mass[i,:].T X[i,:] = spsolve(F,Mass[:,i]) # print Schur.todense() Schur = L*X print Schur.diagonal() if backend == "PETSc": return PETSc.Mat().createAIJ(size=Schur.transpose().shape,csr=(Schur.transpose().indptr, Schur.transpose().indices, Schur.transpose().data)) else: return Schur.transpose()
def test_example_comparison(self): with warnings.catch_warnings(): warnings.simplefilter("ignore", category=SparseEfficiencyWarning) row = array([0, 0, 1, 2, 2, 2]) col = array([0, 2, 2, 0, 1, 2]) data = array([1, 2, 3, -4, 5, 6]) sM = csr_matrix((data, (row, col)), shape=(3, 3), dtype=float) M = sM.todense() row = array([0, 0, 1, 1, 0, 0]) col = array([0, 2, 1, 1, 0, 0]) data = array([1, 1, 1, 1, 1, 1]) sN = csr_matrix((data, (row, col)), shape=(3, 3), dtype=float) N = sN.todense() sX = spsolve(sM, sN) X = scipy.linalg.solve(M, N) assert_array_almost_equal(X, sX.todense())
def solve(self): ''' Solve the PDE. ''' maxiter = 50 trace = True for iter in xrange(0, maxiter): self.state.clearFunJac() self.calcFunJac() self.state.assembleJac() flagConv, err = self.checkConv() if trace: print iter, err if flagConv: break dx = np.negative(dsolve.spsolve(self.state.J, self.state.b)) self.state.dx = self.dampStep(dx) self.state.x = np.add(self.state.x, self.state.dx)
def solve(self): ''' Solve the PDE. ''' maxiter=50 trace = True for iter in xrange(0,maxiter): self.state.clearFunJac() self.calcFunJac() self.state.assembleJac() flagConv, err = self.checkConv() if trace: print iter, err if flagConv: break dx = np.negative(dsolve.spsolve(self.state.J, self.state.b)) self.state.dx = self.dampStep(dx) self.state.x = np.add(self.state.x, self.state.dx)
def update_pressure(self): """ Updates the pressure equation explicitly """ m_multipliers = np.ones(self.mesh.get_number_of_cells()) rhs_current = np.zeros(self.mfd.get_number_of_dof()) rhs_current += self.rhs_mfd for cell_index in range(self.mesh.get_number_of_cells()): density = -self.ref_pressure density += self.current_pressure[cell_index] density *= self.compressibility density += 1. density *= self.ref_density # We multiply by the inverse of \frac{\rho}{\mu} m_multipliers[cell_index] = self.viscosity/density c_entry = self.compressibility c_entry *= self.porosities[cell_index] c_entry /= self.delta_t c_entry *= self.mesh.get_cell_volume(cell_index) rhs_current[self.mesh.get_number_of_faces()+ cell_index] += c_entry*self.current_pressure[cell_index] self.lhs_coo.data[self.c_start+cell_index] = c_entry for [index, cell_index] in enumerate(self.rate_wells): rhs_current[self.mesh.get_number_of_faces()+cell_index] += \ self.rate_wells_rate[index] self.mfd.update_m(self.lhs_coo.data[:self.m_x_coo_length], m_multipliers) solution = dsolve.spsolve(self.lhs_coo.tocsr(), rhs_current) self.prev_pressure = self.current_pressure self.current_pressure = solution[self.mesh.get_number_of_faces():] self.current_velocity = solution[:self.mesh.get_number_of_faces()]
def update_pressure(self): """ Updates the pressure equation explicitly """ m_multipliers = np.ones(self.mesh.get_number_of_cells()) rhs_current = np.zeros(self.mfd.get_number_of_dof()) rhs_current += self.rhs_mfd for cell_index in range(self.mesh.get_number_of_cells()): density = -self.ref_pressure density += self.current_pressure[cell_index] density *= self.compressibility density += 1. density *= self.ref_density # We multiply by the inverse of \frac{\rho}{\mu} m_multipliers[cell_index] = self.viscosity / density c_entry = self.compressibility c_entry *= self.porosities[cell_index] c_entry /= self.delta_t c_entry *= self.mesh.get_cell_volume(cell_index) rhs_current[ self.mesh.get_number_of_faces() + cell_index] += c_entry * self.current_pressure[cell_index] self.lhs_coo.data[self.c_start + cell_index] = c_entry for [index, cell_index] in enumerate(self.rate_wells): rhs_current[self.mesh.get_number_of_faces()+cell_index] += \ self.rate_wells_rate[index] self.mfd.update_m(self.lhs_coo.data[:self.m_x_coo_length], m_multipliers) solution = dsolve.spsolve(self.lhs_coo.tocsr(), rhs_current) self.prev_pressure = self.current_pressure self.current_pressure = solution[self.mesh.get_number_of_faces():] self.current_velocity = solution[:self.mesh.get_number_of_faces()]
def SchurPCD2(Mass, L, F, backend): Mass = Mass.sparray() F = F.sparray() L = L.sparray() X = np.empty_like(Mass.todense()) print X.shape Mass = Mass + 1e-4 * sp.identity(Mass.shape[0]) Mass = Mass.toarray() print np.array(Mass[:, 0]).T for i in range(X.shape[1]): print Mass[i, :].T X[i, :] = spsolve(F, Mass[:, i]) # print Schur.todense() Schur = L * X print Schur.diagonal() if backend == "PETSc": return PETSc.Mat().createAIJ(size=Schur.transpose().shape, csr=(Schur.transpose().indptr, Schur.transpose().indices, Schur.transpose().data)) else: return Schur.transpose()
def solveDiffusion(nx, ny, inputd): # Create the DA and setup the problem if inputd.kspType == 'sd': U = 0.0 self = 0.0 [M, R, row, col, val] = build_A(inputd, self) tic = PETSc.Log().getTime() U = dsolve.spsolve(M, R, use_umfpack=True) #Direct solver toc = PETSc.Log().getTime() its = 1.0 rnorm = np.linalg.norm(M * U - R) pde = 0.0 else: da = PETSc.DA().create([nx, ny], stencil_width=1, boundary_type=('ghosted', 'ghosted')) pde = diffusion2D(da) pde.setupSolver(inputd) print "Solving using", pde.solver_name #Now solve tic = PETSc.Log().getTime() pde.solve(pde.b, pde.x) toc = PETSc.Log().getTime() its = pde.ksp.getIterationNumber() rnorm = pde.ksp.getResidualNorm() M = 0.0 U = M # output performance/convergence information time = toc - tic timePerGrid = time / nx / ny #rnorm = np.linalg.norm(M*U-R) print "Nx Ny its ||r||_2 ElapsedTime (s) Elapsed Time/N_tot" print nx, ny, its, rnorm, time, timePerGrid return pde, time, timePerGrid, its, rnorm, U, M
def n_springs(N, f_vec): """ Compute the ratio $u_N/f_0$ for a chain of $N$ springs. The range of frequencies is given by $[f_{\min}, f_{\max}]$. """ nfreq = len(f_vec) uf_ratio = np.zeros(nfreq) for k, freq in enumerate(f_vec): d_main = -2.0 * np.ones(N) + freq**2 d_main[0] = -1.0 + freq**2 d_main[-1] = -1.0 + freq**2 d_low = np.ones(N) data = [d_low, d_main, d_low] diags = [-1, 0, 1] A = sparse.spdiags(data, diags, N, N, format='csc') force = np.zeros(N) force[0] = -1.0 x = dsolve.spsolve(A, force) uf_ratio[k] = x[-1] return uf_ratio
def test_new_gram(self): self._check_for_empty_Data() start = time.time() print('making sparse gram') self.sparse_gram = gram_Wendland_sparse(self, self.io.dir + '/Gram matrix') #only for COPAN Interpolant objects print('finished sparse gram') end_sparse = time.time() print('making Gram with gram() function') self.gram = gram(self) print('finished gram') end_gram = time.time() print('making Gram with gram_Wendland function') self.gram_Wendland = gram_Wendland(self) print('finished gram_Wendland') end_gram_Wendland = time.time() print('Time for sparse: ', end_sparse - start) print('Time for gram: ', end_gram - end_sparse) print('Time for gram_Wendland: ', end_gram_Wendland - end_gram) print('type(self.sparse_gram) = ', type(self.sparse_gram)) print('Difference in norm between gram and sparse_gram: ', np.linalg.norm(self.gram - self.sparse_gram.toarray())) print('Difference in norm between gram_Wendland and sparse_gram: ', np.linalg.norm(self.gram_Wendland - self.sparse_gram.toarray())) for data_object in self.data_points: #self.dim = data_object.points.shape[0] self.beta = np.hstack((self.beta, data_object.targets)) self.coefficients = np.linalg.solve(self.gram_Wendland, self.beta) self.coefficients2 = spsolve(self.sparse_gram, self.beta) print('Difference in coeffs between gram_Wendland and sparse_gram: ', np.linalg.norm(self.coefficients - self.coefficients2))
def update_state(self): Ah = self.Ah J = self.J self.calculate_f() b = self.to1d(self.F) u = dsolve.spsolve(Ah, b) z = np.empty([J + 2, J + 2]) for i in range(0, J + 2): for j in range(0, J + 2): n = j + J * (i - 1) # Going from two indices to one if i == 0 or i == J + 1: z[i, j] = 0.0 if j == 0 or j == J + 1: z[i, j] = 0.0 if i > 0 and j > 0 and i < J + 1 and j < J + 1: z[i, j] = u[n - 1] # elements of u are numbered starting at 0 self.state = z
def n_springs(N, f_vec): """ Compute the ratio $u_N/f_0$ for a chain of $N$ springs. The range of frequencies is given by $[f_{\min}, f_{\max}]$. """ nfreq = len(f_vec) uf_ratio = np.zeros(nfreq) for k, freq in enumerate(f_vec): d_main = -2.0*np.ones(N) + freq**2 d_main[0] = -1.0 + freq**2 d_main[-1] = -1.0 + freq**2 d_low = np.ones(N) data = [d_low, d_main, d_low] diags = [-1,0,1] A = sparse.spdiags(data, diags, N, N, format='csc') force = np.zeros(N) force[0] = -1.0 x = dsolve.spsolve(A, force) uf_ratio[k] = x[-1] return uf_ratio
def test_ndarray_support(self): A = array([[1., 2.], [2., 0.]]) x = array([[1., 1.], [0.5, -0.5]]) b = array([[2., 0.], [2., 2.]]) assert_array_almost_equal(x, spsolve(A, b))
def SolPhaseField(FemInf,MatInf,MacroInf): Node_xy = FemInf.Node_xy Elem = FemInf.Elem Hmax = FemInf.Hmax GcI = MatInf.GcI Lc = MatInf.Lc Nnode = FemInf.Nnode Nelem = FemInf.Nelem NPE = FemInf.Npoint # Node Number per element NGP = FemInf.Ngauss # Number of Gauss Point per element w,r,s,t = QuadraturePoint() Kg_irow = np.zeros((6*6*Nelem,),dtype = np.int) Kg_icol = np.zeros((6*6*Nelem,),dtype = np.int) Kg_V = np.zeros((6*6*Nelem,),dtype = np.float) K_g_index = 0 Fn = np.zeros((Nnode),dtype=np.float) for ielement in range(Nelem): Node_xy_e = np.zeros((6,2),dtype=np.float) for inode in range(NPE): Node_xy_e[inode,:] = Node_xy[Elem[ielement,inode+1]-1,1:3] Eldof = np.zeros((NPE,),dtype=np.int) for inode in range(NPE): Eldof[inode] = Elem[ielement,inode+1]-1 K1_e = np.zeros((6,6),dtype=np.float) K2_e = np.zeros((6,6),dtype=np.float) Fn_e = np.zeros((6,),dtype=np.float) for igauss in range(NGP): dNdr = np.array([[4.*r[igauss]-1., 0., -3.+4.*(r[igauss]+s[igauss]), 4.*s[igauss], -4.*s[igauss], 4.-8.*r[igauss]- 4.*s[igauss]], [ 0., 4.*s[igauss]-1., -3.+4.*(r[igauss]+s[igauss]), 4.*r[igauss], 4.-4.*r[igauss]- 8.*s[igauss], -4.*r[igauss]]],dtype=np.float) J = np.dot(dNdr,Node_xy_e) detJ = J[0,0]*J[1,1]-J[1,0]*J[0,1] invJ = np.array([[ J[1,1], -1.*J[0,1]], [-1.*J[1,0], J[0,0]]])/detJ dNdx = np.dot(invJ,dNdr) Bs_e = dNdx Ns_e = np.matrix([(2.*r[igauss]-1.)*r[igauss], (2.*s[igauss]-1.)*s[igauss], (2.*t[igauss]-1.)*t[igauss], 4.*r[igauss]*s[igauss], 4.*s[igauss]*t[igauss], 4.*t[igauss]*r[igauss]]) K1_e = K1_e + w[igauss]*detJ*(Ns_e.T*Ns_e)*(Hmax[ielement,igauss]+GcI/4./Lc) Ndx=np.matrix(Bs_e[0,:]) Ndy=np.matrix(Bs_e[1,:]) K2_e = K2_e + w[igauss]*detJ*(Ndx.T*Ndx+Ndy.T*Ndy)*GcI*Lc Fn_e = Fn_e + w[igauss]*detJ*1.*Hmax[ielement,igauss]*Ns_e for i in range(6): Fn[Eldof[i]] = Fn[Eldof[i]] + Fn_e[0,i] for j in range(6): Kg_irow[K_g_index] = Eldof[i] Kg_icol[K_g_index] = Eldof[j] Kg_V [K_g_index] = K1_e[i,j] + K2_e[i,j] K_g_index = K_g_index + 1 K_g = sparse.coo_matrix((Kg_V,(Kg_irow,Kg_icol)),shape=(Nnode,Nnode)) K_g = K_g.tocsc() Phase = dsolve.spsolve(K_g,Fn,use_umfpack=True) FemInf.Phase = Phase return FemInf
def update_pressure(self, time_step): """ Solve the pressure system for p_o. self.current_p_o and self.current_u_t are considered the pressure and velocity at time n, and routine computes these quantities for time n+1. """ # po_k, ut_k are the current newton iteration approximations # to pressure and velocity. po_k = np.array(self.current_p_o) ut_k = np.array(self.current_u_t) newton_residual = 100. newton_step = 0 while abs(newton_residual > self.newton_threshold): current_total_mobility = self.water_mobility(self.current_s_w, po_k) current_total_mobility += self.oil_mobility(self.current_s_w, po_k) current_total_mobility = 1./current_total_mobility current_c_matrix = self.ref_density_water*self.current_s_w current_c_matrix *= self.compressibility_water current_c_matrix += self.ref_density_oil*(self.compressibility_oil *(1.-self.current_s_w)) current_c_matrix *= self.porosities current_c_matrix *= \ self.mesh.cell_volume[:self.mesh.get_number_of_cells()] current_c_matrix /= self.delta_t self.mfd.update_m(self.lhs_coo.data[:self.m_x_coo_length], current_total_mobility) for (cell_index, pressure_pi) in zip(self.pressure_wells, self.pressure_wells_pi): current_c_matrix[cell_index] += \ pressure_pi*1./current_total_mobility[cell_index] self.lhs_coo.data[self.c_start:self.c_end] = current_c_matrix lhs = self.lhs_coo.tocsr() ## J(x_n)(x_{n+1}-x_n) = -F(x_n) ## This line applies F(x_n) ut_k_po_k_combo = np.concatenate((ut_k, po_k)) rhs = -self.mfd.build_rhs() rhs += lhs.dot(ut_k_po_k_combo) f2sum_l = np.ones(self.mesh.get_number_of_cells()) f2sum_l *= self.ref_density_water*self.current_s_w f2sum_l *= self.porosities/self.delta_t f2sum_l *= self.mesh.cell_volume[:self.mesh.get_number_of_cells()] f2sum2_l = np.ones(self.mesh.get_number_of_cells()) f2sum2_l *= self.ref_density_oil f2sum2_l *= 1.-self.current_s_w f2sum2_l *= self.porosities/self.delta_t f2sum2_l *= self.mesh.cell_volume[:self.mesh.get_number_of_cells()] f2sum3_l = np.zeros(self.mesh.get_number_of_cells()) f2sum3_l += self.ref_density_water*(1.+self.compressibility_water* (self.current_p_o)) f2sum3_l *= self.current_s_w f2sum3_l += self.ref_density_oil*\ (1+self.compressibility_oil*self.current_p_o)*\ (1.-self.current_s_w) f2sum3_l *= self.porosities/self.delta_t f2sum3_l *= self.mesh.cell_volume[:self.mesh.get_number_of_cells()] rhs[self.mfd.flux_dof:] += f2sum_l rhs[self.mfd.flux_dof:] += f2sum2_l rhs[self.mfd.flux_dof:] -= f2sum3_l for (well_index, cell_index) in enumerate(self.rate_wells): rhs[cell_index+self.mfd.flux_dof] += \ -self.get_well_rate_water(well_index) rhs[cell_index+self.mfd.flux_dof] += \ -self.get_well_rate_oil(well_index) for (cell_index, bhp, pressure_pi) in zip(self.pressure_wells, self.pressure_wells_bhp, self.pressure_wells_pi): rhs[cell_index+self.mfd.flux_dof] -= \ pressure_pi*bhp*1./current_total_mobility[cell_index] newton_residual = np.linalg.norm(rhs)/float(len(rhs)) if newton_residual > self.newton_threshold: if self.solver == 0: self.newton_solution = dsolve.spsolve(lhs, -rhs) delta_po_k = self.newton_solution[self.mfd.flux_dof:] delta_ut_k = self.newton_solution[:self.mfd.flux_dof] if self.solver == 1: self.mfd.update_m(self.m_coo.data, current_total_mobility) m_csr = self.m_coo.tocsr() self.m_petsc.createAIJWithArrays(size=m_csr.shape, csr=(m_csr.indptr, m_csr.indices, m_csr.data)) self.m_petsc.setUp() self.m_petsc.assemblyBegin() self.m_petsc.assemblyEnd() self.c_coo.data = current_c_matrix c_csr = self.c_coo.tocsr() self.c_petsc.createAIJWithArrays( size=(self.mesh.get_number_of_cells(), self.mesh.get_number_of_cells()), csr=(c_csr.indptr, c_csr.indices, c_csr.data)) self.c_petsc.setUp() self.c_petsc.assemblyBegin() self.c_petsc.assemblyEnd() m_diag = m_csr.diagonal() m_diag = 1./m_diag m_diag = sparse.csr_matrix((m_diag, (list(range(self.mfd.flux_dof)), list(range(self.mfd.flux_dof))))) pc_matrix = -self.div_csr.dot(m_diag.dot(self.div_t_csr)) pc_matrix += c_csr pc_matrix.sort_indices() self.pc_petsc = PETSc.Mat() self.pc_petsc.create(PETSc.COMM_WORLD) self.pc_petsc.createAIJWithArrays( size=(self.mesh.get_number_of_cells(), self.mesh.get_number_of_cells()), csr=(pc_matrix.indptr, pc_matrix.indices, pc_matrix.data)) self.pc_petsc.assemblyBegin() self.pc_petsc.assemblyEnd() self.schur_mat.set_c(self.c_petsc) self.schur_mat.update_solver() x, y = self.c_petsc.getVecs() df1, f1 = self.m_petsc.getVecs() f1.setArray(rhs[:self.mfd.flux_dof]) self.schur_mat.ksp.solve(f1, df1) df1 = self.div_coo.dot(df1) temp1, temp2 = self.c_petsc.getVecs() temp1.setArray(np.ones(self.mesh.get_number_of_cells())) self.schur_mat.mult(None, temp1, temp2) x.setArray(df1-rhs[self.mfd.flux_dof:]) self.ksp.setOperators(self.schur_petsc, self.pc_petsc) self.ksp.solve(x, y) if newton_step == 1: self.last_solution = np.array(y.getArray()) delta_po_k = y f1_minvp, delta_ut_k = self.m_petsc.getVecs() f1_minvp.setArray(-rhs[:self.mfd.flux_dof]- self.div_t_coo.dot(y.getArray())) self.schur_mat.ksp.solve(f1_minvp, delta_ut_k) delta_po_k = delta_po_k.getArray() delta_ut_k = delta_ut_k.getArray() po_k += delta_po_k ut_k += delta_ut_k print("\t\t", newton_step, newton_residual) newton_step += 1 if newton_step > self.newton_step_max: 1/0 self.previous_p_o = np.array(self.current_p_o) self.previous_u_t = np.array(self.current_u_t) self.current_p_o = po_k self.current_u_t = ut_k
def fischer_newton(A, b, x, max_iter=0, tol_rel=0.00001, tol_abs=np.finfo(np.float64).eps*10, solver='perturbation', profile=True): """ Copyright 2012, Michael Andersen, DIKU, michael (at) diku (dot) dk """ # Human readable dictionary of exit messages msg = {1 : 'preprocessing', # flag = 1 2 : 'iterating', # flag = 2 3 : 'relative', # flag = 3 4 : 'absolute', # flag = 4 5 : 'stagnation', # flag = 5 6 : 'local minima', # flag = 6 7 : 'nondescent', # flag = 7 8 : 'maxlimit', # flag = 8 } # We use N as a reference for the usage of asserts throughout the # program. We assume that everything is column vector of shape # (N,1) if not the asserts will catch them. N = np.size(b) flag = 1 assert x.shape == (N,1), 'x0 is not a column vector, it has shape: ' + repr(x.shape) assert A.shape == (N,N), 'A is not a square matrix, it has shape: ' + repr(A.shape) assert b.shape == (N,1), 'b is not a column vector, it has shape: ' + repr(b.shape) if max_iter == 0: max_iter = np.floor(N/2.0) # Ensure sane values max_iter = max(max_iter,1) # Rest of the value should be sane ##### Magic constants ##### h = 1e-7 alpha = 0.5 beta = 0.001 gamma = 1e-28 eps = np.finfo(np.float64).eps rho = np.finfo(np.float64).eps gmres_tol = 10*eps ##### Warm start of FN using Blocked Gauss-Seidel from PyAMG ##### warm_start = False max_warm_iterate = 5 max_bgs_iterate = 5 if warm_start: x = fischer_warm_start(A, x, b, max_warm_iterate, max_bgs_iterate) ##### Values needed file iterating ##### convergence = np.zeros(max_iter+1) # Should use np.infty. err = 1e20 iterate = 1 flag = 2 grad_steps = 0 grad_steps_max = max_iter use_grad_steps = True while iterate <= max_iter: alpha = 0.5 take_grad_step = False y = np.dot(A,x) + b assert y.shape == (N,1), 'y is not a column vector, it has shape: ' + repr(y.shape) assert np.all(np.isreal(y)), 'y is not real' # Calculate the fischer function value phi = fischer(y,x) assert phi.shape == (N,1), 'phi is not a column vector, it has shape: ' + repr(phi.shape) assert np.all(np.isreal(phi)), 'phi is not real' old_err = err # Calculate merit value, error err = 0.5*np.dot(phi.T,phi) assert err.shape == (1,1), 'err is not a scalar, it has shape: ' + repr(err.shape) assert np.isreal(err), 'err is not real' if profile: convergence[iterate-1] = err if grad_steps > grad_steps_max: # Should we break or should we just stop using grad steps? use_grad_steps = False # flag = 10 # Number of grad steps exceeded. # break ##### Test the stopping criterias used ##### rel_err = np.abs(err-old_err)/np.abs(old_err) if rel_err < tol_rel: if use_grad_steps: take_grad_step = True elif rel_err < eps: flag = 3 break if err < tol_abs: flag = 4 break ##### Solving the Newton system dx = np.zeros((N,1)) # Bitmask of True/False values where the conditions are # satisfied, that is where phi and x are near # singular/singular. S = np.logical_and(np.abs(phi) < gamma, np.abs(x) < gamma) # Bitmask of nonsingular values I = np.logical_not(S) idx = np.where(I) restart = min(np.size(A,0), 10) # Number of iterates done # before Restart for GMRES # should restart if 'random' == str.lower(solver): # Works on full system # Initialize as sparse, otherwise indexing will not work. J = sps.lil_matrix((N,N)) dx = sps.lil_matrix((N,1)) q = np.random.rand(N,1) / np.sqrt(2) - 1.0 p = np.random.rand(N,1) / np.sqrt(2) - 1.0 q[I] = (y[I]/((y[I]**2+x[I]**2)**(0.5)))-1 p[I] = (x[I]/((y[I]**2+x[I]**2)**(0.5)))-1 J[idx[0],idx[0]] = np.diag(p[I])*np.identity(A[idx].shape[0]) + np.dot(np.diag(q[I]),A[idx[0],:][:,idx[0]]) J = J.toarray() # Call GMRES (This is very slow, might consider another # approach) dx[idx] = gmres(J[idx[0],:][:,idx[0]], (-phi[idx]), tol=gmres_tol, restart=restart)[0].reshape(idx[0].size,1) dx = dx.toarray() dx = dx.reshape(-1,1) assert dx.shape == (N,1), 'dx is not a column vector, it has shape: ' + repr(dx.shape) assert np.all(np.isreal(dx)), 'dx is not real' ##### Available methods from scipy ##### # bicg(A, b[, x0, tol, maxiter, xtype, M, ...]) Use BIConjugate Gradient iteration to solve A x = b # bicgstab(A, b[, x0, tol, maxiter, xtype, M, ...]) Use BIConjugate Gradient STABilized iteration to solve A x = b # cg(A, b[, x0, tol, maxiter, xtype, M, callback]) Use Conjugate Gradient iteration to solve A x = b # cgs(A, b[, x0, tol, maxiter, xtype, M, callback]) Use Conjugate Gradient Squared iteration to solve A x = b # gmres(A, b[, x0, tol, restart, maxiter, ...]) Use Generalized Minimal RESidual iteration to solve A x = b. # lgmres(A, b[, x0, tol, maxiter, M, ...]) Solve a matrix equation using the LGMRES algorithm. # minres(A, b[, x0, shift, tol, maxiter, ...]) Use MINimum RESidual iteration to solve Ax=b # qmr(A, b[, x0, tol, maxiter, xtype, M1, M2, ...]) Use Quasi-Minimal Residual iteration to solve A x = b elif 'perturbation' == str.lower(solver): # Works on full system px = np.zeros(x.shape) px[:] = x # Copy x assert px.shape == (N,1), 'px is not a column vector, it has shape: ' + repr(px.shape) assert np.all( np.isreal(px) ), 'px is not real' direction = np.zeros(x.shape) direction[:] = np.sign(x) direction[ direction == 0 ] = 1 px[S] = gamma * direction[S] p = np.zeros(px.shape) p = (px / (np.sqrt(np.power(y,2) + np.power(px,2))))-1 assert p.shape == (N,1), 'p is not a column vector, it has shape: ' + repr(p.shape) assert np.all(np.isreal(p)), 'p is not real' q = np.zeros(y.shape) q = (y / (np.sqrt(np.power(y,2) + np.power(px,2)))) - 1 assert q.shape == (N,1), 'q is not a column vector, it has shape: ' + repr(q.shape) assert np.all(np.isreal(q)), 'q is not reeal' J = np.dot(np.diag(p[:,0]),np.identity(N)) + np.dot(np.diag(q[:,0]),A) assert J.shape == (N,N), 'J is not a square matrix, it has shape: ' + repr(J.shape) assert np.all(np.isreal(J)), 'J is not real' # Reciprocal conditioning number of J rcond = 1/np.linalg.cond(J) if np.isnan(rcond): rcond = np.nan_to_num(rcond) # Check conditioning of J, if bad use pinv to solve the system. if rcond < 2*eps: if np.any(np.isnan(J)): print "J contains nan" if np.any(np.isnan(phi)): print "phi contains nan" try: dx = np.dot(spl.pinv(J), (-phi)) except Exception: print repr(dir(Exception)) dx = np.dot(spl.pinv2(J), (-phi)) else: J = sps.csc_matrix(J) dx = dsolve.spsolve(J, (-phi), use_umfpack=True) dx = dx.reshape(dx.size,1) J = J.toarray() assert dx.shape == (N,1), 'dx is not a column vector, it has shape: ' + repr(dx.shape) assert np.all(np.isreal(dx)), 'dx is not real' elif 'zero' == str.lower(solver): J = sps.lil_matrix((N,N)) dx = sps.lil_matrix((N,1)) q = (y[I]/((y[I]**2+x[I]**2)**(0.5)))-1 p = (x[I]/((y[I]**2+x[I]**2)**(0.5)))-1 J[idx[0],idx[0]] = np.diag(p)*np.identity(A[idx].shape[0]) + np.dot(np.diag(q),A[idx[0],:][:,idx[0]]) J = J.toarray() # Call GMRES (This is very slow, might consider another # approach) dx[idx] = gmres(J[idx[0],:][:,idx[0]], (-phi[idx]), tol=gmres_tol, restart=restart)[0].reshape(idx[0].size,1) dx = dx.toarray() dx = dx.reshape(-1,1) assert dx.shape == (N,1), 'dx is not a column vector, it has shape: ' + repr(dx.shape) elif 'approximation' == str.lower(solver): ### THIS IS NOT WORKING YET ### J = sps.lil_matrix((N,N)) dx = sps.lil_matrix((N,1)) q = np.zeros(x.shape) p = np.zeros(x.shape) q[I] = y[I]/((y[I]**2+x[I]**2)**(0.5))-1 p[I] = x[I]/((y[I]**2+x[I]**2)**(0.5))-1 J[idx[0],idx[0]] = np.diag(p[I])*np.identity(A[idx].shape[0]) + np.dot(np.diag(q[I]),A[idx[0],:][:,idx[0]]) # Call GMRES, how do we handle a function handle for gmres? fun = lambda dx: (fischer(np.dot(A[idx[0],:][:,idx[0]],(x[I]+dx[I]*h)) + b[I],x[I] + dx[I]*h) - phi[I]) / h LO = LinearOperator((N,1), matvec = fun) dx[idx] = gmres(LO, -phi[I], tol=gmres_tol, restart=restart) # dx[idx] = gmres(fun, -phi[I], tol=1e-20, restart=restart) else: sys.stderr.write('Unknown solver method for Newton subsystem') nabla_phi = np.dot(phi.T, J) # We could use nabla_phi = nabla_phi.reshape(nabla_phi.size, # 1) instead this creates a column vector no matter what. nabla_phi = nabla_phi.T assert nabla_phi.shape == (N,1), 'nabla_phi is not a column vector, it has shape: ' + repr(nabla_phi.shape) assert np.all(np.isreal(nabla_phi)), 'nabla_phi is not real' # Perform gradient descent step if take_grad_step is defined if take_grad_step: alpha = 0.9 dx = -nabla_phi grad_steps += 1 # Tests whether the search direction is below machine # precision. if np.max(np.abs(dx)) < eps: flag = 5 # If enabled and the relative change in error is low, use # a gradient descent step if take_grad_step: dx = -nabla_phi grad_steps += 1 print "*** Search direction below machine precision at iterate " + repr(iterate) + ", choosing gradient as search direction." else: break # Test whether we are stuck in a local minima if np.linalg.norm(nabla_phi) < tol_abs: flag = 6 break # Test whether our direction is a sufficient descent direction if np.dot(nabla_phi.T,dx) > -rho*(np.dot(dx.T, dx)): # Otherwise we should try gradient direction instead. if use_grad_steps: dx = -nabla_phi grad_steps += 1 print "*** Non descend direction at iterate " + repr(iterate) + ", choosing gradient as search direction." else: flag = 7 break ##### Armijo backtracking combined with a projected line-search ##### tau = 1.0 f_0 = err grad_f = beta*np.dot(nabla_phi.T,dx) x_k = x[:] assert x_k.shape == (N,1), 'x_k is not a column vector, it has shape: ' + repr(x_k) assert np.all(np.isreal(x_k)), 'x_k is not real' # Perform line search while True: x_k = np.maximum(0, x + dx*tau) assert x_k.shape == (N,1), 'x_k is not a column vector, it has shape: ' + repr(x_k.shape) assert np.all(np.isreal(x_k)), 'x_k is not real' y_k = np.dot(A,x_k)+b assert y_k.shape == (N,1), 'y_k is not a column vector, it has shape: ' + repr(y_k.shape) assert np.all(np.isreal(y_k)), 'y_k is not real' phi_k = fischer(y_k,x_k) assert phi_k.shape == (N,1), 'phi_k is not a column vector, it has shape: ' + repr(phi_k.shape) assert np.all(np.isreal(phi_k)), 'phi_k is not real' f_k = 0.5*(np.dot(phi_k.T,phi_k)) # Test Armijo condition for sufficient decrease if f_k <= f_0 + tau*grad_f: break # Test whether the stepsize has become too small if tau*tau < gamma: break tau *= alpha # Update iterate with result from line search. x = x_k assert x.shape == (N,1), 'x is not a column vector, it has shape: ' + repr(x.shape) assert np.all(np.isreal(x)), 'x is not real.' # Increment iterate iterate +=1 if iterate >= max_iter: iterate -= 1 flag = 8 print "No grad steps: " + repr(grad_steps) return (x, err, iterate, flag, convergence[:iterate], msg[flag])
def test_singular(self): A = csc_matrix((5, 5), dtype='d') b = array([1, 2, 3, 4, 5], dtype='d') x = spsolve(A, b, use_umfpack=False)