def axb(A, B, X): #Initial the X matrix X.zeroEntries() B.convert('dense') X.convert('dense') #Setup the precondition pcr = PETSc.PC().create(comm=PETSc.COMM_WORLD) pcr.setType('lu') pcr.setFactorSolverType('superlu_dist') pcr.setFactorShift(shift_type=1, amount=1e-10) pcr.setFactorOrdering(ord_type='amd') pcr.setFromOptions() pcr.setOperators(A) pcr.setUp() F = pcr.getFactorMatrix() #Solve the AX=B F.matSolve(B, X) X.assemblyBegin() X.assemblyEnd() X.convert('aij') pcr.destroy() return X
def setUp(self): pc = self.pc = PETSc.PC() ctx = PC_PYTHON_CLASS() pc.createPython(ctx, comm=PETSc.COMM_SELF) self.pc.prefix = self.PC_PREFIX self.pc.setFromOptions() assert self._getCtx().log['create'] == 1 assert self._getCtx().log['setFromOptions'] == 1
def help(args=None): import sys, shlex # program name try: prog = sys.argv[0] except Exception: prog = getattr(sys, 'executable', 'python') # arguments 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 and initialize import petsc4py petsc4py.init([prog, '-help'] + args) from petsc4py import PETSc # help dispatcher COMM = PETSc.COMM_SELF if 'vec' in args: vec = PETSc.Vec().create(comm=COMM) vec.setSizes(0) vec.setFromOptions() vec.destroy() if 'mat' in args: mat = PETSc.Mat().create(comm=COMM) mat.setSizes([0, 0]) mat.setFromOptions() mat.destroy() if 'pc' in args: pc = PETSc.PC().create(comm=COMM) pc.setFromOptions() pc.destroy() if 'ksp' in args: ksp = PETSc.KSP().create(comm=COMM) ksp.setFromOptions() ksp.destroy() if 'snes' in args: snes = PETSc.SNES().create(comm=COMM) snes.setFromOptions() snes.destroy() if 'ts' in args: ts = PETSc.TS().create(comm=COMM) ts.setFromOptions() ts.destroy() if 'tao' in args: tao = PETSc.TAO().create(comm=COMM) tao.setFromOptions() tao.destroy() if 'dmda' in args: dmda = PETSc.DMDA().create(comm=COMM) dmda.setFromOptions() dmda.destroy() if 'dmplex' in args: dmplex = PETSc.DMPlex().create(comm=COMM) dmplex.setFromOptions() dmplex.destroy()
def pc_setup(self): self.pc = PETSc.PC().create(MPI.comm_world) self.pc.setType("cholesky") if hasattr(self.pc, 'setFactorSolverType'): self.pc.setFactorSolverType("mumps") elif hasattr(self.pc, 'setFactorSolverPackage'): self.pc.setFactorSolverPackage('mumps') else: ColorPrint.print_warn('Could not configure preconditioner')
def solveLinear(self): self.method_PETSc.solve(self.b_PETSc, self.x_PETSc) convergedReason = self.method_PETSc.getConvergedReason() if convergedReason < 0: if self.rank == 0: print "linear solver has not converged for reason", convergedReason opt_init = self.method_PETSc.getPC().getType() self.method_PETSc.setInitialGuessNonzero(0) if convergedReason < 0: # if self.rank==0: print "linear solver has not converged for reason", convergedReason pc = _PETSc.PC() pc.create(self.comm) pc.setType('sor') #successive over relaxation self.method_PETSc.setPC(pc) self.method_PETSc.setOperators(self.A_PETSc) if self.rank == 0: print "change preconditionner to", self.method_PETSc.getPC( ).getType() self.method_PETSc.solve(self.b_PETSc, self.x_PETSc) convergedReason = self.method_PETSc.getConvergedReason() self.method_PETSc.setInitialGuessNonzero(1) if convergedReason < 0: if self.rank == 0: print "linear solver has not converged for reason", convergedReason pc.setType('asm') #successive over relax self.method_PETSc.setPC(pc) self.method_PETSc.setOperators(self.A_PETSc) if self.rank == 0: print "change preconditionner to", self.method_PETSc.getPC( ).getType() self.method_PETSc.solve(self.b_PETSc, self.x_PETSc) convergedReason = self.method_PETSc.getConvergedReason() if convergedReason < 0: if self.rank == 0: print "linear solver has not converged for reason", convergedReason else: if self.rank == 0: print "linear solver has finally converged" self.method_PETSc.setInitialGuessNonzero(0) #if self.rank==0: print "setInitialGuess back to non zero" pc.setType(opt_init) self.method_PETSc.setPC(pc) self.method_PETSc.setOperators(self.A_PETSc) if self.rank == 0: print "change preconditionner back to", self.method_PETSc.getPC( ).getType() return
def get_pc(self): flag_3_way = self.pc_type in ("diagonal 3-way", "undrained 3-way") ctx = PreconditionerCC(self.P.mat(), self.P_diff.mat(), self.index_map, flag_3_way, self.inner_ksp_type, self.inner_pc_type, self.inner_rtol, self.inner_atol, self.inner_maxiter, self.inner_monitor, 1.0, 0.1, self.inner_accel_order, self.bcs_sub_pressure) self.pc = PETSc.PC().create() self.pc.setType('python') self.pc.setPythonContext(ctx) self.pc.setOperators(self.A.mat()) self.pc.setUp() return self.pc
def solve_eigensystem(A, B, problem_type=SLEPc.EPS.ProblemType.GHEP): # Create the results vectors xr, tmp = A.getVecs() xi, tmp = A.getVecs() pc = PETSc.PC().create() # pc.setType(pc.Type.HYPRE) pc.setType(pc.Type.BJACOBI) ksp = PETSc.KSP().create() ksp.setType(ksp.Type.PREONLY) ksp.setPC(pc) F = SLEPc.ST().create() F.setType(F.Type.PRECOND) F.setKSP(ksp) F.setShift(0) # Setup the eigensolver E = SLEPc.EPS().create() E.setST(F) E.setOperators(A, B) E.setType(E.Type.LOBPCG) E.setDimensions(10, PETSc.DECIDE) E.setWhichEigenpairs(E.Which.SMALLEST_REAL) E.setProblemType(problem_type) E.setFromOptions() # Solve the eigensystem E.solve() Print("") its = E.getIterationNumber() Print("Number of iterations of the method: %i" % its) sol_type = E.getType() Print("Solution method: %s" % sol_type) nev, ncv, mpd = E.getDimensions() Print("Number of requested eigenvalues: %i" % nev) tol, maxit = E.getTolerances() Print("Stopping condition: tol=%.4g, maxit=%d" % (tol, maxit)) nconv = E.getConverged() Print("Number of converged eigenpairs: %d" % nconv) if nconv > 0: Print("") Print(" k ||Ax-kx||/||kx|| ") Print("----------------- ------------------") for i in range(nconv): k = E.getEigenpair(i, xr, xi) error = E.computeError(i) if k.imag != 0.0: Print(" %9f%+9f j %12g" % (k.real, k.imag, error)) else: Print(" %12f %12g" % (k.real, error)) Print("")
def __init__(self, mat, freedofs=None): ngs.BaseMatrix.__init__(self) self.ngsmat = mat self.vecmap = VectorMapping(mat.row_pardofs, freedofs) self.mat = CreatePETScMatrix(mat, freedofs) self.precond = psc.PC().create() self.precond.setType("gamg") self.precond.setOperators(self.mat) self.precond.setUp() self.pscx, self.pscy = self.mat.createVecs()
def petsc_preconditioner(B, mat, A): ''' Represent block_mat as a petsc matrix (by having corrent matrix vector product ''' pc = PETSc.PC().create() pc.setType(PETSc.PC.Type.PYTHON) pc.setOperators(mat) # To get the sizes right pc.setPythonContext(WrapAction(B, A)) pc.setUp() return pc
def setup_preconditioner(W, which, eps=None): ''' This is a block diagonal preconditioner based on H1 x H^{-0.5} ''' from xii.linalg.matrix_utils import as_petsc from numpy import hstack from petsc4py import PETSc from hsmg import HsNorm assert len(eps) == 2 mu_value, lmbda_value = eps V, Q = W # H1 u, v = TrialFunction(V), TestFunction(V) b00 = inner(grad(u), grad(v)) * dx + inner(u, v) * dx A = as_backend_type(assemble(b00)) # Attach rigid deformations to A # Functions Z = [ interpolate(Constant((1, 0)), V), interpolate(Constant((0, 1)), V), interpolate(Expression(('x[1]', '-x[0]'), degree=1), V) ] # The basis Z = VectorSpaceBasis([z.vector() for z in Z]) Z.orthonormalize() A.set_nullspace(Z) A.set_near_nullspace(Z) A = as_petsc(A) # Setup the preconditioner in petsc pc = PETSc.PC().create() pc.setType(PETSc.PC.Type.HYPRE) pc.setOperators(A) # Other options opts = PETSc.Options() opts.setValue('pc_hypre_boomeramg_cycle_type', 'V') opts.setValue('pc_hypre_boomeramg_relax_type_all', 'symmetric-SOR/Jacobi') opts.setValue('pc_hypre_boomeramg_coarsen_type', 'Falgout') pc.setFromOptions() # Wrap for cbc.block B00 = BlockPC(pc) # The Q norm via spectral Qi = Q.sub(0).collapse() B11 = inverse(VectorizedOperator(HsNorm(Qi, s=-0.5), Q)) return block_diag_mat([B00, B11])
def __init__(self, V, hdiv0=False, bc=None): # FIXME: lift assert V.ufl_element().family() == 'Raviart-Thomas' assert V.ufl_element().degree() == 1 mesh = V.mesh() assert mesh.geometry().dim() == 2 sigma, tau = TrialFunction(V), TestFunction(V) a = inner(div(sigma), div(tau)) * dx if not hdiv0: a += inner(sigma, tau) * dx f = Constant(np.zeros(V.ufl_element().value_shape())) L = inner(tau, f) * dx A, _ = assemble_system(a, L, bc) # AMS setup Q = FunctionSpace(mesh, 'CG', 1) G = DiscreteOperators.build_gradient(V, Q) pc = PETSc.PC().create(mesh.mpi_comm().tompi4py()) pc.setType('hypre') pc.setHYPREType('ams') # Attach gradient pc.setHYPREDiscreteGradient(mat(G)) # Constant nullspace (in case not mass and bcs) constants = [ vec(interpolate(c, V).vector()) for c in (Constant((1, 0)), Constant((0, 1))) ] pc.setHYPRESetEdgeConstantVectors(*constants) # NOTE: term mass term is accounted for automatically by Hypre # unless pc.setPoissonBetaMatrix(None) if hdiv0: pc.setHYPRESetBetaPoissonMatrix(None) pc.setOperators(mat(A)) # FIXME: some defaults pc.setFromOptions() pc.setUp() self.pc = pc self.A = A # For creating vec
def __init__(self, A, prectype, parameters=None, pdes=1, nullspace=None): from dolfin import info from time import time T = time() Ad = A.down_cast().mat() if nullspace: from block.block_util import isscalar ns = PETSc.NullSpace() if isscalar(nullspace): ns.create(constant=True) else: ns.create(constant=False, vectors=[v.down_cast().vec() for v in nullspace]) try: Ad.setNearNullSpace(ns) except: info( 'failed to set near null space (not supported in petsc4py version)' ) self.A = A self.petsc_prec = PETSc.PC() self.petsc_prec.create() self.petsc_prec.setType(prectype) # self.petsc_prec.setOperators(Ad, Ad, PETSc.Mat.Structure.SAME_PRECONDITIONER) self.petsc_prec.setOperators(Ad, Ad) # Merge parameters into the options database if parameters: origOptions = PETSc.Options().getAll() for key, val in iter(parameters.items()): PETSc.Options().setValue(key, val) # Create preconditioner based on the options database self.petsc_prec.setFromOptions() self.petsc_prec.setUp() # Reset the options database if parameters: for key in iter(parameters.keys()): PETSc.Options().delValue(key) for key, val in iter(origOptions.items()): PETSc.Options().setValue(key, val) info('constructed %s preconditioner in %.2f s' % (self.__class__.__name__, time() - T))
def setUp(self): pc = self.pc = PETSc.PC() pc.create(PETSc.COMM_SELF) pc.setType(self.PC_TYPE) module = __name__ factory = 'PC_PYTHON_CLASS' self.pc.prefix = self.PC_PREFIX OptDB = PETSc.Options(self.pc) assert OptDB.prefix == self.pc.prefix OptDB['pc_python_type'] = '%s.%s' % (module, factory) self.pc.setFromOptions() del OptDB['pc_python_type'] assert self._getCtx().log['create'] == 1 assert self._getCtx().log['setFromOptions'] == 1 ctx = self._getCtx() self.assertEqual(getrefcount(ctx), 3)
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 pc_mat(pc, block): '''Set pc for (non-block) operator''' if isinstance(block, LU): pc.setType('lu') pc.setFactorPivot(1E-18) return block.A if isinstance(block, SUPERLU_LU): pc.setType('lu') pc.setFactorPivot(1E-18) pc.setFactorSolverType('superlu') return block.A if isinstance(block, AMG): pc.setType('hypre') return block.A if isinstance(block, Elasticity): pc.setType('gamg') return block.A # FIXME: Very add hoc support for sum, this should recursive if isinstance(block, block_add): this, that = block.A, block.B assert isinstance(this, precond) and isinstance(that, precond) pc.setType('composite') pc.setCompositeType(PETSc.PC.CompositeType.ADDITIVE) for sub, op in enumerate((this, that)): # Fake it pc_ = PETSc.PC().create() A = pc_mat(pc_, op) pc.addCompositePC(pc_.getType()) pc_sub = pc.getCompositePC(sub) # Make it pc_mat(pc_sub, op) pc_sub.setOperators(as_petsc(A)) mat = diagonal_matrix(op.A.size(0), 1) return mat assert False, type(block)
def testGetSetPC(self): oldpc = self.ksp.getPC() self.assertEqual(oldpc.getRefCount(), 2) newpc = PETSc.PC() newpc.create(self.ksp.getComm()) self.assertEqual(newpc.getRefCount(), 1) self.ksp.setPC(newpc) self.assertEqual(newpc.getRefCount(), 2) self.assertEqual(oldpc.getRefCount(), 1) oldpc.destroy() self.assertFalse(bool(oldpc)) pc = self.ksp.getPC() self.assertTrue(bool(pc)) self.assertEqual(pc, newpc) self.assertEqual(pc.getRefCount(), 3) newpc.destroy() self.assertFalse(bool(newpc)) self.assertEqual(pc.getRefCount(), 2)
def setup_preconditioner(W, which, eps=None): ''' This is a block diagonal preconditioner based on H1 x L2 x H^{-0.5} ''' from block.algebraic.petsc import LumpedInvDiag from xii.linalg.matrix_utils import as_petsc from numpy import hstack from petsc4py import PETSc from hsmg import HsNorm V, Q, Y = W # H1 u, v = TrialFunction(V), TestFunction(V) b00 = inner(grad(u), grad(v)) * dx + inner(u, v) * dx # NOTE: since interpolation is broken with MINI I don't interpolate # here the RM basis to attach the vectros to matrix A = assemble(b00) A = as_petsc(A) # Setup the preconditioner in petsc pc = PETSc.PC().create() pc.setType(PETSc.PC.Type.HYPRE) pc.setOperators(A) # Other options opts = PETSc.Options() opts.setValue('pc_hypre_boomeramg_cycle_type', 'V') opts.setValue('pc_hypre_boomeramg_relax_type_all', 'symmetric-SOR/Jacobi') opts.setValue('pc_hypre_boomeramg_coarsen_type', 'Falgout') pc.setFromOptions() # Wrap for cbc.block B00 = BlockPC(pc) p, q = TrialFunction(Q), TestFunction(Q) B11 = LumpedInvDiag(assemble(inner(p, q) * dx)) # The Y norm via spectral Yi = Y.sub(0).collapse() B22 = inverse(VectorizedOperator(HsNorm(Yi, s=-0.5), Y)) return block_diag_mat([B00, B11, B22])
def inertia_setup(self): self.pc = PETSc.PC().create(MPI.comm_world) prefix = "inertia_" if prefix: self.pc.setOptionsPrefix(prefix) self.pc.setFromOptions() for parameter, value in self.parameters['inertia'].items(): dolfin.PETScOptions.set(parameter, value) log( LogLevel.DEBUG, 'Setting up inertia solver: {}: {}'.format( prefix + parameter, value)) dolfin.PETScOptions.set("inertia_ksp_type", "preonly") dolfin.PETScOptions.set("inertia_pc_type", "cholesky") dolfin.PETScOptions.set("inertia_pc_factor_mat_solver_type", "mumps") dolfin.PETScOptions.set("inertia_mat_mumps_icntl_24", 1) dolfin.PETScOptions.set("inertia_mat_mumps_icntl_13", 1) self.pc.setFromOptions()
def compute_stability(self, mu, params, lb, ub, branch, z, v, w, Z, bcs, J): # trial = w # test = v test = TestFunction(Z) comm = Z.mesh().mpi_comm() # a dummy linear form, needed to construct the SystemAssembler b = inner( Function(Z), test ) * dx # a dummy linear form, needed to construct the SystemAssembler # Build the LHS matrix A = PETScMatrix(comm) asm = SystemAssembler(J, b, bcs) asm.assemble(A) pc = PETSc.PC().create(comm) pc.setOperators(A.mat()) pc.setType("cholesky") if PETSc.Sys.getVersion()[0:2] < (3, 9): pc.setFactorSolverPackage("mumps") else: pc.setFactorSolverType("mumps") pc.setUp() Factor = pc.getFactorMatrix() (neg, zero, pos) = Factor.getInertia() inertia = [neg, zero, pos] expected_dim = 0 # Nocedal & Wright, theorem 16.3 if neg == expected_dim: is_stable = True else: is_stable = False d = {"stable": is_stable} return inertia
def initialize(self, pc): options_prefix = pc.getOptionsPrefix() A, P = pc.getOperators() dm = pc.getDM() appctx = dm.getAppCtx() F = appctx[0].F V = F.arguments()[0].function_space() # create vertically constant version of functionspace mesh = V.mesh() hcell, vcell = mesh.ufl_cell().sub_cells() hele, _ = V.ufl_element().sub_elements() vele = FiniteElement("R", vcell, 0) ele = TensorProductElement(hele, vele) V_1layer = FunctionSpace(mesh, ele) # create interpolation matrix Prol from V_1layer to V v = TestFunction(V_1layer) interp = Interpolator(v, V) Prol = interp.callable().handle self.pc = PETSc.PC().create(comm=pc.comm) self.pc.setOptionsPrefix(options_prefix + 'lumped_') # hack: we actually want to call self.pc.setMGGalerkin() # but there appears to be no petsc4py interface options = PETSc.Options() options[options_prefix + 'lumped_pc_mg_galerkin'] = 'both' self.pc.setOperators(A, P) self.pc.setType("mg") self.pc.setMGLevels(2) self.pc.setMGInterpolation(1, Prol) self.pc.setFromOptions() self.pc.setUp() self.update(pc)
poisson_problem = poisson(dm, {"dx": 0.1, "dy": 0.1, "dz": 0.1}) ksp = PETSc.KSP().create() ksp.setDM(dm) ksp.setComputeRHS(poisson_problem.rhs) ksp.setComputeOperators(poisson_problem.compute_operators) ksp.setFromOptions() if (comm.size <= 1): if not(OptDB.hasName("ksp_type")): ksp.setType(PETSc.KSP().Type.PREONLY) if not(OptDB.hasName("pc_type")): ksp.getPC().setType(PETSc.PC().Type.LU) else: if not(OptDB.hasName("ksp_type")): ksp.setType(PETSc.KSP().Type.GMRES) if not(OptDB.hasName("pc_type")): ksp.getPC().setType(PETSc.PC().Type.BJACOBI) field = dm.createGlobalVector() sol = field.duplicate() start = time.clock() cProfile.run("ksp.solve(field,sol)", sort="time") end = time.clock() print(ksp.getSolution().getArray()[:])
def __init__(self, comm, cpu, rank, dim, maxit, relative, solver): self.A_PETSc = _PETSc.Mat() self.A_PETSc_c = _PETSc.Mat() self.A_PETSc_p = _PETSc.Mat() self.method_PETSc = _PETSc.KSP() self.null_space = None self.comm = comm self.dim = dim self.cpu = cpu self.rank = rank csr = (_np.zeros(self.dim + 1, dtype=_np.int32), _np.zeros(0, dtype=_np.int32), _np.zeros(0)) self.A_PETSc.create(self.comm) self.A_PETSc.setSizes([self.dim, self.dim]) self.A_PETSc.setType('mpiaij') self.A_PETSc.setPreallocationCSR(csr) self.A_PETSc_p.create(self.comm) self.A_PETSc_p.setSizes([self.dim, self.dim]) self.A_PETSc_p.setType('mpiaij') self.A_PETSc_p.setPreallocationCSR(csr) self.A_PETSc_c.create(self.comm) self.A_PETSc_c.setSizes([self.dim, self.dim]) self.A_PETSc_c.setType('mpiaij') self.A_PETSc_c.setPreallocationCSR(csr) self.x_PETSc, self.b_PETSc = self.A_PETSc_p.getVecs() length_x = self.b_PETSc.getOwnershipRange( )[1] - self.b_PETSc.getOwnershipRange()[0] self.method_PETSc.create(self.comm) if solver == "pressure": self.method_PETSc.setType('gmres') #self.method_PETSc.setType('bicg') #self.method_PETSc.setType('bcgs') #self.method_PETSc.setType('cg') #JADIM #self.method_PETSc.setType('preonly') pc = _PETSc.PC() pc.create(self.comm) pc.setType('asm') #additive schwarz #pc.setType('pbjacobi') #JADIM #pc.setType('sor') #pc.setASMType(2) # pc.setType('ilu') self.method_PETSc.setPC(pc) #print self.method_PETSc.getPCSide() if solver == "velocity": self.method_PETSc.setType('bcgs') #self.method_PETSc.setType('gmres') #self.method_PETSc.setType('cg') #JADIM pc = _PETSc.PC() pc.create(self.comm) pc.setType('asm') #additive schwarz #pc.setType('pbjacobi') #JADIM #pc.setType('sor') self.method_PETSc.setPC(pc) pc = self.method_PETSc.getPC() if self.rank == 0: print solver, self.method_PETSc.getType(), pc.getType( ), relative, maxit #self.method_PETSc.setInitialGuessNonzero(1) self.method_PETSc.setInitialGuessNonzero(0) self.method_PETSc.setTolerances(rtol=relative, atol=1e-50, divtol=1e5, max_it=maxit)
a = inner(grad(u), grad(v)) * dx L = f * v * dx + g * v * ds # Compute solution u = Function(V) A, b = assemble_system(a, L, bc) # Fetch underlying PETSc objects A_petsc = as_backend_type(A).mat() b_petsc = as_backend_type(b).vec() x_petsc = as_backend_type(u.vector()).vec() # Create solver, apply preconditioner and solve system ksp = PETSc.KSP().create() ksp.setOperators(A_petsc) pc = PETSc.PC().create() pc.setOperators(A_petsc) pc.setType(pc.Type.JACOBI) ksp.setPC(pc) ksp.solve(b_petsc, x_petsc) # Plot solution plot(u, interactive=True) # Save solution to file file = File("poisson.pvd") file << u
def build_preconditioner(self): opts = PETSc.Options().getAll() if 'snes_lag_preconditioner' in opts: if opts['snes_lag_preconditioner'] == "-1" and hasattr(self, 'P'): self.P.setReusePreconditioner(True) return self.P = PETSc.PC().create(self.comm) # Set the operator appropriately, taking the right subsets (Jmat, Pmat) = self.get_submat() self._subJ = PETScMatrix(Jmat) if self.nullsp is not None: Jmat.setNearNullSpace(self.nullsp) self.P.setOperators(Jmat, Pmat) (self._ptmpvec1, self._ptmpvec2) = map(PETScVector, Jmat.createVecs()) self.P.setType("lu") self.P.setFactorSolverPackage("mumps") self.P.setOptionsPrefix(self.pc_prefix) self.P.setFromOptions() if self.P.getType() == "fieldsplit" and Jmat.getBlockSize( ) <= 1 and self.eqn_subindices is None: if self.fieldsplit_is is None: self.fieldsplit_is = [] for i in range(self.function_space.num_sub_spaces()): subdofs = self.function_space.sub(i).dofmap().dofs() iset = PETSc.IS().createGeneral(subdofs) self.fieldsplit_is.append(("%s" % i, iset)) if self.inact_subindices is None: self.P.setFieldSplitIS(*self.fieldsplit_is) else: # OK. Get the dofs from the inactive set and figure out which split they're from. # Agh. VIs make everything so complicated. fsets = [ set(field[1].getIndices()) for field in self.fieldsplit_is ] inact_fieldsplit_is = {} for field in self.fieldsplit_is: inact_fieldsplit_is[int(field[0])] = [] # OK. Suppose you have a 6x6 matrix and the splits are [1, 2, 3, 4]; [5, 6]. # Suppose further that the inactive indices are [2, 3, 4, 5]. Then what we # want to produce for the fieldsplit of the reduced problem is [1, 2, 3]; [4]. # In other words, we add the *index* of the inactive dof to the reduced split # if the inactive dof is in the full split. # We also need the offset of how many dofs all earlier processes own. from mpi4py import MPI as MPI4 offset = MPI4.COMM_WORLD.exscan( self.inact_subindices.getLocalSize()) if offset is None: offset = 0 for (i, idx) in enumerate(self.inact_subindices.getIndices()): for (j, fset) in enumerate(fsets): if idx in fset: inact_fieldsplit_is[j].append(offset + i) break inact_input = [] for j in inact_fieldsplit_is: iset = PETSc.IS().createGeneral(inact_fieldsplit_is[j], comm=self.comm) inact_input.append(("%s" % j, iset)) for (orig_data, vi_data) in zip(self.fieldsplit_is, inact_input): orig_iset = orig_data[1] vi_iset = vi_data[1] if orig_iset.getSizes() == vi_iset.getSizes(): nullsp = orig_iset.query("nearnullspace") if nullsp is not None: vi_iset.compose("nearnullspace", nullsp) self.P.setFieldSplitIS(*inact_input) if self.eqn_subindices is not None: nullsp = self.eqn_subindices.query("nearnullspace") if nullsp is not None: op = self.P.getOperators()[0] op.setNearNullSpace(nullsp) self.preconditioner_hook() # argh, such a hack. self.P.setUp()