def project(expr, space): u, v = TrialFunction(space), TestFunction(space) a = inner(u, v)*dx L = inner(expr, v)*dx A, b = PETScMatrix(), PETScVector() assemble_system(a, L, A_tensor=A, b_tensor=b) uh = Function(space) x = uh.vector() solve(A, x, b, 'lu') lmax = SLEPcEigenSolver(A) lmax.parameters["spectrum"] = "largest magnitude" lmax.parameters["problem_type"] = "hermitian" lmax.solve(2) lmax = max([lmax.get_eigenpair(i)[0] for i in range(lmax.get_number_converged())]) lmin = SLEPcEigenSolver(A) lmin.parameters["spectrum"] = "smallest magnitude" lmin.parameters["problem_type"] = "hermitian" lmin.solve(2) lmin = max([lmin.get_eigenpair(i)[0] for i in range(lmin.get_number_converged())]) print space.dim(), 'Cond number', lmax/lmin return uh
def __init__(self, V, A, B=None, bcs=None): self.V = V if bcs is not None: self._set_boundary_conditions(bcs) A = self._assemble_if_form(A) if B is not None: B = self._assemble_if_form(B) self._set_operators(A, B) if self.B is not None: self.eigen_solver = SLEPcEigenSolver(self.condensed_A, self.condensed_B) else: self.eigen_solver = SLEPcEigenSolver(self.condensed_A)
def solve(self, mesh, num=5): """ Solve for num eigenvalues based on the mesh. """ # conforming elements V = FunctionSpace(mesh, "CG", self.degree) u = TrialFunction(V) v = TestFunction(V) # weak formulation a = inner(grad(u), grad(v)) * dx b = u * v * ds A = PETScMatrix() B = PETScMatrix() A = assemble(a, tensor=A) B = assemble(b, tensor=B) # find eigenvalues eigensolver = SLEPcEigenSolver(A, B) eigensolver.parameters["spectral_transform"] = "shift-and-invert" eigensolver.parameters["problem_type"] = "gen_hermitian" eigensolver.parameters["spectrum"] = "smallest real" eigensolver.parameters["spectral_shift"] = 1.0E-10 eigensolver.solve(num + 1) # extract solutions lst = [ eigensolver.get_eigenpair(i) for i in range(1, eigensolver.get_number_converged()) ] for k in range(len(lst)): u = Function(V) u.vector()[:] = lst[k][2] lst[k] = (lst[k][0], u) # pair (eigenvalue,eigenfunction) return np.array(lst)
def setup_solver(self): shift = (2.0*pi*self.eigenmode_guess)**2 self.esolver = SLEPcEigenSolver(self._A, self._B) self.esolver.parameters["solver"] = "krylov-schur" self.esolver.parameters["tolerance"] = 1e-12 self.esolver.parameters["spectral_transform"] = "shift-and-invert" self.esolver.parameters["spectral_shift"] = shift self.esolver.parameters["spectrum"] = "target magnitude"
def __init__(self, mesh, materials): """ init class always require mesh and materials to build the weak form """ self.mesh = mesh self.materials = materials #FIXME throw error if not all domains are initilized self.eigenmode_guess = 1.0 self.n_modes = 10 # number of modes to solve for self.plot_eigenmodes = True self._A = PETScMatrix() self._B = PETScMatrix() self.esolver = SLEPcEigenSolver(self._A, self._B)
def compute_eig(M, filename, parameters=[]): """ Compute eigenvalues of a PETScMatrix M, and print to filename """ mpirank = MPI.rank(M.mpi_comm()) if mpirank == 0: print '\t\tCompute eigenvalues' eigsolver = SLEPcEigenSolver(M) eigsolver.parameters.update(parameters) eigsolver.solve() if mpirank == 0: print '\t\tSort eigenvalues' eig = [] for ii in range(eigsolver.get_number_converged()): eig.append(eigsolver.get_eigenvalue(ii)[0]) eig.sort() print '\t\tPrint results to file' np.savetxt(filename, np.array(eig))
def _assemble(self): # Get input: self.gamma = self.Parameters['gamma'] if self.Parameters.has_key('beta'): self.beta = self.Parameters['beta'] else: self.beta = 0.0 self.Vm = self.Parameters['Vm'] if self.Parameters.has_key('m0'): self.m0 = self.Parameters['m0'].copy(deepcopy=True) isFunction(self.m0) else: self.m0 = Function(self.Vm) self.mtrial = TrialFunction(self.Vm) self.mtest = TestFunction(self.Vm) self.mysample = Function(self.Vm) self.draw = Function(self.Vm) # Assemble: self.R = assemble(inner(nabla_grad(self.mtrial), \ nabla_grad(self.mtest))*dx) self.M = PETScMatrix() assemble(inner(self.mtrial, self.mtest) * dx, tensor=self.M) # preconditioner is Gamma^{-1}: if self.beta > 1e-16: self.precond = self.gamma * self.R + self.beta * self.M else: self.precond = self.gamma * self.R + (1e-14) * self.M # Discrete operator K: self.K = self.gamma * self.R + self.beta * self.M # Get eigenvalues for M: self.eigsolM = SLEPcEigenSolver(self.M) self.eigsolM.solve() # Solver for M^{-1}: self.solverM = LUSolver() self.solverM.parameters['reuse_factorization'] = True self.solverM.parameters['symmetric'] = True self.solverM.set_operator(self.M) # Solver for K^{-1}: self.solverK = LUSolver() self.solverK.parameters['reuse_factorization'] = True self.solverK.parameters['symmetric'] = True self.solverK.set_operator(self.K)
def solve(self, n=None): """ solve(n=None): Solve the eigenvalue problem and return the converged eigenvalues n indicates the number of eigenvalues to be calculated """ # Standard eigenvalue problem if self.b is None: A = PETScMatrix() assemble(self.a, tensor=A) if self.bc: self.bc.apply(A) solver = SLEPcEigenSolver(A) solver.solve() # Generalized eigenvalue problem else: A = PETScMatrix() assemble(self.a, tensor=A) B = PETScMatrix() assemble(self.b, tensor=B) # Set options for eigensolver solver = SLEPcEigenSolver(A, B) for key, key_info in self.parameters.iterdata(): solver.parameters[key] = self.parameters[key] if n is None: n = A.size(0) if self.bc: self.bc.apply(A) self.bc.apply(B) solver.solve(n) # Pick real part of eigenvalues computed m = solver.get_number_converged() complex_eps = 0.001 eigenvalues = [solver.get_eigenvalue(i)[0] for i in range(m) if abs(solver.get_eigenvalue(i)[1]) < complex_eps] if len(eigenvalues) == 0: raise RuntimeError("No real-valued eigenvalues found") # Compute all eigenvalues if eigenvalue is zero and not only # testing for stability if (n < A.size(0) and abs(eigenvalues[0]) < ascot_parameters["eps"] and not ascot_parameters["only_stable"]): info("Only zero eigenvalues detected. Computing all.") solver.solve(A.size(0)) m = solver.get_number_converged() eigenvalues = [solver.get_eigenvalue(i)[0] for i in range(m) if abs(solver.get_eigenvalue(i)[1]) < 0.1] return eigenvalues
def solve(self): """ Find eigenvalues for transformed mesh. """ self.progress("Building mesh.") # build transformed mesh mesh = self.refineMesh() # dim = mesh.topology().dim() if self.bcLast: mesh = transform_mesh(mesh, self.transformList) Robin, Steklov, shift, bcs = get_bc_parts(mesh, self.bcList) else: Robin, Steklov, shift, bcs = get_bc_parts(mesh, self.bcList) mesh = transform_mesh(mesh, self.transformList) # boundary conditions computed on non-transformed mesh # copy the values to transformed mesh fun = FacetFunction("size_t", mesh, shift) fun.array()[:] = bcs.array()[:] bcs = fun ds = Measure('ds', domain=mesh, subdomain_data=bcs) V = FunctionSpace(mesh, self.method, self.deg) u = TrialFunction(V) v = TestFunction(V) self.progress("Assembling matrices.") wTop = Expression(self.wTop) wBottom = Expression(self.wBottom) # # build stiffness matrix form # s = dot(grad(u), grad(v)) * wTop * dx # add Robin parts for bc in Robin: s += Constant(bc.parValue) * u * v * wTop * ds(bc.value + shift) # # build mass matrix form # if len(Steklov) > 0: m = 0 for bc in Steklov: m += Constant( bc.parValue) * u * v * wBottom * ds(bc.value + shift) else: m = u * v * wBottom * dx # assemble # if USE_EIGEN: # S, M = EigenMatrix(), EigenMatrix() # tempv = EigenVector() # else: S, M = PETScMatrix(), PETScMatrix() # tempv = PETScVector() if not np.any(bcs.array() == shift + 1): # no Dirichlet parts assemble(s, tensor=S) assemble(m, tensor=M) else: # # with EIGEN we could # apply Dirichlet condition symmetrically # completely remove rows and columns # # Dirichlet parts are marked with shift+1 # # temp = Constant(0)*v*dx bc = DirichletBC(V, Constant(0.0), bcs, shift + 1) # assemble_system(s, temp, bc, A_tensor=S, b_tensor=tempv) # assemble_system(m, temp, bc, A_tensor=M, b_tensor=tempv) assemble(s, tensor=S) bc.apply(S) assemble(m, tensor=M) # bc.zero(M) # if USE_EIGEN: # M = M.sparray() # M.eliminate_zeros() # print M.shape # indices = M.indptr[:-1] - M.indptr[1:] < 0 # M = M[indices, :].tocsc()[:, indices] # S = S.sparray()[indices, :].tocsc()[:, indices] # print M.shape # # solve the eigenvalue problem # self.progress("Solving eigenvalue problem.") eigensolver = SLEPcEigenSolver(S, M) eigensolver.parameters["problem_type"] = "gen_hermitian" eigensolver.parameters["solver"] = "krylov-schur" if self.target is not None: eigensolver.parameters["spectrum"] = "target real" eigensolver.parameters["spectral_shift"] = self.target else: eigensolver.parameters["spectrum"] = "smallest magnitude" eigensolver.parameters["spectral_shift"] = -0.01 eigensolver.parameters["spectral_transform"] = "shift-and-invert" eigensolver.solve(self.number) self.progress("Generating eigenfunctions.") if eigensolver.get_number_converged() == 0: return None eigf = [] eigv = [] if self.deg > 1: mesh = refine(mesh) W = FunctionSpace(mesh, 'CG', 1) for i in range(eigensolver.get_number_converged()): pair = eigensolver.get_eigenpair(i)[::2] eigv.append(pair[0]) u = Function(V) u.vector()[:] = pair[1] eigf.append(interpolate(u, W)) return eigv, eigf
def standard_solver(K, M): solver = SLEPcEigenSolver(K, M) solver.parameters['spectrum'] = 'smallest magnitude' solver.parameters['tolerance'] = 1e-4 solver.parameters['problem_type'] = 'pos_gen_non_hermitian' return solver