def get_color_solve(mark_color_yuv, mark_binary, wd=1): shape = mark_color_yuv.shape n = shape[0] m = shape[1] img_size = n * m out_img_yuv = np.zeros(shape, dtype=np.float) out_img_yuv[:, :, 0] = mark_color_yuv[:, :, 0] indexM = np.arange(img_size).reshape((n, m), order='F') len = 0 consts_len = 0 col_inds = np.zeros(img_size * (2 * wd + 1)**2, dtype=np.int) row_inds = np.zeros(img_size * (2 * wd + 1)**2, dtype=np.int) vals = np.zeros(img_size * (2 * wd + 1)**2, dtype=np.float) gvals = np.zeros((2 * wd + 1)**2, dtype=np.float) A = sps.lil_matrix((img_size, img_size), dtype=np.float) bU = np.zeros((A.shape[0]), dtype=np.float) bV = np.zeros((A.shape[0]), dtype=np.float) for j in range(m): for i in range(n): if (mark_binary[i, j]): bU[consts_len] = 1 * mark_color_yuv[i, j, 1] bV[consts_len] = 1 * mark_color_yuv[i, j, 2] vals[len] = 1 else: tlen = 0 for ii in range(max(0, i - wd), min(i + wd, n - 1) + 1): for jj in range(max(0, j - wd), min(j + wd, m - 1) + 1): if (ii != i or jj != j): row_inds[len] = consts_len col_inds[len] = indexM[ii, jj] gvals[tlen] = mark_color_yuv[ii, jj, 0] len += 1 tlen += 1 gvals[tlen] = mark_color_yuv[i, j, 0] gvals = get_exp_weights(gvals, tlen) #gvals = get_linear_weights(gvals, tlen) vals[len - tlen:len] = gvals[0:tlen] vals[len] = 1 row_inds[len] = consts_len col_inds[len] = indexM[i, j] len += 1 consts_len += 1 for i in range(len): A[row_inds[i], col_inds[i]] = vals[i] A = A.tocsr() xU = linsolve.spsolve(A, bU) xV = linsolve.spsolve(A, bV) out_img_yuv[:, :, 1] = xU.reshape((n, m), order='F') out_img_yuv[:, :, 2] = xV.reshape((n, m), order='F') return out_img_yuv
def diffuse_one_time_step(self, enzyme_concentration = None, external_add_subtract = None): """Solve a single time step in the diffusion problem""" self.set_boundary_values() if self.breakdown_k: self.set_reaction_vector_breakdown() if self.enzyme_limited_breakdown_Vmax: self.set_reaction_vector_enzyme_limited_breakdown( enzyme_concentration) if external_add_subtract.__class__ == numpy.ndarray: self.set_reaction_vector_external_add_subtract( external_add_subtract) A = self.A.tocsr() B = self.B.tocsr() if self.linear_or_radial == "linear": c_old = self.conc elif self.linear_or_radial == "radial": c_old = self.convert_radial_to_linear(self.conc) self.R = self.convert_radial_to_linear(self.R) c_new = linsolve.spsolve(A, ((B * c_old) + self.C + 2*self.R)) if self.linear_or_radial == "linear": self.conc = c_new elif self.linear_or_radial == "radial": self.conc = self.convert_linear_to_radial(c_new) self.conc[self.conc<0] = 0 #needed if enzyme brings conc<0 self.R = numpy.zeros(self.n, dtype = numpy.float32) #Reset reaction matrix
def test_solve_umfpack(self): """Solve with UMFPACK: double precision""" linsolve.use_solver( useUmfpack = True ) a = self.a.astype('d') b = self.b x = linsolve.spsolve(a, b) #print x #print "Error: ", a*x-b assert_array_almost_equal(a*x, b)
def test_solve_sparse_rhs(self): """Solve with UMFPACK: double precision, sparse rhs""" linsolve.use_solver( useUmfpack = True ) a = self.a.astype('d') b = csc_matrix( self.b.reshape((5,1)) ) x = linsolve.spsolve(a, b) #print x #print "Error: ", a*x-b assert_array_almost_equal(a*x, self.b)
def solve_with_initial_guess(self, initial_guess, solver="LU"): A = self.matrix.get_csr_matrix() if(solver == "AMG"): ml = smoothed_aggregation_solver(A) M = ml.aspreconditioner() self.sol = gmres(A, self.rhs.val, x0=initial_guess, M=M)[0] elif( solver == "LU"): self.sol = linsolve.spsolve(A, self.rhs.val)
def test_solve_without_umfpack(self): """Solve: single precision""" linsolve.use_solver( useUmfpack = False ) a = self.a.astype('f') b = self.b x = linsolve.spsolve(a, b.astype('f')) #print x #print "Error: ", a*x-b # single precision: be more generous... assert_array_almost_equal(a*x, b, decimal = 5)
def test_solve_complex_without_umfpack(self): """Solve: single precision complex""" linsolve.use_solver( useUmfpack = False ) a = self.a a.data = a.data.astype('F',casting='unsafe') b = self.b b = b.astype('F') x = linsolve.spsolve(a, b) #print x #print "Error: ", a*x-b assert_array_almost_equal(a*x, b)
def poissonneumann(k,N,g,f, points): tag = "B1" elements = H1Elements(k) quadrule = pyramidquadrature(k+1) system = SymmetricSystem(elements, quadrule, lambda m: buildcubemesh(N,m,tag), []) SM = system.systemMatrix(True) S = SM[1:,:][:,1:] # the first basis fn is guaranteed to be associated with an external degree, so is a linear comb of all the others F = 0 if f is None else system.loadVector(f) G = 0 if g is None else system.boundaryLoad({tag:g}, squarequadrature(k+1), trianglequadrature(k+1), False) U = numpy.concatenate((numpy.array([0]), spsolve(S, G[tag][1:]-F[1:])))[:,numpy.newaxis] return system.evaluate(points, U, {}, False)
def oopsi_est_map(F, P): # extract parameters from dict (turples) T, dt, gam, a, b, sig, lam = ( P[k] for k in ('T', 'dt', 'gamma', 'alpha', 'beta', 'sigma', 'lambda') ) # initialize n,C,llam n = 0.01 + np.zeros(T) C = lfilter([1.0], [1.0, -gam], n) llam = (lam * dt) * np.ones(T) # M, H, H1, H2 are 'sparse' matrix, therefore # we can directly multiply it with a vector (without np.dot) M = oopsi_m(gam, T) grad_lnprior = M.T * llam H1 = (a ** 2) / (sig ** 2) * eye(T) z = 1.0 # weight on barrier function while z > 1e-13: D = F - a * C - b # residual lik = 1 / (2 * (sig ** 2)) * np.dot(D.T, D) post = lik + np.dot(llam.T, n) - z * np.sum(np.log(n)) # calculate L s = 1.0 d = 1.0 while (lp.norm(d) > 5e-2) and (s > 1e-3): # conv for z glik = -a / (sig ** 2) * (F - a * C - b) g = glik + grad_lnprior - z * (M.T * (1 / n)) # gradient, g H2 = spdiags(1 / (n ** 2), 0, T, T) H = H1 + z * (M.T * H2 * M) # Hessian, H d = linsolve.spsolve(H, g) # direction to step # find s hit = n / (M * d) # steps within constraint boundaries hit = hit[hit > 0] if any(hit < 1): s = 0.99 * hit.min() else: s = 1.0 # loop over s post1 = post + 1.0 while post1 > post + 1e-7: # goal: newton step decrease objective C1 = C - s * d n = M * C1 D = F - a * C1 - b lik1 = 1 / (2 * (sig ** 2)) * np.dot(D.T, D) post1 = lik1 + np.dot(llam.T, n) - z * np.sum(np.log(n)) s = s / 5.0 if s < 1e-20: break C = C1 # update C post = post1 # update post z = z / 10.0 # reduce z (sequence of z reductions is arbitrary) # clearing n[0],n[1] and normalize n between [0,1] n[0:2] = 1e-8 n = n / n.max() return n, C, post
def solve(self, rhs): '''Construct the matrix and use the solver to get the solution for the supplied rhs. ''' ij = vstack((self.x_l, self.y_l)) # Assemble the system matrix from the flattened data and # sparsity map containing two rows - first one are the row # indices and second one are the column indices. mtx = sparse.coo_matrix((self.data_l, ij)) u_vct = linsolve.spsolve(mtx, rhs) return u_vct
def solve( self, rhs ): '''Construct the matrix and use the solver to get the solution for the supplied rhs. ''' ij = vstack( ( self.x_l, self.y_l ) ) # Assemble the system matrix from the flattened data and # sparsity map containing two rows - first one are the row # indices and second one are the column indices. mtx = sparse.coo_matrix( ( self.data_l, ij ) ) u_vct = linsolve.spsolve( mtx, rhs ) return u_vct
def oopsi_est_map(F,P): # extract parameters from dict (turples) T,dt,gam,a,b,sig,lam = \ (P[k] for k in ('T','dt','gamma','alpha','beta','sigma','lambda')) # initialize n,C,llam n = 0.01 + np.zeros(T) C = lfilter([1.0],[1.0,-gam],n) llam = (lam*dt) * np.ones(T) # M, H, H1, H2 are 'sparse' matrix, therefore # we can directly multiply it with a vector (without np.dot) M = oopsi_m(gam,T) grad_lnprior = M.T*llam H1 = (a**2)/(sig**2) * eye(T) z = 1.0 # weight on barrier function while z>1e-13: D = F - a*C - b # residual lik = 1/(2*(sig**2))*np.dot(D.T,D); post = lik + np.dot(llam.T,n) - z*np.sum(np.log(n)) # calculate L s = 1.0 d = 1.0 while (lp.norm(d) > 5e-2) and (s > 1e-3): # conv for z glik = -a/(sig**2)*(F - a*C - b) g = glik + grad_lnprior - z*(M.T*(1/n)) # gradient, g H2 = spdiags(1/(n**2),0,T,T) H = H1 + z*(M.T*H2*M) # Hessian, H d = linsolve.spsolve(H,g) # direction to step # find s hit = n/(M*d) # steps within constraint boundaries hit = hit[hit>0] if any(hit<1): s = 0.99*hit.min() else: s = 1.0 # loop over s post1 = post + 1.0 while (post1 > post + 1e-7): #goal: newton step decrease objective C1 = C - s*d n = M*C1 D = F - a*C1 - b lik1 = 1/(2*(sig**2)) * np.dot(D.T,D) post1 = lik1 + np.dot(llam.T,n) - z*np.sum(np.log(n)) s = s/5.0 if (s<1e-20): break C = C1 # update C post = post1 # update post z = z/10.0 # reduce z (sequence of z reductions is arbitrary) # clearing n[0],n[1] and normalize n between [0,1] n[0:2] = 1e-8 n = n / n.max() return n, C, post
def laplacedirichlet(k, N, g, points): tag = "B1" elements = H1Elements(k) quadrule = pyramidquadrature(k+1) system = SymmetricSystem(elements, quadrule, lambda m: buildcubemesh(N, m, tag), [tag]) SM = system.systemMatrix(True) S, SIBs, Gs = system.processBoundary(SM, {tag:g}) SG = SIBs[tag] * Gs[tag] print S.shape U = spsolve(S, -SG)[:,numpy.newaxis] return system.evaluate(points, U, Gs, False)
def solve(self): self.nb_dof_condensed = self.nb_dof_FEM - self.nb_dof_master start = timeit.default_timer() self.linear_system_2_numpy() index_A = np.where(((self.A_i * self.A_j) != 0)) A = coo_matrix( (self.A_v[index_A], (self.A_i[index_A] - 1, self.A_j[index_A] - 1)), shape=(self.nb_dof_master - 1, self.nb_dof_master - 1)).tocsr() F = np.zeros(self.nb_dof_master - 1, dtype=complex) for _i, f_i in enumerate(self.F_i): F[f_i - 1] += self.F_v[_i] # Resolution of the sparse linear system if self.verbose: print("Resolution of the linear system") X = linsolve.spsolve(A, F) # Concatenation of the first (zero) dof at the begining of the vector X = np.insert(X, 0, 0) # Concatenation of the slave dofs at the end of the vector T = coo_matrix( (self.T_v, (self.T_i, self.T_j)), shape=(self.nb_dof_condensed, self.nb_dof_master)).tocsr() X = np.insert(T @ X, 0, X) stop = timeit.default_timer() if self.verbose: print("Elapsed time for linsolve = {} ms".format( (stop - start) * 1e3)) for _vr in self.vertices[1:]: for i_dim in range(4): _vr.sol[i_dim] = X[_vr.dofs[i_dim]] for _ed in self.edges: for i_dim in range(4): _ed.sol[i_dim] = X[_ed.dofs[i_dim]] for _fc in self.faces: for i_dim in range(4): _fc.sol[i_dim] = X[_fc.dofs[i_dim]] for _bb in self.bubbles: for i_dim in range(4): _bb.sol[i_dim] = X[_bb.dofs[i_dim]] if self.export_paraview is not False: export_paraview(self) return X
def poissondirichlet(k,N,g,f, points): tag = "B1" elements = H1Elements(k) quadrule = pyramidquadrature(k+1) system = SymmetricSystem(elements, quadrule, lambda m: buildcubemesh(N, m, tag), [tag]) SM = system.systemMatrix(True) S, SIBs, Gs = system.processBoundary(SM, {tag:g}) SG = SIBs[tag] * Gs[tag] if f: F = system.loadVector(f) else: F = 0 print SM.shape, S.shape, SIBs[tag].shape, Gs[tag].shape, F.shape, SG.shape t = Timer().start() U = spsolve(S, -F-SG)[:,numpy.newaxis] t.split("spsolve").show() return system.evaluate(points, U, Gs, False)
def solve(self): debug = True sol = None # np.zeros((self.mod.M, self.mod.N), dtype=float) for k in range(self.mod.T): print "Generating RHS # %s" % k LHS = self._generate_LHS() RHS = self._generate_RHS() print "Solving % s system" % k sol = linsolve.spsolve(LHS, RHS) sol = sol + self.buff stable = self.is_stable(sol) if not stable: print "No stability!" self.buff = self.initial_state break self.solutions.append(sol) self.buff = sol for i in range(len(self.solutions)): self.solutions[i] = self.solutions[i].reshape((self.mod.M, self.mod.N)) self.buff = self.initial_state
def solve(self, rhs, check_pos_dev=False): '''Construct the matrix and use the solver to get the solution for the supplied rhs pos_dev - test the positive definiteness of the matrix. ''' ij = vstack((self.x_l, self.y_l)) # Assemble the system matrix from the flattened data and # sparsity map containing two rows - first one are the row # indices and second one are the column indices. mtx = sparse.coo_matrix((self.data_l, ij)) mtx_csr = mtx.tocsr() pos_def = True if check_pos_dev: evals_small, evecs_small = eigsh(mtx_csr, 3, sigma=0, which='LM') min_eval = np.min(evals_small) pos_def = min_eval > 1e-10 u_vct = linsolve.spsolve(mtx_csr, rhs) return u_vct, pos_def
def wiener(self, F, dt=0.020, iter_max=25, update=True): # normalize F = (F-F.mean())/np.abs(F).max() # fluor T = F.shape[0] gam = 1.0 - dt/1.0 gtol = 1e-4 # global tolerance M = spdiags([-gam*np.ones(T), np.ones(T)],[-1,0],T,T) # conv mat C = np.ones(T) # calcium n = M*C lam = 1.0 llam = (lam*dt) sig = 0.1*lp.norm(F) # 0.1 is arbitrary D0 = F - C # assume a=1.0, b=0.0 D1 = n - llam # likelihood lik = np.dot(D0.T,D0)/(2*sig**2) + np.dot(D1.T,D1)/(2*llam) # eq 11.b # See appendix B Vogelstein et. al., 2010. for i in range(iter_max): g = -(F-C)/sig**2 + (M.T*(M*C)-llam*(M.T*np.ones(T)))/llam H = eye(T)/sig**2 + M.T*M/llam d = linsolve.spsolve(H,g) C = C - d N = M*C old_lik = lik D0 = F - C D1 = n - llam lik = np.dot(D0.T,D0)/(2*sig**2) + np.dot(D1.T,D1)/(2*llam) if lik <= old_lik - gtol: # NR step until convergence n = N if update: sig = np.sqrt(np.dot(D0.T,D0)/T) else: break n = n/n.max() return n, C
def solve_direct(grid, ivar, rvar, verbose=False): """Solve the Poisson system using a direct solver. Arguments --------- grid : Grid object Grid containing data. ivar : string Name of the grid variable of the numerical solution. rvar : string Name of the grid variable of the right-hand side. Returns ------- residual: float Final residual. verbose : bool, optional Set True to display convergence information; default: False. """ phi = grid.get_values(ivar) b = grid.get_values(rvar) nx, ny = grid.nx, grid.ny dx, dy = grid.dx, grid.dy A = mtx(grid, ivar) x = linsolve.spsolve(A, b[1:-1, 1:-1].flatten()) residual = numpy.linalg.norm(A * x - b[1:-1, 1:-1].flatten()) phi[1:-1, 1:-1] = numpy.reshape(x, (nx, ny)) grid.fill_guard_cells(ivar) if verbose: print('Direct Solver:') print('- Final residual: {}'.format(residual)) return residual
def cal_numerical_solution(self): for k in range(self.num_triangles): self.cal_B(k) #if ( k == 0 ): # print(self.B_tilde) for l in range(3): i = int(self.triangles[k, l] - 1) #print('Value of i={}, k={}, l={}'.format(i,k,l)) #print('k={},i={},vertice={}'.format(k,i,self.points[i])) for m in range(3): j = int(self.triangles[k, m] - 1) #print('Value of j: {}'.format(j)) if (i < self.num_inner_points) and (j < self.num_inner_points): self.alpha1 = ( self.B_tilde[0, 0] * self.basis[l, 0] + self.B_tilde[0, 1] * self.basis[l, 1]) * ( self.B_tilde[0, 0] * self.basis[m, 0] + self.B_tilde[0, 1] * self.basis[m, 1]) self.alpha2 = ( self.B_tilde[1, 0] * self.basis[l, 0] + self.B_tilde[1, 1] * self.basis[l, 1]) * ( self.B_tilde[1, 0] * self.basis[m, 0] + self.B_tilde[1, 1] * self.basis[m, 1]) self.alpha = self.alpha1 + self.alpha2 self.A[i, j] = self.A[ i, j] + self.alpha / (4 * abs(self.triangle_area)) if (i < self.num_inner_points): #print(i) self.f[i] = self.f[i] + (self.triangle_area / 3) * ( 2 * np.pi**2 * np.sin(np.pi * self.vertices[l, 0]) * np.sin(np.pi * self.vertices[l, 1])) #print(self.A) #print(self.f) self.A = self.A.tocsr() self.numerical_solution = linsolve.spsolve(self.A, self.f) #self.numerical_solution = np.linalg.solve(self.A,self.f) print('Max: {}, min: {}'.format(np.max(self.f), np.min(self.f))) print('Max: {}, min: {}'.format(np.max(self.A), np.min(self.A)))
def wiener(F, dt=0.020, iter_max=20, update=True): # normalize F = (F - F.mean()) / np.abs(F).max() T = F.shape[0] gam = 1.0 - dt / 1.0 M = spdiags([-gam * np.ones(T), np.ones(T)], [-1, 0], T, T) C = np.ones(T) n = M * C lam = 1.0 llam = (lam * dt) sig = 0.1 * lp.norm(F) # 0.1 is arbitrary # D0 = F - C # we assume a=1.0, b=0.0 D1 = n - llam lik = np.dot(D0.T, D0) / (2 * sig**2) + np.dot(D1.T, D1) / (2 * llam) gtol = 1e-4 # for i in xrange(iter_max): # g = -(F-C)/sig**2 + ((M*C).T*M-llam*(M.T*np.ones(T)))/llam g = -(F - C) / sig**2 + (M.T * (M * C) - llam * (M.T * np.ones(T))) / llam H = eye(T) / sig**2 + M.T * M / llam d = linsolve.spsolve(H, g) C = C - d N = M * C # old_lik = lik D0 = F - C D1 = n - llam lik = np.dot(D0.T, D0) / (2 * sig**2) + np.dot(D1.T, D1) / (2 * llam) if lik <= old_lik - gtol: # NR step decreases likelihood n = N if update: sig = np.sqrt(np.dot(D0.T, D0) / T) else: break n = n / n.max() return n, C
def wiener(F,dt=0.020,iter_max=20,update=True): # normalize F = (F-F.mean())/np.abs(F).max() T = F.shape[0] gam = 1.0 - dt/1.0 M = spdiags([-gam*np.ones(T), np.ones(T)],[-1,0],T,T) C = np.ones(T) n = M*C lam = 1.0 llam = (lam*dt) sig = 0.1*lp.norm(F) # 0.1 is arbitrary # D0 = F - C # we assume a=1.0, b=0.0 D1 = n - llam lik = np.dot(D0.T,D0)/(2*sig**2) + np.dot(D1.T,D1)/(2*llam) gtol = 1e-4 # for i in xrange(iter_max): # g = -(F-C)/sig**2 + ((M*C).T*M-llam*(M.T*np.ones(T)))/llam g = -(F-C)/sig**2 + (M.T*(M*C)-llam*(M.T*np.ones(T)))/llam H = eye(T)/sig**2 + M.T*M/llam d = linsolve.spsolve(H,g) C = C - d N = M*C # old_lik = lik D0 = F - C D1 = n - llam lik = np.dot(D0.T,D0)/(2*sig**2) + np.dot(D1.T,D1)/(2*llam) if lik <= old_lik - gtol: # NR step decreases likelihood n = N if update: sig = np.sqrt(np.dot(D0.T,D0)/T) else: break n = n/n.max() return n, C
def _fsolve(self, params, alphas, visualize=False, save_fig=False): mu, tauchar, beta = [x for x in params] dx, dt = self._dx, self._dt; xs, ts = self._xs, self._ts; if visualize: print 'tauchar = %.2f, beta = %.2f,' %(tauchar, beta) print 'Tf = %.2f' %self.getTf() print 'xmin = %.f, dx = %f, dt = %f' %(self.getXmin(), dx,dt) #Allocate memory for solution: fs = zeros((self._num_nodes(), self._num_steps() )); #Impose Dirichlet BCs: = Automatic #Impose ICs: fs[:,0] = self._getICs(xs, alphas[0], beta) if visualize: figure() subplot(311) plot(xs, fs[:,-1]); title(r'$\alpha=%.2f, \tau=%.2f, \beta=%.2f$'%(alphas[0],tauchar, beta) + ':ICs', fontsize = 24); xlabel('x'); ylabel('f') subplot(312) plot(ts, fs[-1, :]); title('BCs at xth', fontsize = 24) ; xlabel('t'); ylabel('f') subplot(313) plot(ts, alphas); title('Control Input', fontsize = 24) ; xlabel('t'); ylabel(r'\alpha') #Solve it using C-N/C-D: D = beta * beta / 2.; #the diffusion coeff dx_sqrd = dx * dx; #Allocate mass mtx: active_nodes = self._num_nodes() - 1 M = lil_matrix((active_nodes, active_nodes)); #Centre Diagonal: e = ones(active_nodes); d_on = D * dt / dx_sqrd; centre_diag = e + d_on; M.setdiag(centre_diag) soln_fig = None; if visualize: soln_fig = figure() for tk in xrange(1, self._num_steps()): #Rip the forward-in-time solution: f_prev = fs[:,tk-1]; #Rip the control: alpha_prev = alphas[tk-1] alpha_next = alphas[tk] #Calculate the velocity field U_prev = (mu + alpha_prev - xs/ tauchar) U_next = (mu + alpha_next - xs/ tauchar) #Form the RHS: L_prev = -(U_prev[2:]*f_prev[2:] - U_prev[:-2]*f_prev[:-2]) / (2.* dx) + \ D * diff(f_prev, 2) / dx_sqrd; #impose the x_min BCs: homogeneous Newmann: and assemble the RHS: RHS = r_[0., f_prev[1:-1] + .5 * dt * L_prev]; #Reset the Mass Matrix: #Lower Diagonal u = U_next / (2*dx); d_off = D / dx_sqrd; L_left = -.5*dt*(d_off + u[:-2]); M.setdiag(L_left, -1); #Upper Diagonal L_right = -.5*dt*(d_off - u[2:]); M.setdiag(r_[NaN, L_right], 1); #Bottome BCs: M[0,0] = U_next[0] + D / dx; M[0,1] = -D / dx; #add the terms coming from the upper BC at the backward step to the end of the RHS #RHS[-1] += 0 #Here it is 0!!! #Convert mass matrix to CSR format: Mx = M.tocsr(); #and solve: f_next = spsolve(Mx, RHS); #Store solutions: fs[:-1, tk] = f_next; if visualize: mod_steps = 4; num_cols = 4; num_rows = ceil(double(self._num_steps())/num_cols / mod_steps) step_idx = tk; if 0 == mod(step_idx,mod_steps) or 1 == tk: plt_idx = floor(tk / mod_steps) + 1 ax = soln_fig.add_subplot(num_rows, num_cols, plt_idx) ax.plot(xs, fs[:,tk], label='k=%d'%tk); if 1 == tk: ax.hold(True) ax.plot(xs, fs[:,tk-1], 'r', label='ICs') ax.legend(loc='upper left') # ax.set_title('k = %d'%tk); if False : #(self._num_steps()-1 != tk): ticks = ax.get_xticklabels() for t in ticks: t.set_visible(False) else: ax.set_xlabel('$x$'); ax.set_ylabel('$f$') for t in ax.get_xticklabels(): t.set_visible(True) #Return: if visualize: for fig in [soln_fig]: fig.canvas.manager.window.showMaximized() if save_fig: file_name = os.path.join(FIGS_DIR, 'f_t=%.0f_b=%.0f.png'%(10*tauchar, 10*beta)) print 'saving to ', file_name soln_fig.savefig(file_name) return fs
def sparseLM(x0, func, fjaco, ferr, fcallback=None, lambda0=1e-2, eps_grad=1e-3, eps_param=1e-3, eps_cost=1e-3, eps_improv=1e-2, eps_es=1e10, max_iter=None, Lp=11, Lm=9, retall=False, disp=1, damping='eye', args=()): """ Levenberg-Marquard optimization, see: http://people.duke.edu/~hpgavin/ce281/lm.pdf :param x0: initial estimate :param func: function callback that returns cost :param fjaco: function callback that returns Jacobian matrix :param ferr: function callback that returns per equation error :param fcallback: function callback that is called every iteration :param lambda0: initial lambda :param eps_grad: gradient convergence threshold :param eps_param: parameter convergence threshold :param eps_cost: cost convergence treshold :param eps_improv: improvement threshold :param eps_es: early stopping threshold, stop when objective decreased by this factor :param max_iter: maximum number of iterations :param Lp: increase factor of lambda :param Lm: decrease factor of lambda :param retall: returns list, including cost over iterations, otherwise only optimized values :param disp: display intermediate information :param damping: select damping range: eye, max, diag :param args: additional arguments passed to func, fjaco, ferr, fcallback, etc :return: optimized values """ errs = [] x_intermed = [] x = x0.copy() lambdai = lambda0 i = 0 if max_iter is None: max_iter = numpy.inf while i < max_iter: func_x = func(x, *args) if disp: print "Error {} at iteration {}, lambdai {}".format( func_x, i, lambdai) # log errors if len(errs) <= i: errs.append(func_x) else: errs[i - 1] = func_x # get parts of equation j_mtx = fjaco(x, *args).tocsr() jtj = j_mtx.T.dot(j_mtx) dy = ferr(x, *args) rhs = j_mtx.T.dot(dy) # solve system # (J^T*J + lambda*I)*db = J^T*dy if damping == 'eye': diag = sps.eye(jtj.shape[0]) elif damping == 'diag': diag = sps.spdiags(jtj.diagonal(), 0, jtj.shape[0], jtj.shape[1]) elif damping == 'max': diag = numpy.max(jtj.diagonal()) * sps.eye(jtj.shape[0]) else: raise NotImplementedError("!") h = linsolve.spsolve(jtj + lambdai * diag, rhs) # calculate update func_xh = func(x + h, *args) rho_h = (func_x - func_xh) / (numpy.sum(h * (lambdai * diag * h + rhs))) if disp: print "rho={}, fun delta={}".format(rho_h, func_x - func_xh) if rho_h > eps_improv: x += h lambdai = max(lambdai / Lm, 1e-8) if fcallback is not None: fcallback(i, x) x_intermed.append(x.copy()) i += 1 else: lambdai = min(lambdai * Lp, 1e8) # test convergence, test separately so this is not a full iteration if lambdai >= 1e8: if disp: print "Convergence lambdai {} >= {}".format(lambdai, 1e8) break if errs[0] / func_x > eps_es: if disp: print "Early stopping objective {}/{} > {}".format( errs[0], func_x, eps_es) break if numpy.abs(rhs).max() < eps_grad: if disp: print "Convergence gradient {} < {}".format( numpy.abs(rhs).max(), eps_grad) break if numpy.nanmax(numpy.abs(h / x)) < eps_param: if disp: print "Convergence parameters {} < {}".format( numpy.abs(h / x).max(), eps_param) break if func_x < eps_cost: if disp: print "Convergence cost {} < {}".format(func_x, eps_cost) break if i == max_iter: if disp: print "Maximum number of iteration {} reached!".format(i) if retall: return [x, errs, x_intermed] else: return x
""" Construct a 1000x1000 lil_matrix and add some values to it, convert it to CSC format and solve A x = b for x with a direct solver. """ %pylab inline --no-import-all from matplotlib import pyplot as plt import numpy as np import scipy.sparse as sps from scipy.sparse.linalg.dsolve import linsolve import time rand = np.random.rand A = sps.lil_matrix((10000, 10000), dtype=np.float64) A[0::100, 2000:3000] = rand(1000) A.setdiag(rand(10000)) A = A.tocsc() # Compressed Sparse Column format # Spy matrix plt.spy(mtx, marker='.', markersize=2) plt.show() b = rand(10000) # random rhs t1 = time.time() # initial time x = linsolve.spsolve(A, b) # solve system t2 = time.time() # final time print 'residual:', np.linalg.norm(A * x - rhs) print t2-t1
def simcond(self, xo, method='approx', i_unknown=None): """ Simulate values conditionally on observed known values Parameters ---------- x : vector timeseries including missing data. (missing data must be NaN if i_unknown is not given) Assumption: The covariance of x is equal to self and have the same sample period. method : string defining method used in the conditional simulation. Options are: 'approximate': Condition only on the closest points. Quite fast 'exact' : Exact simulation. Slow for large data sets, may not return any result due to near singularity of the covariance matrix. i_unknown : integers indices to spurious or missing data in x Returns ------- sample : ndarray a random sample of the missing values conditioned on the observed data. mu, sigma : ndarray mean and standard deviation, respectively, of the missing values conditioned on the observed data. Notes ----- SIMCOND generates the missing values from x conditioned on the observed values assuming x comes from a multivariate Gaussian distribution with zero expectation and Auto Covariance function R. See also -------- CovData1D.sim TimeSeries.reconstruct, rndnormnd Reference --------- Brodtkorb, P, Myrhaug, D, and Rue, H (2001) "Joint distribution of wave height and wave crest velocity from reconstructed data with application to ringing" Int. Journal of Offshore and Polar Engineering, Vol 11, No. 1, pp 23--32 Brodtkorb, P, Myrhaug, D, and Rue, H (1999) "Joint distribution of wave height and wave crest velocity from reconstructed data" in Proceedings of 9th ISOPE Conference, Vol III, pp 66-73 """ x = atleast_1d(xo).ravel() acf = self._get_acf() num_x = len(x) num_acf = len(acf) if i_unknown is not None: x[i_unknown] = nan i_unknown = flatnonzero(isnan(x)) num_unknown = len(i_unknown) mu1o = zeros((num_unknown, )) mu1o_std = zeros((num_unknown, )) sample = zeros((num_unknown, )) if num_unknown == 0: warnings.warn('No missing data, no point to continue.') return sample, mu1o, mu1o_std if num_unknown == num_x: warnings.warn('All data missing, returning sample from' + ' the apriori distribution.') mu1o_std = ones(num_unknown) * sqrt(acf[0]) return self.sim(ns=num_unknown, cases=1)[:, 1], mu1o, mu1o_std i_known = flatnonzero(1 - isnan(x)) if method.startswith('exac'): # exact but slow. It also may not return any result if num_acf > 0.3 * num_x: Sigma = toeplitz(hstack((acf, zeros(num_x - num_acf)))) else: acf[0] = acf[0] * 1.00001 Sigma = sptoeplitz(hstack((acf, zeros(num_x - num_acf)))) Soo, So1, S11 = self._split_cov(Sigma, i_known, i_unknown) if issparse(Sigma): So1 = So1.todense() S11 = S11.todense() S1o_Sooinv = spsolve(Soo + Soo.T, 2 * So1).T else: Sooinv_So1, _res, _rank, _s = lstsq(Soo + Soo.T, 2 * So1, cond=1e-4) S1o_Sooinv = Sooinv_So1.T mu1o = S1o_Sooinv.dot(x[i_known]) Sigma1o = S11 - S1o_Sooinv.dot(So1) if (diag(Sigma1o) < 0).any(): raise ValueError('Failed to converge to a solution') mu1o_std = sqrt(diag(Sigma1o)) sample[:] = rndnormnd(mu1o, Sigma1o, cases=1).ravel() elif method.startswith('appr'): # approximating by only condition on the closest points Nsig = min(2 * num_acf, num_x) Sigma = toeplitz(hstack((acf, zeros(Nsig - num_acf)))) overlap = int(Nsig / 4) # indices to the points used idx = r_[0:Nsig] + max(0, min(i_unknown[0] - overlap, num_x - Nsig)) mask_unknown = zeros(num_x, dtype=bool) # temporary storage of indices to missing points mask_unknown[i_unknown] = True t_unknown = where(mask_unknown[idx])[0] t_known = where(1 - mask_unknown[idx])[0] ns = len(t_unknown) # number of missing data in the interval num_restored = 0 # number of previously simulated points x2 = x.copy() while ns > 0: Soo, So1, S11 = self._split_cov(Sigma, t_known, t_unknown) if issparse(Soo): So1 = So1.todense() S11 = S11.todense() S1o_Sooinv = spsolve(Soo + Soo.T, 2 * So1).T else: Sooinv_So1, _res, _rank, _s = lstsq(Soo + Soo.T, 2 * So1, cond=1e-4) S1o_Sooinv = Sooinv_So1.T Sigma1o = S11 - S1o_Sooinv.dot(So1) if (diag(Sigma1o) < 0).any(): raise ValueError('Failed to converge to a solution') ix = slice((num_restored), (num_restored + ns)) # standard deviation of the expected surface mu1o_std[ix] = np.maximum(mu1o_std[ix], sqrt(diag(Sigma1o))) # expected surface conditioned on the closest known # observations from x mu1o[ix] = S1o_Sooinv.dot(x2[idx[t_known]]) # sample conditioned on the known observations from x mu1os = S1o_Sooinv.dot(x[idx[t_known]]) sample[ix] = rndnormnd(mu1os, Sigma1o, cases=1) if idx[-1] == num_x - 1: ns = 0 # no more points to simulate else: x2[idx[t_unknown]] = mu1o[ix] # expected surface x[idx[t_unknown]] = sample[ix] # sampled surface # removing indices to data which has been simulated mask_unknown[idx[:-overlap]] = False # data we want to simulate once more nw = sum(mask_unknown[idx[-overlap:]] is True) num_restored += ns - nw # update # points simulated so far idx = self._update_window(idx, i_unknown, num_x, num_acf, overlap, nw, num_restored) # find new interval with missing data t_unknown = flatnonzero(mask_unknown[idx]) t_known = flatnonzero(1 - mask_unknown[idx]) ns = len(t_unknown) # # missing data in the interval return sample, mu1o, mu1o_std
def solve(self, params, alpha_bounds = (-1, 1.), energy_eps = 1.0, visualize=False, save_fig=False): mu, tauchar, beta = params[0], params[1], params[2] alpha_min, alpha_max = alpha_bounds[0],alpha_bounds[1] dx, dt = self._dx, self._dt; xs, ts = self._xs, self._ts; if visualize: print 'tauchar = %.2f, beta = %.2f,' %(tauchar, beta) print 'amin = %.2f, amax = %.2f, energy_eps=%.3f,'%(alpha_min, alpha_max,energy_eps) print 'Tf = %.2f' %self.getTf() print 'xmin = %.1f, dx = %f, dt = %f' %(self.getXmin(), dx,dt) # #Allocate memory for solution: vs = empty((self._num_nodes(), self._num_steps() )); cs = empty((self._num_nodes()-1, self._num_steps())) #Impose TCs: vs[:,-1] = self._getTCs(xs, alpha_max+mu, tauchar, beta) #Impose Dirichlet BCs: vs[-1,:] = self._getBCs(ts, self.getTf() ) if visualize: figure() subplot(211) plot(xs, vs[:,-1]); title(r'$\alpha=%.2f, \tau=%.2f, \beta=%.2f$'%(alpha_max,tauchar, beta) + ':TCs', fontsize = 24); xlabel('x'); ylabel('v') subplot(212) plot(ts, vs[-1, :]); title('BCs at xth', fontsize = 24) ; xlabel('t'); ylabel('v') #Solve it using C-N/C-D: D = beta * beta / 2.; #the diffusion coeff dx_sqrd = dx * dx; #Allocate mass mtx: active_nodes = self._num_nodes() - 1 M = lil_matrix((active_nodes, active_nodes)); #Centre Diagonal: e = ones(active_nodes); d_on = D * dt / dx_sqrd; centre_diag = e + d_on; M.setdiag(centre_diag) #Bottome BCs: M[0,0] = -1.; controls_fig, soln_fig = None,None; if visualize: soln_fig = figure() controls_fig = figure() def calc_control(di_x_v): alpha_reg = -di_x_v / (2.*energy_eps) e = ones_like(alpha_reg) alpha_bounded_below = amax(c_[alpha_min*e, alpha_reg], axis=1) return amin(c_[alpha_max*e, alpha_bounded_below], axis=1) for tk in xrange(self._num_steps()-2,-1, -1): #Rip the forward-in-time solution: v_forward = vs[:,tk+1]; di_x_v_forward = (v_forward[2:] - v_forward[:-2]) / (2*dx) di2_x_v_forward = (v_forward[2:] - 2*v_forward[1:-1] + v_forward[:-2]) / (dx_sqrd) #Calculate the control: alpha = calc_control(di_x_v_forward) #Form the velocity field: U = (mu + alpha - xs[1:-1]/tauchar) #Form the right hand side: L_prev = D * di2_x_v_forward + \ U * di_x_v_forward + \ 2*energy_eps * alpha*alpha #impose the x_min BCs: homogeneous Neumann: and assemble the RHS: RHS = r_[(.0, v_forward[1:-1] + .5 * dt * L_prev)]; #Reset the Mass Matrix: #Lower Diagonal u = U / (2*dx); d_off = D / dx_sqrd; L_left = -.5*dt*(d_off - u); M.setdiag(L_left, -1); #Upper Diagonal L_right = -.5*dt*(d_off + u); M.setdiag(r_[(1.0, L_right)], 1); #add the terms coming from the upper BC at the backward step to the end of the RHS v_upper_boundary = vs[-1,tk] RHS[-1] += .5* dt*(D * v_upper_boundary / dx_sqrd + U[-1] *v_upper_boundary / (2*dx) ) #Convert mass matrix to CSR format: Mx = M.tocsr(); #and solve: v_backward = spsolve(Mx, RHS); #Store solutions: vs[:-1, tk] = v_backward; # cs[:, tk+1] = r_[0.0, alpha] cs[:, tk+1] = r_[ alpha[0], alpha] if visualize: mod_steps = 8; num_cols = 2; num_rows = ceil(double(self._num_steps())/num_cols / mod_steps) + 1 step_idx = self._num_steps() - 2 - tk; if 0 == mod(step_idx,mod_steps) or 0 == tk: plt_idx = 1 + floor(tk / mod_steps) + int(0 < tk) ax = soln_fig.add_subplot(num_rows, num_cols, plt_idx) ax.plot(xs, vs[:,tk], label='k=%d'%tk); if self._num_steps() - 2 == tk: ax.hold(True) ax.plot(xs, vs[:,tk+1], 'r', label='TCs') ax.legend() # ax.set_title('k = %d'%tk); if (0 != tk): ticks = ax.get_xticklabels() for t in ticks: t.set_visible(False) else: ax.set_xlabel('$x$'); ax.set_ylabel('$v$') for t in ax.get_xticklabels(): t.set_visible(True) ax = controls_fig.add_subplot(num_rows, num_cols, plt_idx) ax.plot(xs[1:-1], alpha, label='k = %d'%tk) ax.set_ylim(alpha_min-.1, alpha_max+.1) ax.legend(); #ax.set_title('k = %d'%tk); if (0 != tk): for t in ax.get_xticklabels(): t.set_visible(False) else: ax.set_xlabel('$x$'); ax.set_ylabel(r'$\alpha$') for t in ax.get_xticklabels(): t.set_visible(True) #//end time loop #Now store the last control: v_init = vs[:,0]; cs[1:, 0] = calc_control( (v_init[2:] - v_init[:-2]) / (2*dx) ); cs[0,0] = cs[1,0] #Return: if visualize: for fig in [soln_fig, controls_fig]: fig.canvas.manager.window.showMaximized() if save_fig: file_name = os.path.join(FIGS_DIR, 'soln_al=%.0f_au=%.0f__t=%.0f_b=%.0f.png'%(10*alpha_min, 10*alpha_max,10*tauchar, 10*beta)) print 'saving to ', file_name soln_fig.savefig(file_name) file_name = os.path.join(FIGS_DIR, 'control_al=%.0f_au=%.0f__t=%.0f_b=%.0f.png'%(10*alpha_min, 10*alpha_max,10*tauchar, 10*beta)) print 'saving to ', file_name controls_fig.savefig(file_name) return xs, ts, vs, cs
triplets.insert(1, 0, -0.25) triplets.insert(1, 1, 0.25) # add impact of R2 triplets.insert(1, 1, 0.5) # add impact of V1 triplets.insert(0, 2, 1) triplets.insert(2, 0, 1) print(triplets, "\n") # setup matrix mtx = sparse.coo_matrix((triplets.data, (triplets.rows, triplets.cols)), shape=(3, 3)) del triplets # convert to CSR A = mtx.tocsr() print("A:") print(A, "\n") print(A.todense()) b = np.array([0, 2, 3]) print("\nB:", b) x = linsolve.spsolve(A, b) print("\nX:", x)
def solveSystem(A, b): x = linsolve.spsolve(A, b) return x
""" Solve a linear system ======================= Construct a 1000x1000 lil_matrix and add some values to it, convert it to CSR format and solve A x = b for x:and solve a linear system with a direct solver. """ import numpy as np import scipy.sparse as sps from matplotlib import pyplot as plt from scipy.sparse.linalg.dsolve import linsolve rand = np.random.rand mtx = sps.lil_matrix((1000, 1000), dtype=np.float64) mtx[0, :100] = rand(100) mtx[1, 100:200] = mtx[0, :100] mtx.setdiag(rand(1000)) plt.clf() plt.spy(mtx, marker='.', markersize=2) plt.show() mtx = mtx.tocsr() rhs = rand(1000) x = linsolve.spsolve(mtx, rhs) print('rezidual: %r' % np.linalg.norm(mtx * x - rhs))
m.set_icntl(3, -1) m.set_icntl(6, 5) m.set_icntl(12, 2) m.n = A.shape[0] m.nz = A.nnz print "Initializing arrays" print "IRN..." m.set_irn(A.row) print "JCN..." m.set_jcn(A.col) print "A..." m.set_a(A.data) print "RHS..." m.set_rhs(np.ones(m.n)) #lets have fun! t3 = time.time() m.dmumps(6) solution = m.get_rhs() t2 = time.time() print "MUMPS -> %s"%(t2-t1) A = A.tocsc() t1 = time.time() solution = spsolve(A, np.ones(m.n)) t2 = time.time() print "SLU -> %s"%(t2-t1)
def _psolve(self, tb, alphas, alpha_max, visualize=False, save_fig=False): tauchar, beta = tb[0], tb[1] dx, dt = self._dx, self._dt; xs, ts = self._xs, self._ts; if visualize: print 'tauchar = %.2f, beta = %.2f,' %(tauchar, beta) print 'amax = %.2f,'%alpha_max print 'Tf = %.2f' %self.getTf() print 'xmin = %.f, dx = %f, dt = %f' %(self.getXmin(), dx,dt) #Allocate memory for solution: ps = zeros((self._num_nodes(), self._num_steps() )); #Impose TCs: ps[:,-1] = self._getTCs(xs, alpha_max, tauchar, beta) #Impose BCs at upper end: ps[-1,:] = self._getAdjointBCs(ts, self.getTf()) if visualize: figure() subplot(311) plot(xs, ps[:,-1]); title(r'$\alpha=%.2f, \tau=%.2f, \beta=%.2f$'%(alphas[-1], tauchar, beta) + ':TCs', fontsize = 24); xlabel('x'); ylabel('p') subplot(312) plot(ts, ps[-1, :]); title('BCs at xth', fontsize = 24) ; xlabel('t'); ylabel('p') subplot(313) plot(ts, alphas); title('Control Input', fontsize = 24) ; xlabel('t'); ylabel(r'\alpha') #Solve it using C-N/C-D: D = beta * beta / 2.; #the diffusion coeff dx_sqrd = dx * dx; #Allocate mass mtx: active_nodes = self._num_nodes() - 1 M = lil_matrix((active_nodes, active_nodes)); #Centre Diagonal: e = ones(active_nodes); d_on = D * dt / dx_sqrd; centre_diag = e + d_on; M.setdiag(centre_diag) #Bottome BCs: M[0,0] = -1.; soln_fig = None; if visualize: soln_fig = figure() for tk in xrange(self._num_steps()-2,-1, -1): #Rip the forward-in-time solution: p_forward = ps[:,tk+1]; #Rip the control: alpha_forward = alphas[tk+1] alpha_current = alphas[tk] #Calculate the velocity field U_forward = (alpha_forward - xs[1:-1]/ tauchar) U_current = (alpha_current - xs[1:-1]/ tauchar) #Form the RHS: L_forward = U_forward*(p_forward[2:] - p_forward[:-2]) / (2.* dx) + \ D * diff(p_forward, 2) / dx_sqrd; #Impose the x_min BCs: homogeneous Newmann: and assemble the RHS: RHS = r_[0., p_forward[1:-1] + .5 * dt * L_forward]; #Reset the Mass Matrix: #Lower Diagonal u = U_current / (2*dx); d_off = D / dx_sqrd; L_left = -.5*dt*(d_off - u[1:-1]); M.setdiag(L_left, -1); #Upper Diagonal L_right = -.5*dt*(d_off + u[1:]); M.setdiag(r_[NaN, L_right], 1); #Bottome BCs: M[0,1] = 1.0; #add the terms coming from the upper BC at the backward step to the end of the RHS p_upper_boundary = ps[-1,tk]; RHS[-1] += .5* dt*(D * p_upper_boundary / dx_sqrd + U_current[-1] *p_upper_boundary / (2*dx) ) #Convert mass matrix to CSR format: Mx = M.tocsr(); #and solve: p_current = spsolve(Mx, RHS); #Store solutions: ps[:-1, tk] = p_current; if visualize: mod_steps = 4; num_cols = 4; num_rows = ceil(double(self._num_steps())/num_cols / mod_steps) + 1 step_idx = self._num_steps() - 2 - tk; if 0 == mod(step_idx,mod_steps) or 0 == tk: plt_idx = 1 + floor(tk / mod_steps) + int(0 < tk) ax = soln_fig.add_subplot(num_rows, num_cols, plt_idx) ax.plot(xs, ps[:,tk], label='k=%d'%tk); if self._num_steps() - 2 == tk: ax.hold(True) ax.plot(xs, ps[:,tk+1], 'r', label='TCs') ax.legend(loc='upper left') # ax.set_title('k = %d'%tk); if False : #(self._num_steps()-1 != tk): ticks = ax.get_xticklabels() for t in ticks: t.set_visible(False) else: ax.set_xlabel('$x$'); ax.set_ylabel('$p$') for t in ax.get_xticklabels(): t.set_visible(True) #Return: if visualize: for fig in [soln_fig]: fig.canvas.manager.window.showMaximized() if save_fig: file_name = os.path.join(FIGS_DIR, 'f_t=%.0f_b=%.0f.png'%(10*tauchar, 10*beta)) print 'saving to ', file_name soln_fig.savefig(file_name) return ps
def _bsolve(self, tcs, pAs, fs, params, alphas, visualize=False): sigma, = [x for x in params] dx, dt = self._dx, self._dt; xs, ts = self._xs, self._ts; if visualize: print 'x-,+', xs[[0,-1]] print 'Tf = %.2f' %self.getTf() print 'pAs', pAs print 'tcs', tcs #Allocate memory for solution: ps = zeros((len(tcs), self._num_steps(), self._num_nodes() )); #WARNING:!!! fs[fs<0]= 1e-8; fs_averaged = tensordot(pAs, fs, axes=1); adjoint_source = ones_like(fs); for idx, pA in enumerate(pAs): adjoint_source[idx, :, :] fAs = fs[idx, :, :]; adjoint_source[idx,:,:] += -pA*fAs / fs_averaged + log( fAs / fs_averaged ); #Impose TCs: #already done they are 0 #Solve it using C-N/C-D: D = sigma * sigma / 2.; #the diffusion coeff dx_sqrd = dx * dx; #Allocate mass mtx: active_nodes = self._num_nodes() M = lil_matrix((active_nodes, active_nodes)); #Centre Diagonal: e = ones(active_nodes); d_on = D * dt / dx_sqrd; centre_diag = e + d_on; M.setdiag(centre_diag) for tk in xrange(self._num_steps()-2,-1, -1): for tc_idx, tc in enumerate(tcs): #Rip the forward-in-time solution: p_forward = ps[tc_idx, tk+1,:]; di_x_p_forward = (p_forward[2:] - p_forward[:-2]) / (2*dx) di2_x_p_forward = (p_forward[2:] - 2*p_forward[1:-1] + p_forward[:-2]) / (dx_sqrd) #Calculate the velocity field Us_internal_field = -(xs/tc)[1:-1]; Us_forward = Us_internal_field + alphas[tk-1,:] Us_current = Us_internal_field + alphas[tk,:] source_term = adjoint_source[tc_idx, tk,:]; #Form the RHS: L_forward = D * di2_x_p_forward + \ Us_forward * di_x_p_forward + \ 2*source_term; #impose the x_min BCs: homogeneous Neumann: and assemble the RHS: RHS = r_[(.0, p_forward[1:-1] + .5 * dt * L_forward, .0)]; #Reset the Mass Matrix: #Lower Diagonal u = Us_current/ (2*dx); d_off = D / dx_sqrd; L_left = -.5*dt*(d_off - u); M.setdiag(L_left, -1); #Upper Diagonal L_right = -.5*dt*(d_off + u); M.setdiag(r_[NaN, L_right], 1); #Bottom BCs \di_x w = 0: M[0,0] = -1; M[0,1] = 1; #Upper BCs: M[-1,-2] = -1; M[-1,-1] = 1; #Convert mass matrix to CSR format: Mx = M.tocsr(); #and solve: p_current = spsolve(Mx, RHS); #Store solutions: ps[tc_idx, tk,:] = p_current; #A loop #t loop #Return: def visualize_me(ps, tcs, adjoint_source): soln_fig = figure() rewards_fig = figure(); mod_steps = 20#64; num_cols = 4; num_rows = ceil(double(self._num_steps())/num_cols / mod_steps) + 1 #time plots: for tk in xrange(1,self._num_steps()): step_idx = self._num_steps() - tk - 2; if 0 == mod(step_idx,mod_steps) or 0 == tk or self._num_steps() - 2 == tk: plt_idx = 1 + floor(step_idx / mod_steps) + int(0 == tk) #param plots: for tc_idx, A in enumerate(tcs): ax = soln_fig.add_subplot(num_rows, num_cols, plt_idx) ax.plot(xs, ps[tc_idx,tk,:]); if self._num_steps() - 2 == tk: ax.hold(True) ax.plot(xs,ps[tc_idx, tk+1,:], 'k+', label='TCs') ax.set_title('tk=%d'%tk) ax.set_ylabel('$p(x)$') ax = rewards_fig.add_subplot(num_rows, num_cols, plt_idx) ax.plot(xs[1:-1], adjoint_source [tc_idx, tk,:]) ax.set_title('tk=%d'%tk) ax.set_ylabel(r'$r(x | \theta)$') for fig in [soln_fig, rewards_fig]: fig.canvas.manager.window.showMaximized() if visualize: visualize_me(ps, tcs, adjoint_source) return ps
nn = 10000 # size of the matrix nz = 3 * nn # number of non zero terms i = np.random.randint(0, nn - 1, nz) j = np.random.randint(0, nn - 1, nz) x = np.random.normal(size=nz) dd = pd.DataFrame({"i": i, "j": j, "x": x}) dd = pd.concat([dd, dd.rename(columns={ 'i': 'j', 'j': 'i' })], sort=False).query('i!=j') diag = pd.DataFrame({'i': range(nn), 'j': range(nn), 'x': 10}) dd = pd.concat([dd, diag]) M = csc_matrix((dd.x, (dd.i, dd.j)), shape=(nn, nn)) b = np.random.normal(size=nn) #M = M.tocsr() time_start = time.clock() #lu = sla.splu(M) #x = spla.spsolve(M,b,use_umfpack=False) #x = lu.solve(b) # x = spla.cg(M,b)[0] # x = pypardiso.spsolve(M,b) x = linsolve.spsolve(M, rhs) time_elapsed = (time.clock() - time_start) mse = np.power(M.dot(x) - b, 2.0).mean() #mse= 0 print(" time = {} error = {}".format(time_elapsed, mse))
def solve(self, alphas, thetas, visualize=False): dx, dt = self._dx, self._dt; xs, ts = self._xs, self._ts; mu, beta = self._mu, self._beta num_thetas = len(thetas) #Allocate memory for solution: Fs = zeros((num_thetas, self._num_steps(), self._num_nodes() )); #Impose ICs: initial_distribution = ones_like(xs) * (xs > .0); Fs[:, 0, :] = array(list(initial_distribution)*num_thetas).reshape((num_thetas,-1)); if visualize: figure(100); hold(True) for theta_idx in xrange(num_thetas): plot(xs, Fs[theta_idx, 0, :]); title('INITIAL CONDITIONS:'); xlim((xs[0], xs[-1]) ) ylim((-.1, 1.1)) #Solve it using C-N/C-D: D = beta * beta / 2.; #the diffusion coeff #AlloCATE mass mtx: M = lil_matrix((self._num_nodes() - 1, self._num_nodes() - 1)); e = ones(self._num_nodes() - 1); dx_sqrd = dx * dx; d_on = D * dt / dx_sqrd; centre_diag = e + d_on; centre_diag[-1] = 1.0; M.setdiag(centre_diag) for tk in xrange(1, self._num_steps()): # t_prev = ts[tk-1] t_next = ts[tk] alpha_prev = alphas[tk-1] alpha_next = alphas[tk] for theta_idx, theta in enumerate(thetas): #Rip the previous time solution: F_prev = Fs[theta_idx, tk - 1, :]; if max(abs(F_prev)) < 1e-5: continue #Advection coefficient: U_prev = -(mu + alpha_prev - theta*xs); U_next = -(mu + alpha_next - theta*xs); #Form the right hand side: L_prev = U_prev[1:] * r_[ ((F_prev[2:] - F_prev[:-2]) / 2. / dx, (F_prev[-1] - F_prev[-2]) / dx)] + \ D * r_[(diff(F_prev, 2), - F_prev[-1] + F_prev[-2])] / dx_sqrd; #the last term comes from the Neumann BC: RHS = F_prev[1:] + .5 * dt * L_prev; #impose the right BCs: RHS[-1] = 0.; #Reset the 'mass' matrix: flow = .5 * dt / dx / 2. * U_next[1:]; d_off = -.5 * D * dt / dx_sqrd; # d_on = D * dt / dx_sqrd; #With Scipy .11 we have the nice diags function: #TODO: local Peclet number should determine whether we central diff, or upwind it! L_left = d_off + flow; M.setdiag(r_[(L_left[1:-1], -1.0)], -1); L_right = d_off - flow; M.setdiag(r_[(L_right[:-1])], 1); #Thomas Solve it: Mx = M.tocsr() F_next = spsolve(Mx, RHS); if visualize: if rand() < 1./ (1+ log(self._num_steps())): figure() plot(xs[1:], F_next); title('t=' + str(t_next) + ' \theta = %.2g'%theta); #Store solution: Fs[theta_idx, tk, 1:] = F_next; #Break out of loop? if amax(Fs[:, tk, :]) < 1e-5: break #Return: return Fs
def _vsolve(self, As, pAs, fs, params, alpha_bounds, visualize=False, save_fig=False): c, sigma = [x for x in params] dx, dt = self._dx, self._dt; xs, ts = self._xs, self._ts; Ahat = dot(As,pAs) if visualize: print 'abounds = ',alpha_bounds print 'Tf = %.2f' %self.getTf() print 'Ahat = ', Ahat #Allocate memory for solution: ws = zeros((self._num_steps(), self._num_nodes() )); cs = zeros((self._num_steps(), self._num_nodes()-2 )) #WARNING:!!! fs[fs<0]= 1e-8; fs_averaged = tensordot(pAs, fs, axes=1); incremental_MI = -log(fs_averaged); for idx, pA in enumerate(pAs): incremental_MI += log(fs[idx,:,:])*pA # incremental_MI[:, 99:] = incremental_MI[:, 98::-1] # incremental_MI = tile(-(xs[1:-1] - xs[0])*(xs[1:-1] - xs[-1]), # (self._num_steps(),1)) #Impose TCs: #already done they are 0 #Solve it using C-N/C-D: D = sigma * sigma / 2.; #the diffusion coeff dx_sqrd = dx * dx; #Allocate mass mtx: active_nodes = self._num_nodes() M = lil_matrix((active_nodes, active_nodes)); #Centre Diagonal: e = ones(active_nodes); d_on = D * dt / dx_sqrd; centre_diag = e + d_on; M.setdiag(centre_diag) # #Bottom BCs \di_x w = 0: # M[0,0] = -1; # M[0,1] = 1; # #Upper BCs: # M[-1,-2] = -1; # M[-1,-1] = 1; soln_fig = None; rewards_fig = None; if visualize: soln_fig = figure() rewards_fig = figure(); energy_eps, alpha_min, alpha_max = .0001, alpha_bounds[0], alpha_bounds[1] def calc_control(di_x_v): alpha_reg = -di_x_v / (2.*energy_eps) e = ones_like(alpha_reg) alpha_bounded_below = amax(c_[alpha_min*e, alpha_reg], axis=1) return amin(c_[alpha_max*e, alpha_bounded_below], axis=1) for tk in xrange(self._num_steps()-2,-1, -1): #Rip the forward-in-time solution: w_forward = ws[tk+1,:]; di_x_w_forward = (w_forward[2:] - w_forward[:-2]) / (2*dx) di2_x_w_forward = (w_forward[2:] - 2*w_forward[1:-1] + w_forward[:-2]) / (dx_sqrd) #Rip the control: alpha= calc_control(di_x_w_forward) # alpha = ones_like(di_x_w_forward)*sign(xs[1:-1]) #Calculate the velocity field active_xs = xs[1:-1] U = -(4*active_xs**3 -\ Ahat*active_xs*exp(-1/2*(active_xs/c)**2 ) / c**2 - \ 4*active_xs) + alpha; incremental_MI_forward = incremental_MI[tk+1,:]; #Form the RHS: L_prev = D * di2_x_w_forward + \ U * di_x_w_forward + \ 2*incremental_MI_forward; #impose the x_min BCs: homogeneous Neumann: and assemble the RHS: RHS = r_[(.0, w_forward[1:-1] + .5 * dt * L_prev, .0)]; #Reset the Mass Matrix: #Lower Diagonal u = U / (2*dx); d_off = D / dx_sqrd; L_left = -.5*dt*(d_off - u); M.setdiag(L_left, -1); #Upper Diagonal L_right = -.5*dt*(d_off + u); M.setdiag(r_[NaN, L_right], 1); #Bottom BCs \di_x w = 0: M[0,0] = -1; M[0,1] = 1; #Upper BCs: M[-1,-2] = -1; M[-1,-1] = 1; #Convert mass matrix to CSR format: Mx = M.tocsr(); #and solve: w_current = spsolve(Mx, RHS); #Store solutions: ws[tk,:] = w_current; #store control: cs[tk,:] = alpha; if visualize: mod_steps = 20#64; num_cols = 4; num_rows = ceil(double(self._num_steps())/num_cols / mod_steps) + 1 step_idx = self._num_steps() - 2 - tk; if 0 == mod(step_idx,mod_steps) or 0 == tk or self._num_steps() - 2 == tk: plt_idx = 1 + floor(step_idx / mod_steps) + int(0 == tk) ax = soln_fig.add_subplot(num_rows, num_cols, plt_idx) ax.plot(xs, ws[tk,:], 'b'); if self._num_steps() - 2 == tk: ax.hold(True) ax.plot(xs, ws[tk+1,:], 'k+', label='TCs') ax.set_title('tk=%d'%tk) ax.set_ylabel('$w(x)$') ax = rewards_fig.add_subplot(num_rows, num_cols, plt_idx) ax.plot(xs[1:-1], incremental_MI[tk,:]) ax.set_title('tk=%d'%tk) ax.set_ylabel('$r(x)$') # ax.legend(loc='upper left') # ax.set_title('k = %d'%tk); # ticks = ax.get_xticklabels() # for t in ticks: # t.set_visible(False) # ax.set_xlabel('$x$'); #Return: if visualize: control_fig = figure() for tk in xrange(0, cs.shape[0], 50): plot(xs[1:-1], cs[tk, :], label='tk='+str(tk)) legend() for fig in [soln_fig, rewards_fig]: fig.canvas.manager.window.showMaximized() # if save_fig: # file_name = os.path.join(FIGS_DIR, 'f_t=%.0f_b=%.0f.png'%(10*tauchar, 10*beta)) # print 'saving to ', file_name # soln_fig.savefig(file_name) return ws, cs
e03 = 2 e04 = 3 e12 = 4 e13 = 5 e14 = 6 e23 = 7 e24 = 8 e34 = 9 # A, the potential difference matrix A[[e01, e02, e03, e04], 0] = -1 A[[e12, e13, e14], 1] = -1 A[[e23, e24], 2] = -1 A[e34, 3] = -1 A[[e03, e13, e23], 3] = 1 A[[e02, e12], 2] = 1 A[e01, 1] = 1 x = np.array([1.0, 1.0, 1.0, 1.0]) for i in xrange(100): #Y = [Y01, Y02, 0, 0, 0, Y13, Yg, Y23, Yg, Yg] Y = [Y01, Y02, 0, 0, 0, Y13*x[2], Yg, Y23*x[1], Yg, Yg] G = make_diag(Y) f = np.array(([1,0,0,0])) S = A.T * G * A x = linsolve.spsolve(S, f) #x = (x + newx) / 2 x /= x[0] print x
def solve_radiating(self, energy): data = self.compute_bcs(energy) domain = self.domain # shorthand dx = domain.dx dy = domain.dy Ad = defaultdict(np.complex) b = np.zeros(domain.variables, dtype=np.complex) def processUpper(x, y): i = domain.mapping[x][y] if domain.cells[x][y + 1] == CellType.DOMAIN: ni = domain.mapping[x][y + 1] Ad[(i, ni)] += 1 / dy**2 elif domain.cells[x][y + 1] == CellType.DIRICHLET: b[i] -= 1 / dy**2 * data[x][y + 1] else: raise RuntimeError("SHH") # TODO handle radiating BCs def processLower(x, y): i = domain.mapping[x][y] if domain.cells[x][y - 1] == CellType.DOMAIN: ni = domain.mapping[x][y - 1] Ad[(i, ni)] += 1 / dy**2 elif domain.cells[x][y - 1] == CellType.DIRICHLET: b[i] -= 1 / dy**2 * data[x][y - 1] else: raise RuntimeError("SHH") # TODO handle radiating BCs def processLeft(x, y): i = domain.mapping[x][y] ncell = domain.cells[x - 1][y] if ncell == CellType.DOMAIN: ni = domain.mapping[x - 1][y] Ad[(i, ni)] += 1 / dx**2 elif ncell == CellType.RADIATING_FROM_RIGHT: # psi = psi_inc + R e^{-i kk1 x} # (psi - psi_inc)' = -i kk1 (psi - psi_inc) # (psi_{n + 1} - psi_{n - 1}) / 2 dx -psi_inc' = -i kk1 (psi_n - psi_inc) # psi_{n - 1} = psi_{n + 1} + 2 dx (-psi_inc' + i kk1 psi_n - i kk1 psi_inc) (inc, incdx, kk) = data[x - 1][y] ri = domain.mapping[x + 1][y] Ad[(i, ri)] += 1 / dx**2 Ad[(i, i)] += 1 / dx**2 * (2 * dx * I * kk) b[i] -= 1 / dx**2 * (2 * dx * (-incdx - I * kk * inc)) elif ncell == CellType.DIRICHLET: b[i] -= 1 / dx**2 * data[x - 1][y] else: raise RuntimeError("SHH") def processRight(x, y): i = domain.mapping[x][y] ncell = domain.cells[x + 1][y] if ncell == CellType.DOMAIN: ri = domain.mapping[x + 1][y] Ad[(i, ri)] += 1 / dx**2 elif ncell == CellType.RADIATING_FROM_LEFT: # psi = T e^{i kk1 x} # psi' = i kk psi # (psi_{n + 1} - psi_{n - 1}) / 2 dx = i kk psi_n # psi_{n + 1} = psi_{n - 1} + 2 dx i kk psi_n (inc, incdx, kk) = data[x + 1][y] li = domain.mapping[x - 1][y] Ad[(i, i)] += 1 / dx**2 * (2 * dx * I * kk) Ad[(i, li)] += 1 / dx**2 * 1 # TODO use data elif ncell == CellType.DIRICHLET: b[i] -= 1 / dx**2 * data[x + 1][y] else: raise RuntimeError("SHH") def process(x, y): i = domain.mapping[x][y] Ad[(i, i)] += -2 / dx**2 Ad[(i, i)] += -2 / dy**2 Ad[(i, i)] += energy for x in range(domain.L): for y in range(domain.H): if domain.cells[x][y] == CellType.DOMAIN: process(x, y) processLeft(x, y) processRight(x, y) processLower(x, y) processUpper(x, y) row = [i for (i, _) in Ad.keys()] col = [j for (_, j) in Ad.keys()] data = list(Ad.values()) A = csr_matrix((data, (row, col)), dtype=np.complex) # print(A.todense()) # print(b) w = spsolve(A, b) wf = np.zeros((domain.L, domain.H), dtype=np.complex) for x in range(domain.L): for y in range(domain.H): if domain.cells[x][y] == CellType.DOMAIN: i = domain.mapping[x][y] wf[x][y] = w[i] return wf
e03 = 2 e04 = 3 e12 = 4 e13 = 5 e14 = 6 e23 = 7 e24 = 8 e34 = 9 # A, the potential difference matrix A[[e01, e02, e03, e04], 0] = -1 A[[e12, e13, e14], 1] = -1 A[[e23, e24], 2] = -1 A[e34, 3] = -1 A[[e03, e13, e23], 3] = 1 A[[e02, e12], 2] = 1 A[e01, 1] = 1 x = np.array([1.0, 1.0, 1.0, 1.0]) for i in xrange(100): #Y = [Y01, Y02, 0, 0, 0, Y13, Yg, Y23, Yg, Yg] Y = [Y01, Y02, 0, 0, 0, Y13 * x[2], Yg, Y23 * x[1], Yg, Yg] G = make_diag(Y) f = np.array(([1, 0, 0, 0])) S = A.T * G * A x = linsolve.spsolve(S, f) #x = (x + newx) / 2 x /= x[0] print x
def simcond(self, xo, method='approx', i_unknown=None): """ Simulate values conditionally on observed known values Parameters ---------- x : vector timeseries including missing data. (missing data must be NaN if i_unknown is not given) Assumption: The covariance of x is equal to self and have the same sample period. method : string defining method used in the conditional simulation. Options are: 'approximate': Condition only on the closest points. Quite fast 'exact' : Exact simulation. Slow for large data sets, may not return any result due to near singularity of the covariance matrix. i_unknown : integers indices to spurious or missing data in x Returns ------- sample : ndarray a random sample of the missing values conditioned on the observed data. mu, sigma : ndarray mean and standard deviation, respectively, of the missing values conditioned on the observed data. Notes ----- SIMCOND generates the missing values from x conditioned on the observed values assuming x comes from a multivariate Gaussian distribution with zero expectation and Auto Covariance function R. See also -------- CovData1D.sim TimeSeries.reconstruct, rndnormnd Reference --------- Brodtkorb, P, Myrhaug, D, and Rue, H (2001) "Joint distribution of wave height and wave crest velocity from reconstructed data with application to ringing" Int. Journal of Offshore and Polar Engineering, Vol 11, No. 1, pp 23--32 Brodtkorb, P, Myrhaug, D, and Rue, H (1999) "Joint distribution of wave height and wave crest velocity from reconstructed data" in Proceedings of 9th ISOPE Conference, Vol III, pp 66-73 """ x = atleast_1d(xo).ravel() acf = self._get_acf() num_x = len(x) num_acf = len(acf) if i_unknown is not None: x[i_unknown] = nan i_unknown = flatnonzero(isnan(x)) num_unknown = len(i_unknown) mu1o = zeros((num_unknown,)) mu1o_std = zeros((num_unknown,)) sample = zeros((num_unknown,)) if num_unknown == 0: warnings.warn('No missing data, no point to continue.') return sample, mu1o, mu1o_std if num_unknown == num_x: warnings.warn('All data missing, returning sample from' + ' the apriori distribution.') mu1o_std = ones(num_unknown) * sqrt(acf[0]) return self.sim(ns=num_unknown, cases=1)[:, 1], mu1o, mu1o_std i_known = flatnonzero(1 - isnan(x)) if method.startswith('exac'): # exact but slow. It also may not return any result if num_acf > 0.3 * num_x: Sigma = toeplitz(hstack((acf, zeros(num_x - num_acf)))) else: acf[0] = acf[0] * 1.00001 Sigma = sptoeplitz(hstack((acf, zeros(num_x - num_acf)))) Soo, So1, S11 = self._split_cov(Sigma, i_known, i_unknown) if issparse(Sigma): So1 = So1.todense() S11 = S11.todense() S1o_Sooinv = spsolve(Soo + Soo.T, 2 * So1).T else: Sooinv_So1, _res, _rank, _s = lstsq(Soo + Soo.T, 2 * So1, cond=1e-4) S1o_Sooinv = Sooinv_So1.T mu1o = S1o_Sooinv.dot(x[i_known]) Sigma1o = S11 - S1o_Sooinv.dot(So1) if (diag(Sigma1o) < 0).any(): raise ValueError('Failed to converge to a solution') mu1o_std = sqrt(diag(Sigma1o)) sample[:] = rndnormnd(mu1o, Sigma1o, cases=1).ravel() elif method.startswith('appr'): # approximating by only condition on the closest points Nsig = min(2 * num_acf, num_x) Sigma = toeplitz(hstack((acf, zeros(Nsig - num_acf)))) overlap = int(Nsig / 4) # indices to the points used idx = r_[0:Nsig] + max(0, min(i_unknown[0] - overlap, num_x - Nsig)) mask_unknown = zeros(num_x, dtype=bool) # temporary storage of indices to missing points mask_unknown[i_unknown] = True t_unknown = where(mask_unknown[idx])[0] t_known = where(1 - mask_unknown[idx])[0] ns = len(t_unknown) # number of missing data in the interval num_restored = 0 # number of previously simulated points x2 = x.copy() while ns > 0: Soo, So1, S11 = self._split_cov(Sigma, t_known, t_unknown) if issparse(Soo): So1 = So1.todense() S11 = S11.todense() S1o_Sooinv = spsolve(Soo + Soo.T, 2 * So1).T else: Sooinv_So1, _res, _rank, _s = lstsq(Soo + Soo.T, 2 * So1, cond=1e-4) S1o_Sooinv = Sooinv_So1.T Sigma1o = S11 - S1o_Sooinv.dot(So1) if (diag(Sigma1o) < 0).any(): raise ValueError('Failed to converge to a solution') ix = slice((num_restored), (num_restored + ns)) # standard deviation of the expected surface mu1o_std[ix] = np.maximum(mu1o_std[ix], sqrt(diag(Sigma1o))) # expected surface conditioned on the closest known # observations from x mu1o[ix] = S1o_Sooinv.dot(x2[idx[t_known]]) # sample conditioned on the known observations from x mu1os = S1o_Sooinv.dot(x[idx[t_known]]) sample[ix] = rndnormnd(mu1os, Sigma1o, cases=1) if idx[-1] == num_x - 1: ns = 0 # no more points to simulate else: x2[idx[t_unknown]] = mu1o[ix] # expected surface x[idx[t_unknown]] = sample[ix] # sampled surface # removing indices to data which has been simulated mask_unknown[idx[:-overlap]] = False # data we want to simulate once more nw = sum(mask_unknown[idx[-overlap:]] is True) num_restored += ns - nw # update # points simulated so far idx = self._update_window(idx, i_unknown, num_x, num_acf, overlap, nw, num_restored) # find new interval with missing data t_unknown = flatnonzero(mask_unknown[idx]) t_known = flatnonzero(1 - mask_unknown[idx]) ns = len(t_unknown) # # missing data in the interval return sample, mu1o, mu1o_std
def _fsolve(self, tcs, params, alphas, ICs = None, visualize=False): #The parameters are in order: A, c, sigma sigma, = [x for x in params] num_prior_params = len(tcs); dx, dt = self._dx, self._dt; xs, ts = self._xs, self._ts; if visualize: print 'tcs,c,sigma', tcs,c,sigma print 'Tf = %.2f' %self.getTf() print 'x-,x+ %f,%f, dx = %f, dt = %f' %(self.getXbounds()[0], self.getXbounds()[1], dx,dt) #Allocate memory for solution: fs = zeros((num_prior_params, self._num_steps(), self._num_nodes())); #Impose ICs: if None == ICs: ICs = self._getICs(xs); fs[:, 0,:] = tile( ICs , (num_prior_params, 1)) # if visualize: # figure() # subplot(311) # plot(xs, fs[0, 0,:]); ## title(r'$\alpha=%.2f, \tau=%.2f, \beta=%.2f$'%(alphas[0],tauchar, beta) + ':ICs', fontsize = 24); # xlabel('x'); ylabel('f') # subplot(312) # plot(xs, alphas); # title('Control Input', fontsize = 24) ; # xlabel('x'); ylabel(r'\alpha') #Solve it using C-N/C-D: D = sigma**2 / 2.; #the diffusion coeff dx_sqrd = dx * dx; # if visualize: # title('Drift Field', fontsize = 24) ; # xlabel('x'); ylabel(r'$U$') # subplot(313) # plot(xs, Us); #Allocate mass mtx: active_nodes = self._num_nodes() M = lil_matrix((active_nodes, active_nodes)); #Centre Diagonal: e = ones(active_nodes); d_on = D * dt / dx_sqrd; centre_diag = e + d_on; M.setdiag(centre_diag) #Off Diagonals: d_off = D / dx_sqrd; #Convert mass matrix to CSR format: for tk in xrange(1, self._num_steps()): for tc_idx, tc in enumerate(tcs): #Rip the forward-in-time solution: f_prev = fs[tc_idx, tk-1,:]; #load the drift field: Us_internal_field = -xs/tc; Us_prev = Us_internal_field + alphas[tk-1,:] Us_next = Us_internal_field + alphas[tk,:] #Form the RHS: L_prev = -(Us_prev[2:]*f_prev[2:] - Us_prev[:-2]*f_prev[:-2]) / (2.* dx) + \ D * diff(f_prev, 2) / dx_sqrd; #impose the x_min BCs: homogeneous Newmann: and assemble the RHS: RHS = r_[0., f_prev[1:-1] + .5 * dt * L_prev, 0.]; # TODO Upwind: #Lower Diagonal u = Us_next / (2*dx); L_left = -.5*dt*(d_off + u[:-2]); M.setdiag(L_left, -1); #Upper Diagonal L_right = -.5*dt*(d_off - u[2:]); M.setdiag(r_[NaN, L_right], 1); #Bottom BCs: M[0,0] = Us_next[0] + D / dx; M[0,1] = -D / dx; #Upper BCs: M[-1,-2] = D / dx; M[-1,-1] = Us_next[-1] - D / dx; #and solve: Mx = M.tocsr(); f_next = spsolve(Mx, RHS); #Store solutions: fs[tc_idx, tk, :] = f_next; #End ak loop #end tk loop: #Visualize: def visualize_me(fs, As): #this is a function b/c i'm too lazy to make a bookmark: soln_fig = figure() mod_steps = 20; num_cols = 4; num_rows = ceil(double(self._num_steps())/num_cols / mod_steps) # fs_stat = calculateStationary(); for tk in xrange(1,self._num_steps()): step_idx = tk; if 0 == mod(step_idx,mod_steps) or 1 == tk: for tc_idx, A in enumerate(As): plt_idx = floor(step_idx / mod_steps) + (mod_steps != 1) ax = soln_fig.add_subplot(num_rows, num_cols, plt_idx) ax.plot(xs, fs[tc_idx, tk,:], label='A=%f'%As[tc_idx]); # ax.plot(xs, fs_stat[tc_idx,:], '--') if 1 == tk: ax.hold(True) ax.plot(xs, fs[tc_idx,tk-1,:], 'r', label='ICs') # ax.legend(loc='upper left') # ax.set_title('k = %d'%tk); # if False : #(self._num_steps()-1 != tk): # ticks = ax.get_xticklabels() # for t in ticks: # t.set_visible(False) # else: ax.set_xlabel('$x$'); ax.set_ylabel('$f$') for t in ax.get_xticklabels(): t.set_visible(True) soln_fig.canvas.manager.window.showMaximized() if visualize: visualize_me(fs, tcs) return fs