def convert(bmat, algorithm='numpy'): ''' Attempt to convert bmat to a PETSc(Matrix/Vector) object. If succed this is at worst a number. ''' # Block vec conversion if isinstance(bmat, block_vec): array = block_vec_to_numpy(bmat) vec = PETSc.Vec().createWithArray(array) return PETScVector(vec) # Conversion of bmat is bit more involved because of the possibility # that some of the blocks are numbers or composition of matrix operations if isinstance(bmat, block_mat): # Create collpsed bmat row_sizes, col_sizes = bmat_sizes(bmat) nrows, ncols = len(row_sizes), len(col_sizes) indices = itertools.product(range(nrows), range(ncols)) blocks = np.zeros((nrows, ncols), dtype='object') for block, (i, j) in zip(bmat.blocks.flatten(), indices): # This might is guaranteed to be matrix or number A = collapse(block) # Only numbers on the diagonal block are interpresented as # scaled identity matrices if is_number(A): if A != 0: assert row_sizes[i] == col_sizes[j] A = diagonal_matrix(row_sizes[i], A) else: A = 0 # The converted block blocks[i, j] = A # Now every block is a matrix/number and we can make a monolithic thing bmat = block_mat(blocks) assert all( is_petsc_mat(block) or is_number(block) for block in bmat.blocks.flatten()) # Opt out of monolithic if not algorithm: return bmat # Monolithic via numpy (fast) # Convert to numpy array = block_mat_to_numpy(bmat) # Constuct from numpy return numpy_to_petsc(array) # Try with a composite return collapse(bmat)
def vec_context(self, readonly=True): """A context manager for a :class:`PETSc.Vec` from a :class:`Global`. :param readonly: Access the data read-only (use :meth:`Dat.data_ro`) or read-write (use :meth:`Dat.data`). Read-write access requires a halo update.""" assert self.dtype == PETSc.ScalarType, \ "Can't create Vec with type %s, must be %s" % (self.dtype, PETSc.ScalarType) acc = (lambda d: d.data_ro) if readonly else (lambda d: d.data) # Getting the Vec needs to ensure we've done all current computation. # If we only want readonly access then there's no need to # force the evaluation of reads from the Dat. self._force_evaluation(read=True, write=not readonly) if not hasattr(self, '_vec'): # Can't duplicate layout_vec of dataset, because we then # carry around extra unnecessary data. # But use getSizes to save an Allreduce in computing the # global size. size = self.dataset.layout_vec.getSizes() if self.comm.rank == 0: self._vec = PETSc.Vec().createWithArray(acc(self), size=size, bsize=self.cdim) else: self._vec = PETSc.Vec().createWithArray(np.empty( 0, dtype=self.dtype), size=size, bsize=self.cdim) # PETSc Vecs have a state counter and cache norm computations # to return immediately if the state counter is unchanged. # Since we've updated the data behind their back, we need to # change that state counter. self._vec.stateIncrease() yield self._vec if not readonly: self.comm.Bcast(acc(self), 0)
def solve(): opts = PETSc.Options() mat_filename = opts.getString('-mtx', 'mtx.dat') rhs_filename = opts.getString('-rhs', 'rhs.dat') sol0_filename = opts.getString('-sol0', '') sol_filename = opts.getString('-sol', 'sol.dat') status_filename = opts.getString('-status', 'status.txt') view_mtx = PETSc.Viewer().createBinary(mat_filename, mode='r') view_rhs = PETSc.Viewer().createBinary(rhs_filename, mode='r') mtx = PETSc.Mat().load(view_mtx) rhs = PETSc.Vec().load(view_rhs) ksp = PETSc.KSP().create() ksp.setOperators(mtx) ksp.setFromOptions() if not sol0_filename: sol = rhs.duplicate() else: view_sol0 = PETSc.Viewer().createBinary(sol0_filename, mode='r') sol = PETSc.Vec().load(view_sol0) ksp.setInitialGuessNonzero(True) tt = time.clock() ksp.solve(rhs, sol) elapsed = time.clock() - tt view_sol = PETSc.Viewer().createBinary(sol_filename, mode='w') sol.view(view_sol) fd = open(status_filename, 'w') fd.write('%d %.2f' % (ksp.reason, elapsed)) fd.close()
def _initialize_data(self, root_vector): """ Internally allocate vectors. Sets the following attributes: - _data Parameters ---------- root_vector : Vector or None the root's vector instance or None, if we are at the root. """ super(PETScVector, self)._initialize_data(root_vector) self._petsc = {} self._imag_petsc = {} for set_name, data in iteritems(self._data): if self._ncol == 1: self._petsc[set_name] = PETSc.Vec().createWithArray( data, comm=self._system.comm) else: # for now the petsc array is only the size of one column and we do separate # transfers for each column. Later we'll do it all at once and the petsc # array will be the full size of the data array (and use the same memory). self._petsc[set_name] = PETSc.Vec().createWithArray( data[:, 0].copy(), comm=self._system.comm) # Allocate imaginary for complex step if self._alloc_complex: for set_name, data in iteritems(self._imag_data): if self._ncol == 1: self._imag_petsc[set_name] = \ PETSc.Vec().createWithArray(data, comm=self._system.comm) else: self._imag_petsc[set_name] = \ PETSc.Vec().createWithArray(data[:, 0].copy(), comm=self._system.comm)
def vec_context(self, access): """A context manager for a :class:`PETSc.Vec` from a :class:`Global`. :param access: Access descriptor: READ, WRITE, or RW.""" assert self.dtype == PETSc.ScalarType, \ "Can't create Vec with type %s, must be %s" % (self.dtype, PETSc.ScalarType) # Getting the Vec needs to ensure we've done all current # necessary computation. self._force_evaluation(read=access is not base.WRITE, write=access is not base.READ) data = self._data if not hasattr(self, '_vec'): # Can't duplicate layout_vec of dataset, because we then # carry around extra unnecessary data. # But use getSizes to save an Allreduce in computing the # global size. size = self.dataset.layout_vec.getSizes() if self.comm.rank == 0: self._vec = PETSc.Vec().createWithArray(data, size=size, bsize=self.cdim, comm=self.comm) else: self._vec = PETSc.Vec().createWithArray(np.empty( 0, dtype=self.dtype), size=size, bsize=self.cdim, comm=self.comm) # PETSc Vecs have a state counter and cache norm computations # to return immediately if the state counter is unchanged. # Since we've updated the data behind their back, we need to # change that state counter. self._vec.stateIncrease() yield self._vec if access is not base.READ: self.comm.Bcast(data, 0)
def petsc_solve(A, b, x0=None, tol=1.e-5, ksptype="minres", pctype="ilu"): """ Solves Ax=b using Petsc krylov-type iterative solver Parameters ---------- A: scipy matrix b: ndarray x0: ndarray, optional initial guess tol: float, optional convergence tolerance ksptype: string, optional type of Krylov accelerator. eg. "bcgs", "gmres" Returns ------- out: ndarray solution x to equation Ax=b """ comm = MPI.COMM_SELF # Only works in serial ksp = get_petsc_ksp(A, pctype=pctype, ksptype=ksptype, tol=tol) petsc_rhs = PETSc.Vec().createWithArray(b, comm=comm) if x0 is None: petsc_sol = petsc_rhs.duplicate() else: petsc_sol = PETSc.Vec().createWithArray(x0, comm=comm) ksp.setInitialGuessNonzero(True) ksp.setFromOptions() ksp.solve(petsc_rhs, petsc_sol) return petsc_sol.getArray()
def projectCovToMesh(self, num_kl, cov_expr): """TODO: Docstring for projectCovToMesh. Solves CX = BX where C is the covariance matrix :num_kl : number of kl exapansion terms needed :returns: TODO """ # turn the flag to true self.flag = True # get C,B matrices C = self.getCovMat(cov_expr) B = self._getBMat() # Solve the generalized eigenvalue problem eigensolver = SLEPc.EPS() eigensolver.create() eigensolver.setOperators(C, B) eigensolver.setDimensions(num_kl) eigensolver.setProblemType(SLEPc.EPS.ProblemType.GHEP) eigensolver.setFromOptions() eigensolver.solve() # Get the number of eigen values that converged. #nconv = eigensolver.get_number_converged() # Get N eigenpairs where N is the number of KL expansion and check if N < nconv otherwise you had # really bad matrix # create numpy array of vectors and eigenvalues self.eigen_funcs = np.empty((num_kl), dtype=object) self.eigen_vals = np.empty((num_kl), dtype=float) # store the eigenvalues and eigen functions V = FunctionSpace(self._mesh, "CG", 1) x_real = PETSc.Vec().create() x_real.setSizes(self.domain.getNodes()) x_real.setUp() x_real.setValues(np.arange(0, self.domain.getNodes()), np.zeros(self.domain.getNodes())) # for i in range(0, self.domain.getNodes()): # x_real.setValue(i, 0, 0.) for eigen_pairs in range(0, num_kl): lam = eigensolver.getEigenpair(eigen_pairs, x_real) self.eigen_funcs[eigen_pairs] = Function(V) # use dof_to_vertex map to map values to the function space self.eigen_funcs[eigen_pairs].vector()[:] = x_real.getValues( dof_to_vertex_map(V).astype('int32')) # divide by norm to make the unit norm again self.eigen_funcs[eigen_pairs].vector()[:] = self.eigen_funcs[eigen_pairs].vector()[:] / \ norm(self.eigen_funcs[eigen_pairs]) self.eigen_vals[eigen_pairs] = lam.real
def buildLineIntegralGaugeOperators(self, lines, linesSegments): """ Build the linear algebra operators needed to compute the line integral gauges. The operators are local to each process, contributions are currently summed in the output functions. """ #create lineIntegralGaugesVec to store contributions to all lines from this process self.lineIntegralGaugesVec = PETSc.Vec().create(comm=PETSc.COMM_SELF) self.lineIntegralGaugesVec.setSizes(len(lines)) self.lineIntegralGaugesVec.setUp() # create lineIntegralGaugeMats to store coefficients mapping contributions from each field # to the line integral gauges self.lineIntegralGaugeMats = [] if not self.isLineIntegralGauge: return # size of lineIntegralGaugeMats depends on number of local points for each field for pointGaugesVec in self.pointGaugeVecs: m = PETSc.Mat().create(comm=PETSc.COMM_SELF) m.setSizes([len(lines), pointGaugesVec.getSize()]) m.setType('aij') m.setUp() self.lineIntegralGaugeMats.append(m) # Assemble contributions from each point in each line segment for lineIndex, (line, segments) in enumerate(zip(self.lines, linesSegments)): field, endpoints = line fieldIndex = self.fields.index(field) # Trapezoid Rule to calculate coefficients here for p1, p2 in segments: segmentLength = np.linalg.norm(np.asarray(p2) - np.asarray(p1)) for point in p1, p2: point_data = self.points[tuple(point)] # only assign coefficients for locally owned points if field in point_data: pointID = point_data[field] self.lineIntegralGaugeMats[fieldIndex].setValue( lineIndex, pointID, old_div(segmentLength, 2), addv=True) for m in self.lineIntegralGaugeMats: m.assemble()
def setup(self, parent_params_vec, params_dict, srcvec, my_params, connections, relevance, var_of_interest=None, store_byobjs=False, shared_vec=None): """ Configure this vector to store a flattened array of the variables in params_dict. Variable shape and value are retrieved from srcvec. Args ---- parent_params_vec : `VecWrapper` or None `VecWrapper` of parameters from the parent `System`. params_dict : `OrderedDict` Dictionary of parameter absolute name mapped to metadata dict. srcvec : `VecWrapper` Source `VecWrapper` corresponding to the target `VecWrapper` we're building. my_params : list of str A list of absolute names of parameters that the `VecWrapper` we're building will 'own'. connections : dict of str : str A dict of absolute target names mapped to the absolute name of their source variable. relevance : `Relevance` object Object that knows what vars are relevant for each var_of_interest. var_of_interest : str or None Name of the current variable of interest. store_byobjs : bool, optional If True, store 'pass by object' variables in the `VecWrapper` we're building. shared_vec : ndarray, optional If not None, create vec as a subslice of this array. """ super(PetscTgtVecWrapper, self).setup(parent_params_vec, params_dict, srcvec, my_params, connections, relevance=relevance, var_of_interest=var_of_interest, store_byobjs=store_byobjs, shared_vec=shared_vec) if trace: # pragma: no cover debug("'%s': creating tgt petsc_vec: (size %d) %s: vec=%s" % (self._sysdata.pathname, len(self.vec), self.keys(), self.vec)) self.petsc_vec = PETSc.Vec().createWithArray(self.vec, comm=self.comm) if trace: debug("petsc_vec creation DONE")
def _initialize_data(self, root_vector): """ Internally allocate vectors. Parameters ---------- root_vector : Vector or None the root's vector instance or None, if we are at the root. """ super()._initialize_data(root_vector) self._petsc = {} self._imag_petsc = {} data = self._data.real if self._alloc_complex: self._petsc = PETSc.Vec().createWithArray(data.copy(), comm=self._system().comm) else: self._petsc = PETSc.Vec().createWithArray(data, comm=self._system().comm) # Allocate imaginary for complex step if self._alloc_complex: data = self._data.imag self._imag_petsc = PETSc.Vec().createWithArray(data, comm=self._system().comm)
def createParallelVector(size, vector_type, communicator=None): """Create a parallel vector in petsc format. :param int size: vector size. :param int vector_type: vector type for parallel computations. :param str communicator: mpi communicator. :return: parallel vector. :rtype: petsc parallel vector. """ if communicator is None: communicator = PETSc.COMM_WORLD if vector_type: # Cuda support parallel_vector = PETSc.Vec().create(comm=communicator) parallel_vector.setType('cuda') parallel_vector.setSizes(size) elif not vector_type: # No cuda support parallel_vector = PETSc.Vec().createMPI(size, comm=communicator) else: raise ValueError('Cuda option=', vector_type, ' not supported.') parallel_vector.setUp() return parallel_vector
def test_VecWrite(self): """Test writing a Vec""" array = np.array([1.1, 2.2, 3.3]) PetscBinaryIO().writeBinaryFile('test.dat', [ array.view(Vec), ]) vec = PETSc.Vec().createSeq(3) vec.set(0.) viewer = PETSc.Viewer().createBinary('test.dat', PETSc.Viewer.Mode.R) vec.load(viewer) viewer.destroy() self.assertTrue(np.allclose(array, vec[...])) vec.destroy()
def arrayToVec(vecArray): """ Converts a (global) array to a PETSc vector over :attr:`petsc4py.PETSc.COMM_WORLD`. Args: vecArray (array or numpy.array): input vector. Returns: petsc4py.PETSc.Vec() : """ vec = _PETSc.Vec().create(comm=_PETSc.COMM_WORLD) vec.setSizes(len(vecArray)) vec.setUp() (Istart, Iend) = vec.getOwnershipRange() return vec.createWithArray(vecArray[Istart:Iend], comm=_PETSc.COMM_WORLD) vec.destroy()
def generateDMPlex(self, dh, dim=1): coords, cone, dl = self.generateBody(dh) self.__dl = dl self.__L = self.getLong() self.__dom = PETSc.DMPlex().createFromCellList(dim, cone, coords) self.setUpDimensions() points = self.getTotalNodes() ind = [ poi * 2 + dof for poi in range(points) for dof in range(len(self.__vel)) ] self.__velVec = PETSc.Vec().createMPI( ((points * len(self.__vel), None))) self.__velVec.setValues(ind, np.tile(self.__vel, points)) self.__velVec.assemble()
def testSetMPIGhost(self): import numpy v = PETSc.Vec().create() v.setType(PETSc.Vec.Type.MPI) v.setSizes((5, None)) ghosts = [ i % v.size for i in range(v.owner_range[1], v.owner_range[1] + 3) ] v.setMPIGhost(ghosts) v.setArray(numpy.array(range(*v.owner_range))) v.ghostUpdate() with v.localForm() as loc: self.assertTrue( (loc[0:v.local_size] == range(*v.owner_range)).all()) self.assertTrue((loc[v.local_size:] == ghosts).all())
def setup_7of7_solvers(self): """ Setup up PETSc KSP object """ size = numpy.sum(self.var_sizes[self.comm.rank, :]) zeros = numpy.zeros self.sol_buf = PETSc.Vec().createWithArray(zeros(size), comm=self.comm) self.rhs_buf = PETSc.Vec().createWithArray(zeros(size), comm=self.comm) self.solvers['NL'] = { 'NEWTON': Newton(self), 'NLN_JC': NonlinearJacobi(self), 'NLN_GS': NonlinearGS(self), } self.solvers['LN'] = { 'None': Identity(self), 'KSP_PC': KSP(self), 'LIN_JC': LinearJacobi(self), 'LIN_GS': LinearGS(self), } self.solvers['LS'] = { 'BK_TKG': Backtracking(self), } for subsystem in self.subsystems['local']: subsystem.setup_7of7_solvers()
def testCreateInterpolation(self): mat = PETSc.Mat().create() mat.setSizes(((10, None), (10, None))) mat.setUp() vec = PETSc.Vec().create() vec.setSizes((10, None)) vec.setUp() def create_interp(dm, dmf): return mat, vec self.dm.setCreateInterpolation(create_interp) m, v = self.dm.createInterpolation(self.dm) self.assertEqual(m, mat) self.assertEqual(v, vec)
def testFDColor(self): J = PETSc.Mat().create(PETSc.COMM_SELF) J.setSizes([2,2]) J.setType(PETSc.Mat.Type.SEQAIJ) J.setUp() r = PETSc.Vec().createSeq(2) x = PETSc.Vec().createSeq(2) b = PETSc.Vec().createSeq(2) fun = Function() jac = Jacobian() self.snes.setFunction(fun, r) self.snes.setJacobian(jac, J) self.assertFalse(self.snes.getUseFD()) jac(self.snes, x, J, J) self.snes.setUseFD(False) self.assertFalse(self.snes.getUseFD()) self.snes.setUseFD(True) self.assertTrue(self.snes.getUseFD()) self.snes.setFromOptions() x.setArray([2,3]) b.set(0) self.snes.solve(b, x) self.assertAlmostEqual(abs(x[0]), 1.0) self.assertAlmostEqual(abs(x[1]), 2.0)
def _read_scalars(path, shape, steps, quantity, filetype): """ Read Mandyoc scalar data Read ``temperature``, ``density``, ``radiogenic_heat``, ``viscosity``, ``strain``, ``strain_rate`` and ``pressure``. Parameters ---------- path : str Path to the folder where the Mandyoc files are located. shape: tuple Shape of the expected grid. steps : array Array containing the saved steps. quantity : str Type of scalar data to be read. Returns ------- data: np.array Array containing the Mandyoc scalar data. """ data = [] for step in steps: filename = "{}_{}".format(BASENAMES[quantity], step) # To open outpus binary files if filetype == "binary": load = PETSc.Viewer().createBinary( os.path.join(path, filename + ".bin"), "r" ) data_step = PETSc.Vec().load(load).getArray() del load else: data_step = np.loadtxt( os.path.join(path, filename + ".txt"), unpack=True, comments="P", skiprows=2, ) # Convert very small numbers to zero data_step[np.abs(data_step) < 1.0e-200] = 0 # Reshape data_step data_step = data_step.reshape(shape, order="F") # Append data_step to data data.append(data_step) data = np.array(data) return data
def test_VtensV_eval(self): domain = { 'lower': [0, 0, 0], 'upper': [1, 1], 'nelem': [2, 2], 'ngl': 2 } fem = self.setFemProblem('uniform', **domain) vec_init = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 ] vec_ref = [ 1, 1 * 2, 2 * 2, 3 * 3, 3 * 4, 4 * 4, 5 * 5, 5 * 6, 6 * 6, 7 * 7, 7 * 8, 8 * 8, 9 * 9, 9 * 10, 10 * 10, 11 * 11, 11 * 12, 12 * 12, 13 * 13, 13 * 14, 14 * 14, 15 * 15, 15 * 16, 16 * 16, 17 * 17, 17 * 18, 18 * 18, ] vec_ref = np.array(vec_ref) vec_init = PETSc.Vec().createWithArray(np.array(vec_init)) fem.computeVtensV(vec=vec_init) np.testing.assert_array_almost_equal(vec_ref, fem._VtensV, decimal=10)
def read_petsc(filename, data_type): viewer = PETSc.Viewer().createBinary(filename, 'r') if data_type == 'matrix': A = PETSc.Mat() elif data_type == 'vector': A = PETSc.Vec() else: print('Unknown data type. Pass matrix or vector.') return None A.create(PETSc.COMM_WORLD) A.load(viewer) viewer.destroy() return A
def _create_tmp_vec(self,size): """ Creates an empty vector of given size. Arguments --------- size : int Size of the temporary vector. Returns ------- vec : PETSc vector """ tmp = p4pyPETSc.Vec().create() tmp.setType('mpi') tmp.setSizes(size) return tmp
def solve(self, A, b): size = A.getSizes()[0] x = PETSc.Vec().createSeq(size) # Initialize ksp solver. ksp = PETSc.KSP().create() ksp.setType('cg') ksp.getPC().setType('gamg') ksp.setOperators(A) ksp.setFromOptions() # Solve ksp.solve(b, x) return x
def diagonalBlock(self, k, Nv, RHS): """ Returns diagonal block `A_ii` and vector slice `b_i` in the global matrix `A` and load vector `b`, repspectively """ A, _b = assemble_Ab(k, RHS) b = PETSc.Vec() b.createSeq(len(Nv), comm=comm) P = PETSc.Mat() P.createDense(Nv.shape, array=Nv, comm=comm) P.mult(_b.vec(), b) P.transpose() A = A.mat().PtAP(P) return A, b
def numpy_to_petsc(mat): '''Build PETScMatrix with array structure''' # Dense array to matrix if isinstance(mat, np.ndarray): if mat.ndim == 1: vec = PETSc.Vec().createWithArray(mat) vec.assemble() return PETScVector(vec) return numpy_to_petsc(csr_matrix(mat)) # Sparse A = PETSc.Mat().createAIJ(comm=COMM, size=mat.shape, csr=(mat.indptr, mat.indices, mat.data)) A.assemble() return PETScMatrix(A)
def transition(wt, dicowt, q, n, d, ot, version): Print = PETSc.Sys.Print #Sparse Bt pas symetrique Bt = PETSc.Mat() Ot = PETSc.Vec() Bt.create(PETSc.COMM_WORLD) Bt.setSizes([n, n]) Bt.setType('dense') #sparse Bt.setUp() Istart, Iend = Bt.getOwnershipRange() Print("Debut Bt") for K in range(Istart, Iend): si = float(wt.get(K, 0.0)) # Est-ce que K a des voisins au temps t? if si == 0.0: for L in range(n): if K == L: Bt[K, L] = q + (1 - q) * d / n + (1 - q) * (1 - d) else: Bt[K, L] = (1 - q) * d / n else: for L in range(n): if K == L: Bt[K, L] = q + (1 - q) * d / n else: wtij = dicowt.get(tuple((K, L)), 0.0) if wtij != 0.0: Bt[K, L] = (1 - q) * (wtij * (1 - d) / si + d / n) else: Bt[K, L] = (1 - q) * d / n Bt.assemblyBegin() Bt.assemblyEnd() Print("Fin Bt") if version == 2: Print("Debut Ot") Ot.create(PETSc.COMM_WORLD) Ot.setSizes(n) Ot.setUp() Istart, Iend = Ot.getOwnershipRange() for K in range(Istart, Iend): si = float(wt.get(K, 0.0)) if si != 0.0: Ot[K] = 1 else: Ot[K] = 0 Ot.assemblyBegin() Ot.assemblyEnd() return Bt, Ot
def convert_vec_to_petsc(vec, comm=None): """Convert a vector/array to the PETSc form. Parameters ---------- vec : vector-like Numpy array, will be unravelled to one dimension. comm : mpi4py.MPI.Comm instance The mpi communicator. Returns ------- pvec : petsc4py.PETSc.Vec The vector in petsc form - only the local part if running across several mpi processes. """ PETSc, comm = get_petsc(comm=comm) mpi_sz = comm.Get_size() pvec = PETSc.Vec() # get shape before slicing size = max(vec.shape) pvec.create(comm=comm) pvec.setSizes(size) pvec.setFromOptions() pvec.setUp() ri, rf = pvec.getOwnershipRange() # only consider the vector already sliced if owns whole sliced = (mpi_sz == 1) if isinstance(vec, qu.Lazy): # vector hasn't been constructed yet try: # try and and lazily construct with slicing vec = vec(ownership=(ri, rf)) sliced = True except TypeError: vec = vec() array = np.asarray(vec).reshape(-1) if not sliced: array = array[ri:rf] pvec.createWithArray(array, comm=comm) return pvec
def coarseSolve(self, b): """ - coarseSolve - takes the fine scale right hand side 'b' and projects it into the coarse space to coarse right hand side bH. We then solve the coarse problem AH * xh = bH using a direct solver. The solution is then projected back into the fine space and returned. """ # This is the coarse right hand side bH = PETSc.Vec().create(comm=PETSc.COMM_SELF) bH.setType(PETSc.Vec.Type.SEQ) bH.setSizes(self.totalSize) xH = bH.duplicate() # Build solution vector for coarse space bH_tmp = bH.duplicate() work, _ = self.A.getVecs() workl, _ = self.A_local.getVecs() self.scatter_l2g(b, workl, PETSc.InsertMode.INSERT_VALUES, PETSc.ScatterMode.SCATTER_REVERSE) for i in range(self.comm.Get_size()): # For each subdomain for (j, vec) in enumerate( self.coarse_vecs[i]): # For each basis in subdomain if vec: bH_tmp[self.coarseIS[i][j]] = vec.dot(workl) mpi.COMM_WORLD.Allreduce([bH_tmp, mpi.DOUBLE], [bH, mpi.DOUBLE], mpi.SUM) self.ksp_AH.solve(bH, xH) # solve coarse problem print(xH) workl.set(0.) for i in range(self.comm.Get_size()): # For each subdomain for (j, vec) in enumerate( self.coarse_vecs[i]): # For each basis in subdomain if vec: workl.axpy(xH[self.coarseIS[i][j]], vec) out = b.duplicate() out.set(0.) self.scatter_l2g(workl, out, PETSc.InsertMode.ADD_VALUES) return out
def help(args=None): import sys, shlex # program name try: prog = sys.argv[0] except Exception: prog = getattr(sys, 'executable', 'python') if args is None: args = sys.argv[1:] elif isinstance(args, str): args = shlex.split(args) else: args = [str(a) for a in args] import petsc4py petsc4py.init([prog, '-help'] + args) from petsc4py import PETSc COMM = PETSc.COMM_SELF if 'vec' in args: vec = PETSc.Vec().create(comm=COMM) vec.setSizes(0) vec.setFromOptions() del vec if 'mat' in args: mat = PETSc.Mat().create(comm=COMM) mat.setSizes([0, 0]) mat.setFromOptions() del mat if 'ksp' in args: ksp = PETSc.KSP().create(comm=COMM) ksp.setFromOptions() del ksp if 'pc' in args: pc = PETSc.PC().create(comm=COMM) pc.setFromOptions() del pc if 'snes' in args: snes = PETSc.SNES().create(comm=COMM) snes.setFromOptions() del snes if 'ts' in args: ts = PETSc.TS().create(comm=COMM) ts.setFromOptions() del ts if 'da' in args: da = PETSc.DA().create(comm=COMM) da.setFromOptions() del da
def printVecValues(vecName, rowI, diffTol=1e-30): # read the vector vec1 = PETSc.Vec().create(comm=PETSc.COMM_WORLD) viewer = PETSc.Viewer().createBinary(vecName, comm=PETSc.COMM_WORLD) vec1.load(viewer) rowI = int(rowI) vecSize = vec1.getSize() if rowI == -1: for i in range(vecSize): if vec1.getValue(i) > diffTol: print("%12d %16.14e" % (i, vec1.getValue(i))) else: print("%12d %16.14e" % (rowI, vec1.getValue(rowI)))