def __init__(self, A, solver=default_solver, parameters={}): from PyTrilinos import Epetra, Amesos from dolfin import info from time import time self.A = A # Keep reference T = time() self.problem = Epetra.LinearProblem() self.problem.SetOperator(A.down_cast().mat()) self.solver = Amesos.Factory().Create(solver, self.problem) if (self.solver == None): raise RuntimeError('Failed to create Amesos solver: ' + solver) # This prevents a use-after-free crash for the MPI communicator. It # enforces that the solver is destroyed before A. self.solver.A = A self.solver.SetParameters(parameters) if self.solver is None: raise RuntimeError("Unknown solver '%s'" % solver) err = self.solver.SymbolicFactorization() if err != 0: raise RuntimeError("Amesos " + solver + " symbolic factorization failed, err=%d" % err) err = self.solver.NumericFactorization() if err != 0: raise RuntimeError("Amesos " + solver + " numeric factorization failed, err=%d" % err) info('constructed direct solver (using %s) in %.2f s' % (solver, time() - T))
def __init__(self, tolerance=1e-10, iterations=10, precon=None, maxIterations=10): """ :Parameters: - `tolerance`: The required error tolerance. - `iterations`: The maximum number of iterative steps to perform. """ iterations = min(iterations, maxIterations) TrilinosSolver.__init__(self, tolerance=tolerance, iterations=iterations, precon=None) if precon is not None: import warnings warnings.warn( "Trilinos KLU solver does not accept preconditioners.", UserWarning, stacklevel=2) self.Factory = Amesos.Factory()
def solve_direct(A, rhs, x=None): if x is None: x = Epetra.Vector(A.RangeMap()) problem = Epetra.LinearProblem(A, x, rhs) solver = Amesos.Klu(problem) ierr = solver.Solve() assert (ierr == 0), ierr return x
def query(which=None): """Return list of available solver backends, or True/False if given a solver name""" from PyTrilinos import Amesos factory = Amesos.Factory() if which is None: avail = [] for s in serial_solvers + parallel_solvers: if factory.Query(s): avail.append(s) return avail return factory.Query(which)
def direct_solve(self, jac, rhs): '''Currently unused direct solver that was used for testing.''' A = Epetra.CrsMatrix(Epetra.Copy, self.map, 27) for i in range(len(jac.begA)-1): if i == self.dim: A[i, i] = -1 continue for j in range(jac.begA[i], jac.begA[i+1]): if jac.jcoA[j] != self.dim: A[i, jac.jcoA[j]] = jac.coA[j] A.FillComplete() rhs[self.dim] = 0 x = Vector(rhs) problem = Epetra.LinearProblem(A, x, rhs) factory = Amesos.Factory() solver = factory.Create('Klu', problem) solver.SymbolicFactorization() solver.NumericFactorization() solver.Solve() return x
def __init__(self, ckt): # Init base class _NLFunction.__init__(self) # Save ckt instance self.ckt = ckt # Make sure circuit is ready (analysis should take care) assert ckt.nD_ref # Allocate matrices/vectors # Create Epetra CrsMatrix: need communicator and map comm = Epetra.SerialComm() # Map: numelem, base index, communicator map = Epetra.Map(self.ckt.nD_dimension, 0, comm) # TODO: Find a good estimate for nnzRow nnzRow = min(10, self.ckt.nD_dimension) # G here is G1 = G + G0 in documentation self.G = Epetra.CrsMatrix(Epetra.Copy, map, nnzRow) # Jac is (G1 + di/dv) in doc self.Jac = Epetra.CrsMatrix(Epetra.Copy, map, nnzRow) # Allocate several vectors self.xVec = Epetra.Vector(map) self.iVec = Epetra.Vector(map) self.sVec = Epetra.Vector(map) self.errVec = Epetra.Vector(map) self.deltaxVec = Epetra.Vector(map) if hasattr(self.ckt, 'nD_namRClist'): # Allocate external currents vector self.extSVec = np.empty(self.ckt.nD_dimension) # Generate G and Jac sparse matrices # ---------------------------------- self._get_Gnz() self.Jacnz = [([], []) for i in xrange(self.ckt.nD_dimension)] # Insert linear contributions into G and Jac (to fix structure) for row, data in enumerate(self.Gnz): self.G.InsertGlobalValues(row, *data) self.Jac.InsertGlobalValues(row, *data) # Finalize G (which should not change any more unless parameter sweep) assert not self.G.FillComplete() assert not self.G.OptimizeStorage() # Add nonlinear contribution to Jac. Insert ones for now as the # matrix values will be discarded anyway. for elem in self.ckt.nD_nlinElem: outJac = np.ones((len(elem.csOutPorts), len(elem.controlPorts)), dtype=float) set_Jac(self.Jacnz, elem.nD_cpos, elem.nD_cneg, elem.nD_vpos, elem.nD_vneg, outJac) for row, data in enumerate(self.Jacnz): self.Jac.InsertGlobalValues(row, *data) # Finalize and symbolically factor Jac assert not self.Jac.FillComplete() assert not self.Jac.OptimizeStorage() # Create pytrilinos solver problem = Epetra.LinearProblem(self.Jac, self.deltaxVec, self.errVec) factory = Amesos.Factory() self.solver = factory.Create("Klu", problem) assert not self.solver.SymbolicFactorization()
def run_solver(self, interpolation_method): """Run solver.""" self.interpolation_method = interpolation_method t0 = time.time() n_vertex = len(set(self.mesh_data.all_nodes) - self.dirichlet_nodes) print("interpolation runing...") self.get_nodes_weights(interpolation_method) print( "done interpolation...", "took {0} seconds to interpolate over {1} verts".format( time.time() - t0, n_vertex ), ) print("filling the transmissibility matrix...") begin = time.time() try: for volume in self.volumes: volume_id = self.mb.tag_get_data(self.global_id_tag, volume)[ 0 ][0] RHS = self.mb.tag_get_data(self.source_tag, volume)[0][0] self.Q[volume_id] += RHS # self.Q[volume_id, 0] += RHS except Exception: pass for face in self.neumann_faces: face_flow = self.mb.tag_get_data(self.neumann_tag, face)[0][0] volume = self.mtu.get_bridge_adjacencies(face, 2, 3) volume = np.asarray(volume, dtype="uint64") id_volume = self.mb.tag_get_data(self.global_id_tag, volume)[0][0] face_nodes = self.mtu.get_bridge_adjacencies(face, 0, 0) node_crds = self.mb.get_coords(face_nodes).reshape([3, 3]) face_area = geo._area_vector(node_crds, norma=True) RHS = face_flow * face_area self.Q[id_volume] += -RHS # self.Q[id_volume, 0] += - RHS id_volumes = [] all_LHS = [] for face in self.dirichlet_faces: # '2' argument was initially '0' but it's incorrect I, J, K = self.mtu.get_bridge_adjacencies(face, 2, 0) left_volume = np.asarray( self.mtu.get_bridge_adjacencies(face, 2, 3), dtype="uint64" ) id_volume = self.mb.tag_get_data(self.global_id_tag, left_volume)[ 0 ][0] id_volumes.append(id_volume) JI = self.mb.get_coords([I]) - self.mb.get_coords([J]) JK = self.mb.get_coords([K]) - self.mb.get_coords([J]) LJ = ( self.mb.get_coords([J]) - self.mesh_data.mb.tag_get_data( self.volume_centre_tag, left_volume )[0] ) N_IJK = np.cross(JI, JK) / 2.0 _test = np.dot(LJ, N_IJK) if _test < 0.0: I, K = K, I JI = self.mb.get_coords([I]) - self.mb.get_coords([J]) JK = self.mb.get_coords([K]) - self.mb.get_coords([J]) N_IJK = np.cross(JI, JK) / 2.0 tan_JI = np.cross(N_IJK, JI) tan_JK = np.cross(N_IJK, JK) self.mb.tag_set_data(self.normal_tag, face, N_IJK) face_area = np.sqrt(np.dot(N_IJK, N_IJK)) h_L = geo.get_height(N_IJK, LJ) g_I = self.get_boundary_node_pressure(I) g_J = self.get_boundary_node_pressure(J) g_K = self.get_boundary_node_pressure(K) K_L = self.mb.tag_get_data(self.perm_tag, left_volume).reshape( [3, 3] ) K_n_L = self.vmv_multiply(N_IJK, K_L, N_IJK) K_L_JI = self.vmv_multiply(N_IJK, K_L, tan_JI) K_L_JK = self.vmv_multiply(N_IJK, K_L, tan_JK) D_JK = self.get_cross_diffusion_term( tan_JK, LJ, face_area, h_L, K_n_L, K_L_JK, boundary=True ) D_JI = self.get_cross_diffusion_term( tan_JI, LJ, face_area, h_L, K_n_L, K_L_JI, boundary=True ) K_eq = (1 / h_L) * (face_area * K_n_L) RHS = D_JK * (g_I - g_J) - K_eq * g_J + D_JI * (g_J - g_K) LHS = K_eq all_LHS.append(LHS) self.Q[id_volume] += -RHS # self.Q[id_volume, 0] += - RHS # self.mb.tag_set_data(self.flux_info_tag, face, # [D_JK, D_JI, K_eq, I, J, K, face_area]) all_cols = [] all_rows = [] all_values = [] self.ids = [] self.v_ids = [] self.ivalues = [] for face in self.intern_faces: left_volume, right_volume = self.mtu.get_bridge_adjacencies( face, 2, 3 ) L = self.mesh_data.mb.tag_get_data( self.volume_centre_tag, left_volume )[0] R = self.mesh_data.mb.tag_get_data( self.volume_centre_tag, right_volume )[0] dist_LR = R - L I, J, K = self.mtu.get_bridge_adjacencies(face, 0, 0) JI = self.mb.get_coords([I]) - self.mb.get_coords([J]) JK = self.mb.get_coords([K]) - self.mb.get_coords([J]) N_IJK = np.cross(JI, JK) / 2.0 test = np.dot(N_IJK, dist_LR) if test < 0: left_volume, right_volume = right_volume, left_volume L = self.mesh_data.mb.tag_get_data( self.volume_centre_tag, left_volume )[0] R = self.mesh_data.mb.tag_get_data( self.volume_centre_tag, right_volume )[0] dist_LR = R - L face_area = np.sqrt(np.dot(N_IJK, N_IJK)) tan_JI = np.cross(N_IJK, JI) tan_JK = np.cross(N_IJK, JK) K_R = self.mb.tag_get_data(self.perm_tag, right_volume).reshape( [3, 3] ) RJ = R - self.mb.get_coords([J]) h_R = geo.get_height(N_IJK, RJ) K_R_n = self.vmv_multiply(N_IJK, K_R, N_IJK) K_R_JI = self.vmv_multiply(N_IJK, K_R, tan_JI) K_R_JK = self.vmv_multiply(N_IJK, K_R, tan_JK) K_L = self.mb.tag_get_data(self.perm_tag, left_volume).reshape( [3, 3] ) LJ = L - self.mb.get_coords([J]) h_L = geo.get_height(N_IJK, LJ) K_L_n = self.vmv_multiply(N_IJK, K_L, N_IJK) K_L_JI = self.vmv_multiply(N_IJK, K_L, tan_JI) K_L_JK = self.vmv_multiply(N_IJK, K_L, tan_JK) D_JI = self.get_cross_diffusion_term( tan_JI, dist_LR, face_area, h_L, K_L_n, K_L_JI, h_R, K_R_JI, K_R_n, ) D_JK = self.get_cross_diffusion_term( tan_JK, dist_LR, face_area, h_L, K_L_n, K_L_JK, h_R, K_R_JK, K_R_n, ) K_eq = (K_R_n * K_L_n) / (K_R_n * h_L + K_L_n * h_R) * face_area id_right = self.mb.tag_get_data(self.global_id_tag, right_volume) id_left = self.mb.tag_get_data(self.global_id_tag, left_volume) col_ids = [id_right, id_right, id_left, id_left] row_ids = [id_right, id_left, id_left, id_right] values = [K_eq, -K_eq, K_eq, -K_eq] all_cols.append(col_ids) all_rows.append(row_ids) all_values.append(values) # wait for interpolation to be done self._node_treatment(I, id_left, id_right, K_eq, D_JK=D_JK) self._node_treatment( J, id_left, id_right, K_eq, D_JI=D_JI, D_JK=-D_JK ) self._node_treatment(K, id_left, id_right, K_eq, D_JI=-D_JI) # self.mb.tag_set_data(self.flux_info_tag, face, # [D_JK, D_JI, K_eq, I, J, K, face_area]) self.T.InsertGlobalValues(self.ids, self.v_ids, self.ivalues) # self.T[ # np.asarray(self.ids)[:, :, 0, 0], np.asarray(self.v_ids) # ] = np.asarray(self.ivalues) self.T.InsertGlobalValues(id_volumes, id_volumes, all_LHS) # self.T[ # np.asarray(id_volumes), np.asarray(id_volumes) # ] = np.asarray(all_LHS) self.T.InsertGlobalValues(all_cols, all_rows, all_values) # self.T[ # np.asarray(all_cols)[:, 0, 0, 0], # np.asarray(all_rows)[:, 0, 0, 0] # ] = np.asarray(all_values)[:, 0] self.T.FillComplete() mat_fill_time = time.time() - begin print("matrix fill took {0} seconds...".format(mat_fill_time)) mesh_size = len(self.volumes) print("running solver...") USE_DIRECT_SOLVER = False linearProblem = Epetra.LinearProblem(self.T, self.x, self.Q) if USE_DIRECT_SOLVER: solver = Amesos.Lapack(linearProblem) print("1) Performing symbolic factorizations...") solver.SymbolicFactorization() print("2) Performing numeric factorizations...") solver.NumericFactorization() print("3) Solving the linear system...") solver.Solve() t = time.time() - t0 print( "Solver took {0} seconds to run over {1} volumes".format( t, mesh_size ) ) else: solver = AztecOO.AztecOO(linearProblem) solver.SetAztecOption(AztecOO.AZ_solver, AztecOO.AZ_gmres) solver.SetAztecOption(AztecOO.AZ_output, AztecOO.AZ_none) # solver.SetAztecOption(AztecOO.AZ_precond, AztecOO.AZ_Jacobi) # solver.SetAztecOption(AztecOO.AZ_kspace, 1251) # solver.SetAztecOption(AztecOO.AZ_orthog, AztecOO.AZ_modified) # solver.SetAztecOption(AztecOO.AZ_conv, AztecOO.AZ_Anorm) solver.Iterate(8000, 1e-10) t = time.time() - t0 its = solver.GetAztecStatus()[0] solver_time = solver.GetAztecStatus()[6] print( "Solver took {0} seconds to run over {1} volumes".format( t, mesh_size ) ) print( "Solver converged at %.dth iteration in %3f seconds." % (int(its), solver_time) ) # self.T = self.T.tocsc() # self.Q = self.Q.tocsc() # self.x = spsolve(self.T, self.Q) # print(np.sum(self.T[50]), self.Q[50]) self.mb.tag_set_data(self.pressure_tag, self.volumes, self.x)
# } # prec = ML.MultiLevelPreconditioner(P_epetra, False) # prec.SetParameterList(mlList) # prec.ComputePreconditioner() # solver = AztecOO.AztecOO(A_epetra, x_epetra, b_epetra) # solver.SetPrecOperator(prec) # solver.SetAztecOption(AztecOO.AZ_solver, AztecOO.AZ_gmres); # solver.SetAztecOption(AztecOO.AZ_output, 100); # err = solver.Iterate(20000, 1e-10) tic() problem = Epetra.LinearProblem(A_epetra, x_epetra, b_epetra) print '\n\n\n\n\n\n' factory = Amesos.Factory() solver = factory.Create("Amesos_Umfpack", problem) # solver = factory.Create("MUMPS", problem) amesosList = {"PrintTiming": True, "PrintStatus": True} solver.SetParameters(amesosList) solver.SymbolicFactorization() solver.NumericFactorization() solver.Solve() soln = problem.GetLHS() print "||x_computed||_2 =", soln.Norm2() # solver.PrintTiming() print '\n\n\n\n\n\n' if case == 1: ue = Expression(("20*x[0]*pow(x[1],3)", "5*pow(x[0],4)-5*pow(x[1],4)")) pe = Expression("60*pow(x[0],2)*x[1]-20*pow(x[1],3)+5")
print "Matrix fill took", time.time() - t0, "seconds... Ran over ", len( volumes), "elems" mb.tag_set_data(pres_tag, volumes, np.asarray(b[v_ids])) if USE_DIRECT_SOLVER: outfile_template = "Results/output_direct_{0}.vtk" else: outfile_template = "output_iterative_fine_grid{0}.vtk" mb.write_file(outfile_template.format(0)) linearProblem = Epetra.LinearProblem(A, x, b) if USE_DIRECT_SOLVER: solver = Amesos.Lapack(linearProblem) print "1) Performing symbolic factorizations..." solver.SymbolicFactorization() print "2) Performing numeric factorizations..." solver.NumericFactorization() print "3) Solving the linear system..." ierr = solver.Solve() else: solver = AztecOO.AztecOO(linearProblem) ierr = solver.Iterate(1000, 1e-9) print " solver.Solve() return code = ", ierr