diff --git a/src/PETSc/PC.pyx b/src/PETSc/PC.pyx index 86f7b3e8..112976c9 100644 --- a/src/PETSc/PC.pyx +++ b/src/PETSc/PC.pyx @@ -45,6 +45,7 @@ class PCType(object): KACZMARZ = S_(PCKACZMARZ) TELESCOPE = S_(PCTELESCOPE) LMVM = S_(PCLMVM) + PATCH = S_(PCPATCH) class PCSide(object): # native @@ -103,6 +104,12 @@ class PCFieldSplitSchurFactType(object): UPPER = PC_FIELDSPLIT_SCHUR_FACT_UPPER FULL = PC_FIELDSPLIT_SCHUR_FACT_FULL +class PCPatchConstructType(object): + STAR = PC_PATCH_STAR + VANKA = PC_PATCH_VANKA + USER = PC_PATCH_USER + PYTHON = PC_PATCH_PYTHON + # -------------------------------------------------------------------- cdef class PC(Object): @@ -110,14 +117,15 @@ cdef class PC(Object): Type = PCType Side = PCSide - ASMType = PCASMType - GASMType = PCGASMType - MGType = PCMGType - MGCycleType = PCMGCycleType - GAMGType = PCGAMGType - CompositeType = PCCompositeType - SchurFactType = PCFieldSplitSchurFactType - SchurPreType = PCFieldSplitSchurPreType + ASMType = PCASMType + GASMType = PCGASMType + MGType = PCMGType + MGCycleType = PCMGCycleType + GAMGType = PCGAMGType + CompositeType = PCCompositeType + SchurFactType = PCFieldSplitSchurFactType + SchurPreType = PCFieldSplitSchurPreType + PatchConstructType = PCPatchConstructType # --- xxx --- @@ -644,6 +652,70 @@ cdef class PC(Object): for i from 0 <= i < n: cisfields[i] = (isfields[i]).iset CHKERR( PCBDDCSetDofsSplittingLocal(self.pc, n, cisfields) ) + # --- Patch --- + def setPatchCellNumbering(self, Section sec not None): + CHKERR( PCPatchSetCellNumbering(self.pc, sec.sec) ) + + def setPatchDiscretisationInfo(self, dms, bs, + cellNodeMaps, + subspaceOffsets, + ghostBcNodes, + globalBcNodes): + cdef PetscInt numSubSpaces + cdef PetscInt numGhostBcs, numGlobalBcs + cdef PetscInt *nodesPerCell = NULL + cdef const_PetscInt **ccellNodeMaps = NULL + cdef PetscDM *cdms = NULL + cdef PetscInt *cbs = NULL + cdef PetscInt *csubspaceOffsets = NULL + cdef PetscInt *cghostBcNodes = NULL + cdef PetscInt *cglobalBcNodes = NULL + cdef PetscInt i + + bs = iarray_i(bs, &numSubSpaces, &cbs) + ghostBcNodes = iarray_i(ghostBcNodes, &numGhostBcs, &cghostBcNodes) + globalBcNodes = iarray_i(globalBcNodes, &numGlobalBcs, &cglobalBcNodes) + subspaceOffsets = iarray_i(subspaceOffsets, NULL, &csubspaceOffsets) + + CHKERR( PetscMalloc(numSubSpaces*sizeof(PetscInt), &nodesPerCell) ) + CHKERR( PetscMalloc(numSubSpaces*sizeof(PetscDM), &cdms) ) + CHKERR( PetscMalloc(numSubSpaces*sizeof(PetscInt*), &ccellNodeMaps) ) + for i in range(numSubSpaces): + cdms[i] = (dms[i]).dm + _, nodes = asarray(cellNodeMaps[i]).shape + cellNodeMaps[i] = iarray_i(cellNodeMaps[i], NULL, &(ccellNodeMaps[i])) + nodesPerCell[i] = asInt(nodes) + + # TODO: refactor on the PETSc side to take ISes? + CHKERR( PCPatchSetDiscretisationInfo(self.pc, numSubSpaces, + cdms, cbs, nodesPerCell, + ccellNodeMaps, csubspaceOffsets, + numGhostBcs, cghostBcNodes, + numGlobalBcs, cglobalBcNodes) ) + CHKERR( PetscFree(nodesPerCell) ) + CHKERR( PetscFree(cdms) ) + CHKERR( PetscFree(ccellNodeMaps) ) + + def setPatchComputeOperator(self, operator, args=None, kargs=None): + if args is None: args = () + if kargs is None: kargs = {} + context = (operator, args, kargs) + self.set_attr("__patch_compute_operator__", context) + CHKERR( PCPatchSetComputeOperator(self.pc, PCPatch_ComputeOperator, context) ) + + def setPatchConstructType(self, typ, operator=None, args=None, kargs=None): + if args is None: args = () + if kargs is None: kargs = {} + + if typ in {PC.PatchConstructType.PYTHON, PC.PatchConstructType.USER} and operator is None: + raise ValueError("Must provide operator for USER or PYTHON type") + if operator is not None: + context = (operator, args, kargs) + else: + context = None + self.set_attr("__patch_construction_operator__", context) + CHKERR( PCPatchSetConstructType(self.pc, typ, PCPatch_UserConstructOperator, context) ) + # -------------------------------------------------------------------- del PCType @@ -656,5 +728,6 @@ del PCGAMGType del PCCompositeType del PCFieldSplitSchurPreType del PCFieldSplitSchurFactType +del PCPatchConstructType # -------------------------------------------------------------------- diff --git a/src/PETSc/petscpc.pxi b/src/PETSc/petscpc.pxi index 5ee35257..10ab4dc1 100644 --- a/src/PETSc/petscpc.pxi +++ b/src/PETSc/petscpc.pxi @@ -44,6 +44,7 @@ cdef extern from * nogil: PetscPCType PCKACZMARZ PetscPCType PCTELESCOPE PetscPCType PCLMVM + PetscPCType PCPATCH ctypedef enum PetscPCSide "PCSide": PC_SIDE_DEFAULT @@ -100,6 +101,12 @@ cdef extern from * nogil: PC_FIELDSPLIT_SCHUR_FACT_UPPER PC_FIELDSPLIT_SCHUR_FACT_FULL + ctypedef enum PetscPCPatchConstructType "PCPatchConstructType": + PC_PATCH_STAR + PC_PATCH_VANKA + PC_PATCH_USER + PC_PATCH_PYTHON + int PCCreate(MPI_Comm,PetscPC*) int PCDestroy(PetscPC*) int PCView(PetscPC,PetscViewer) @@ -233,6 +240,24 @@ cdef extern from * nogil: int PCBDDCSetDofsSplitting(PetscPC,PetscInt,PetscIS[]) int PCBDDCSetDofsSplittingLocal(PetscPC,PetscInt,PetscIS[]) + # --- Patch --- + ctypedef int (*PetscPCPatchComputeOperator)(PetscPC, + PetscInt, + PetscMat, + PetscIS, + PetscInt, + const_PetscInt*, + void*) except PETSC_ERR_PYTHON + ctypedef int (*PetscPCPatchConstructOperator)(PetscPC, + PetscInt*, + PetscIS**, + PetscIS*, + void*) except PETSC_ERR_PYTHON + int PCPatchSetCellNumbering(PetscPC, PetscSection) + int PCPatchSetDiscretisationInfo(PetscPC, PetscInt, PetscDM*, PetscInt*, PetscInt*, const_PetscInt**, const_PetscInt*, PetscInt, const_PetscInt*, PetscInt, const_PetscInt*) + int PCPatchSetComputeOperator(PetscPC, PetscPCPatchComputeOperator, void*) + int PCPatchSetConstructType(PetscPC, PetscPCPatchConstructType, PetscPCPatchConstructOperator, void*) + # -------------------------------------------------------------------- cdef extern from "libpetsc4py.h": @@ -242,3 +267,51 @@ cdef extern from "libpetsc4py.h": int PCPythonSetType(PetscPC,char[]) # -------------------------------------------------------------------- + +cdef inline PC ref_PC(PetscPC pc): + cdef PC ob = PC() + ob.pc = pc + PetscINCREF(ob.obj) + return ob + +cdef int PCPatch_ComputeOperator( + PetscPC pc, + PetscInt point, + PetscMat mat, + PetscIS cells, + PetscInt ndof, + const_PetscInt *dofmap, + void *ctx) except PETSC_ERR_PYTHON with gil: + cdef Mat Mat = ref_Mat(mat) + cdef PC Pc = ref_PC(pc) + cdef IS Is = ref_IS(cells) + cdef object context = Pc.get_attr("__patch_compute_operator__") + if context is None and ctx != NULL: context = ctx + assert context is not None and type(context) is tuple + (op, args, kargs) = context + pydofs = asarray(dofmap) + op(Pc, toInt(point), Mat, Is, pydofs, *args, **kargs) + return 0 + + +cdef int PCPatch_UserConstructOperator( + PetscPC pc, + PetscInt *n, + PetscIS **userIS, + PetscIS *userIterationSet, + void *ctx) except PETSC_ERR_PYTHON with gil: + cdef PC Pc = ref_PC(pc) + cdef PetscInt i + cdef object context = Pc.get_attr("__patch_construction_operator__") + if context is None and ctx != NULL: context = ctx + assert context is not None and type(context) is tuple + (op, args, kargs) = context + (patches, iterationSet) = op(Pc, *args, **kargs) + n[0] = len(patches) + CHKERR(PetscMalloc(n[0]*sizeof(PetscIS), userIS)) + for i in range(n[0]): + userIS[0][i] = (patches[i]).iset + PetscINCREF(&(userIS[0][i])) + userIterationSet[0] = (iterationSet).iset + PetscINCREF(&(userIterationSet[0])) + return 0