Barry,<br>Thank you very much. Your codes are very useful !<br><br>Regards,<br>Jiaxun<br><br><b><i>Barry Smith &lt;bsmith@mcs.anl.gov&gt;</i></b> Ð´µÀ£º<blockquote class="replbq" style="border-left: 2px solid rgb(16, 16, 255); margin-left: 5px; padding-left: 5px;"> <br>   Jiaxun,<br><br>     I am assuming you are using the PCSHELL? I have added support for this for <br>you;<br><br>* if you are using petsc-dev<br>    (http://www-unix.mcs.anl.gov/petsc/petsc-as/developers/index.html) you need<br>    only do an hg pull to get my additions then run "make" in<br>    src/ksp/pc/impls/shell.<br><br>* if you are not using petsc-dev (or use the nightly tar ball) then I attach the<br>    three files that were<br>    changed. include/private/pcimpl.h, include/petscpc.h and<br>    src/ksp/pc/impls/shell/shell.c (again run make in src/ksp/pc/impls/shell)<br><br>    If you are actually writing a complete PC and not using
 PCSHELL<br>http://www-unix.mcs.anl.gov/petsc/petsc-as/snapshots/petsc-current/src/ksp/pc/impls/jacobi/jacobi.c.html<br>then you just need to provide a routine PCApplyBA_XXXX() with calling sequence:<br>PC,PCSide,Vec b,Vec x,Vec work<br><br>   Good luck,<br><br>     Barry<br><br><br><br>On Tue, 8 Aug 2006, jiaxun hou wrote:<br><br>&gt; Hi,<br>&gt;<br>&gt;  I met a problem ,when I constructed a user-defined PC. That is I need to defind the process of  P^(-1)Mx in each iteration of GMRES by myself for efficient reason, not only define P^(-1)x . But the Petsc seems to  separate  this process into two parts: the first is y=Mx which is defined in Petsc framework, and the second is P^(-1)y which is defined  by the user. So, is there any way to do it without change the code of Petsc framework?<br>&gt;<br>&gt;  Regards,<br>&gt;  Jiaxun<br>&gt;<br>&gt;<br>&gt; ---------------------------------<br>&gt; ÇÀ×¢ÑÅ»¢Ãâ·ÑÓÊÏä-3.5GÈÝÁ¿£¬20M¸½¼þ£¡/*<br>      Preconditioner module.
 <br>*/<br>#if !defined(__PETSCPC_H)<br>#define __PETSCPC_H<br>#include "petscmat.h"<br>PETSC_EXTERN_CXX_BEGIN<br><br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT  PCInitializePackage(const char[]);<br><br>/*<br>    PCList contains the list of preconditioners currently registered<br>   These are added with the PCRegisterDynamic() macro<br>*/<br>extern PetscFList PCList;<br>#define PCType const char*<br><br>/*S<br>     PC - Abstract PETSc object that manages all preconditioners<br><br>   Level: beginner<br><br>  Concepts: preconditioners<br><br>.seealso:  PCCreate(), PCSetType(), PCType (for list of available types)<br>S*/<br>typedef struct _p_PC* PC;<br><br>/*E<br>    PCType - String with the name of a PETSc preconditioner method or the creation function<br>       with an optional dynamic library name, for example<br>       http://www.mcs.anl.gov/petsc/lib.a:mypccreate()<br><br>   Level: beginner<br><br>   Notes: Click on the links below to see details on a particular
 solver<br><br>.seealso: PCSetType(), PC, PCCreate()<br>E*/<br>#define PCNONE            "none"<br>#define PCJACOBI          "jacobi"<br>#define PCSOR             "sor"<br>#define PCLU              "lu"<br>#define PCSHELL           "shell"<br>#define PCBJACOBI         "bjacobi"<br>#define PCMG              "mg"<br>#define PCEISENSTAT       "eisenstat"<br>#define PCILU             "ilu"<br>#define PCICC             "icc"<br>#define PCASM             "asm"<br>#define PCKSP             "ksp"<br>#define PCCOMPOSITE       "composite"<br>#define PCREDUNDANT       "redundant"<br>#define PCSPAI            "spai"<br>#define PCNN              "nn"<br>#define PCCHOLESKY        "cholesky"<br>#define PCSAMG            "samg"<br>#define PCPBJACOBI        "pbjacobi"<br>#define PCMAT             "mat"<br>#define PCHYPRE           "hypre"<br>#define PCFIELDSPLIT      "fieldsplit"<br>#define PCTFS             "tfs"<br>#define PCML              "ml"<br>#define PCPROMETHEUS     
 "prometheus"<br>#define PCGALERKIN        "galerkin"<br><br>/* Logging support */<br>extern PetscCookie PETSCKSP_DLLEXPORT PC_COOKIE;<br><br>/*E<br>    PCSide - If the preconditioner is to be applied to the left, right<br>     or symmetrically around the operator.<br><br>   Level: beginner<br><br>.seealso: <br>E*/<br>typedef enum { PC_LEFT,PC_RIGHT,PC_SYMMETRIC } PCSide;<br>extern const char *PCSides[];<br><br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCCreate(MPI_Comm,PC*);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCSetType(PC,PCType);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCSetUp(PC);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCSetUpOnBlocks(PC);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCApply(PC,Vec,Vec);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCApplySymmetricLeft(PC,Vec,Vec);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCApplySymmetricRight(PC,Vec,Vec);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCApplyBAorAB(PC,PCSide,Vec,Vec,Vec);<br>EXTERN
 PetscErrorCode PETSCKSP_DLLEXPORT PCApplyTranspose(PC,Vec,Vec);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCHasApplyTranspose(PC,PetscTruth*);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCApplyBAorABTranspose(PC,PCSide,Vec,Vec,Vec);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCApplyRichardson(PC,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,PetscInt);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCApplyRichardsonExists(PC,PetscTruth*);<br><br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCRegisterDestroy(void);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCRegisterAll(const char[]);<br>extern PetscTruth PCRegisterAllCalled;<br><br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCRegister(const char[],const char[],const char[],PetscErrorCode(*)(PC));<br><br>/*MC<br>   PCRegisterDynamic - Adds a method to the preconditioner package.<br><br>   Synopsis:<br>   PetscErrorCode PCRegisterDynamic(char *name_solver,char *path,char *name_create,PetscErrorCode (*routine_create)(PC))<br><br>  
 Not collective<br><br>   Input Parameters:<br>+  name_solver - name of a new user-defined solver<br>.  path - path (either absolute or relative) the library containing this solver<br>.  name_create - name of routine to create method context<br>-  routine_create - routine to create method context<br><br>   Notes:<br>   PCRegisterDynamic() may be called multiple times to add several user-defined preconditioners.<br><br>   If dynamic libraries are used, then the fourth input argument (routine_create)<br>   is ignored.<br><br>   Sample usage:<br>.vb<br>   PCRegisterDynamic("my_solver","/home/username/my_lib/lib/libO/solaris/mylib",<br>              "MySolverCreate",MySolverCreate);<br>.ve<br><br>   Then, your solver can be chosen with the procedural interface via<br>$     PCSetType(pc,"my_solver")<br>   or at runtime via the option<br>$     -pc_type my_solver<br><br>   Level: advanced<br><br>   Notes: ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR},  or ${any environmental
 variable}<br>           occuring in pathname will be replaced with appropriate values.<br>         If your function is not being put into a shared library then use PCRegister() instead<br><br>.keywords: PC, register<br><br>.seealso: PCRegisterAll(), PCRegisterDestroy()<br>M*/<br>#if defined(PETSC_USE_DYNAMIC_LIBRARIES)<br>#define PCRegisterDynamic(a,b,c,d) PCRegister(a,b,c,0)<br>#else<br>#define PCRegisterDynamic(a,b,c,d) PCRegister(a,b,c,d)<br>#endif<br><br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCDestroy(PC);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCSetFromOptions(PC);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCGetType(PC,PCType*);<br><br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCGetFactoredMatrix(PC,Mat*);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCSetModifySubMatrices(PC,PetscErrorCode(*)(PC,PetscInt,const IS[],const IS[],Mat[],void*),void*);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCModifySubMatrices(PC,PetscInt,const IS[],const
 IS[],Mat[],void*);<br><br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCSetOperators(PC,Mat,Mat,MatStructure);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCGetOperators(PC,Mat*,Mat*,MatStructure*);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCGetOperatorsSet(PC,PetscTruth*,PetscTruth*);<br><br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCView(PC,PetscViewer);<br><br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCSetOptionsPrefix(PC,const char[]);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCAppendOptionsPrefix(PC,const char[]);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCGetOptionsPrefix(PC,const char*[]);<br><br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCComputeExplicitOperator(PC,Mat*);<br><br>/*<br>      These are used to provide extra scaling of preconditioned <br>   operator for time-stepping schemes like in SUNDIALS <br>*/<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCDiagonalScale(PC,PetscTruth*);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT
 PCDiagonalScaleLeft(PC,Vec,Vec);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCDiagonalScaleRight(PC,Vec,Vec);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCDiagonalScaleSet(PC,Vec);<br><br>/* ------------- options specific to particular preconditioners --------- */<br><br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCJacobiSetUseRowMax(PC);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCJacobiSetUseAbs(PC);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCSORSetSymmetric(PC,MatSORType);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCSORSetOmega(PC,PetscReal);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCSORSetIterations(PC,PetscInt,PetscInt);<br><br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCEisenstatSetOmega(PC,PetscReal);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCEisenstatNoDiagonalScaling(PC);<br><br>#define USE_PRECONDITIONER_MATRIX 0<br>#define USE_TRUE_MATRIX           1<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCBJacobiSetUseTrueLocal(PC);<br>EXTERN PetscErrorCode
 PETSCKSP_DLLEXPORT PCBJacobiSetTotalBlocks(PC,PetscInt,const PetscInt[]);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCBJacobiSetLocalBlocks(PC,PetscInt,const PetscInt[]);<br><br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCKSPSetUseTrue(PC);<br><br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetApply(PC,PetscErrorCode (*)(void*,Vec,Vec)); <br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetApplyBA(PC,PetscErrorCode (*)(void*,PCSide,Vec,Vec,Vec)); <br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetApplyTranspose(PC,PetscErrorCode (*)(void*,Vec,Vec));<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetSetUp(PC,PetscErrorCode (*)(void*));<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetApplyRichardson(PC,PetscErrorCode (*)(void*,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,PetscInt));<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetView(PC,PetscErrorCode (*)(void*,PetscViewer));<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT
 PCShellSetDestroy(PC,PetscErrorCode (*)(void*));<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCShellGetContext(PC,void**);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetContext(PC,void*);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetName(PC,const char[]);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCShellGetName(PC,char*[]);<br><br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetZeroPivot(PC,PetscReal);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetShiftNonzero(PC,PetscReal); <br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetShiftPd(PC,PetscTruth); <br><br><br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetFill(PC,PetscReal);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetPivoting(PC,PetscReal);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCFactorReorderForNonzeroDiagonal(PC,PetscReal);<br><br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetMatOrdering(PC,MatOrderingType);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT
 PCFactorSetReuseOrdering(PC,PetscTruth);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetReuseFill(PC,PetscTruth);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetUseInPlace(PC);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetAllowDiagonalFill(PC);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetPivotInBlocks(PC,PetscTruth);<br><br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetLevels(PC,PetscInt);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetUseDropTolerance(PC,PetscReal,PetscReal,PetscInt);<br><br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCASMSetLocalSubdomains(PC,PetscInt,IS[]);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCASMSetTotalSubdomains(PC,PetscInt,IS[]);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCASMSetOverlap(PC,PetscInt);<br>/*E<br>    PCASMType - Type of additive Schwarz method to use<br><br>$  PC_ASM_BASIC - symmetric version where residuals from the ghost points are used<br>$                 and computed
 values in ghost regions are added together. Classical<br>$                 standard additive Schwarz<br>$  PC_ASM_RESTRICT - residuals from ghost points are used but computed values in ghost<br>$                    region are discarded. Default<br>$  PC_ASM_INTERPOLATE - residuals from ghost points are not used, computed values in ghost<br>$                       region are added back in<br>$  PC_ASM_NONE - ghost point residuals are not used, computed ghost values are discarded<br>$                not very good.                <br><br>   Level: beginner<br><br>.seealso: PCASMSetType()<br>E*/<br>typedef enum {PC_ASM_BASIC = 3,PC_ASM_RESTRICT = 1,PC_ASM_INTERPOLATE = 2,PC_ASM_NONE = 0} PCASMType;<br>extern const char *PCASMTypes[];<br><br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCASMSetType(PC,PCASMType);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCASMCreateSubdomains2D(PetscInt,PetscInt,PetscInt,PetscInt,PetscInt,PetscInt,PetscInt *,IS **);<br>EXTERN PetscErrorCode
 PETSCKSP_DLLEXPORT PCASMSetUseInPlace(PC);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCASMGetLocalSubdomains(PC,PetscInt*,IS*[]);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCASMGetLocalSubmatrices(PC,PetscInt*,Mat*[]);<br><br>/*E<br>    PCCompositeType - Determines how two or more preconditioner are composed<br><br>$  PC_COMPOSITE_ADDITIVE - results from application of all preconditioners are added together<br>$  PC_COMPOSITE_MULTIPLICATIVE - preconditioners are applied sequentially to the residual freshly<br>$                                computed after the previous preconditioner application<br>$  PC_COMPOSITE_SPECIAL - This is very special for a matrix of the form alpha I + R + S<br>$                         where first preconditioner is built from alpha I + S and second from<br>$                         alpha I + R<br><br>   Level: beginner<br><br>.seealso: PCCompositeSetType()<br>E*/<br>typedef enum
 {PC_COMPOSITE_ADDITIVE,PC_COMPOSITE_MULTIPLICATIVE,PC_COMPOSITE_SPECIAL} PCCompositeType;<br>extern const char *PCCompositeTypes[];<br><br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCCompositeSetUseTrue(PC);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCCompositeSetType(PC,PCCompositeType);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCCompositeAddPC(PC,PCType);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCCompositeGetPC(PC pc,PetscInt n,PC *);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCCompositeSpecialSetAlpha(PC,PetscScalar);<br><br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCRedundantSetScatter(PC,VecScatter,VecScatter);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCRedundantGetOperators(PC,Mat*,Mat*);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCRedundantGetPC(PC,PC*);<br><br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCSPAISetEpsilon(PC,double);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCSPAISetNBSteps(PC,PetscInt);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT
 PCSPAISetMax(PC,PetscInt);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCSPAISetMaxNew(PC,PetscInt);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCSPAISetBlockSize(PC,PetscInt);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCSPAISetCacheSize(PC,PetscInt);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCSPAISetVerbose(PC,PetscInt);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCSPAISetSp(PC,PetscInt);<br><br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCHYPRESetType(PC,const char[]);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCBJacobiGetLocalBlocks(PC,PetscInt*,const PetscInt*[]);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCBJacobiGetTotalBlocks(PC,PetscInt*,const PetscInt*[]);<br><br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetFields(PC,PetscInt,PetscInt*);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetType(PC,PCCompositeType);<br><br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCGalerkinSetRestriction(PC,Mat);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT
 PCGalerkinSetInterpolation(PC,Mat);<br><br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCSetCoordinates(PC,PetscInt,PetscReal*);<br>EXTERN PetscErrorCode PETSCKSP_DLLEXPORT PCSASetVectors(PC,PetscInt,PetscReal *);<br><br><br>PETSC_EXTERN_CXX_END<br>#endif /* __PETSCPC_H */<br><br>#ifndef _PCIMPL<br>#define _PCIMPL<br><br>#include "petscksp.h"<br>#include "petscpc.h"<br><br>typedef struct _PCOps *PCOps;<br>struct _PCOps {<br>  PetscErrorCode (*setup)(PC);<br>  PetscErrorCode (*apply)(PC,Vec,Vec);<br>  PetscErrorCode (*applyrichardson)(PC,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,PetscInt);<br>  PetscErrorCode (*applyBA)(PC,PCSide,Vec,Vec,Vec);<br>  PetscErrorCode (*applytranspose)(PC,Vec,Vec);<br>  PetscErrorCode (*applyBAtranspose)(PC,PetscInt,Vec,Vec,Vec);<br>  PetscErrorCode (*setfromoptions)(PC);<br>  PetscErrorCode (*presolve)(PC,KSP,Vec,Vec);<br>  PetscErrorCode (*postsolve)(PC,KSP,Vec,Vec);  <br>  PetscErrorCode (*getfactoredmatrix)(PC,Mat*);<br>  PetscErrorCode
 (*applysymmetricleft)(PC,Vec,Vec);<br>  PetscErrorCode (*applysymmetricright)(PC,Vec,Vec);<br>  PetscErrorCode (*setuponblocks)(PC);<br>  PetscErrorCode (*destroy)(PC);<br>  PetscErrorCode (*view)(PC,PetscViewer);<br>};<br><br>/*<br>   Preconditioner context<br>*/<br>struct _p_PC {<br>  PETSCHEADER(struct _PCOps);<br>  PetscInt       setupcalled;<br>  MatStructure   flag;<br>  Mat            mat,pmat;<br>  Vec            diagonalscaleright,diagonalscaleleft; /* used for time integration scaling */<br>  PetscTruth     diagonalscale;<br>  PetscErrorCode (*modifysubmatrices)(PC,PetscInt,const IS[],const IS[],Mat[],void*); /* user provided routine */<br>  void           *modifysubmatricesP; /* context for user routine */<br>  void           *data;<br>};<br><br>extern PetscEvent  PC_SetUp, PC_SetUpOnBlocks, PC_Apply, PC_ApplyCoarse, PC_ApplyMultiple, PC_ApplySymmetricLeft;<br>extern PetscEvent  PC_ApplySymmetricRight, PC_ModifySubMatrices;<br><br>#endif<br>#define
 PETSCKSP_DLL<br><br>/*<br>   This provides a simple shell for Fortran (and C programmers) to <br>  create their own preconditioner without writing much interface code.<br>*/<br><br>#include "private/pcimpl.h"        /*I "petscpc.h" I*/<br>#include "private/vecimpl.h"  <br><br>EXTERN_C_BEGIN <br>typedef struct {<br>  void           *ctx;                     /* user provided contexts for preconditioner */<br>  PetscErrorCode (*destroy)(void*);<br>  PetscErrorCode (*setup)(void*);<br>  PetscErrorCode (*apply)(void*,Vec,Vec);<br>  PetscErrorCode (*applyBA)(void*,PCSide,Vec,Vec,Vec);<br>  PetscErrorCode (*presolve)(void*,KSP,Vec,Vec);<br>  PetscErrorCode (*postsolve)(void*,KSP,Vec,Vec);<br>  PetscErrorCode (*view)(void*,PetscViewer);<br>  PetscErrorCode (*applytranspose)(void*,Vec,Vec);<br>  PetscErrorCode (*applyrich)(void*,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,PetscInt);<br>  char           *name;<br>} PC_Shell;<br>EXTERN_C_END<br><br>#undef __FUNCT__  <br>#define
 __FUNCT__ "PCShellGetContext"<br>/*@<br>    PCShellGetContext - Returns the user-provided context associated with a shell PC<br><br>    Not Collective<br><br>    Input Parameter:<br>.   pc - should have been created with PCCreateShell()<br><br>    Output Parameter:<br>.   ctx - the user provided context<br><br>    Level: advanced<br><br>    Notes:<br>    This routine is intended for use within various shell routines<br>    <br>.keywords: PC, shell, get, context<br><br>.seealso: PCCreateShell(), PCShellSetContext()<br>@*/<br>PetscErrorCode PETSCKSP_DLLEXPORT PCShellGetContext(PC pc,void **ctx)<br>{<br>  PetscErrorCode ierr;<br>  PetscTruth     flg;<br><br>  PetscFunctionBegin;<br>  PetscValidHeaderSpecific(pc,PC_COOKIE,1);<br>  PetscValidPointer(ctx,2); <br>  ierr = PetscTypeCompare((PetscObject)pc,PCSHELL,&amp;flg);CHKERRQ(ierr);<br>  if (!flg) *ctx = 0; <br>  else      *ctx = ((PC_Shell*)(pc-&gt;data))-&gt;ctx; <br>  PetscFunctionReturn(0);<br>}<br><br>#undef __FUNCT__ 
 <br>#define __FUNCT__ "PCShellSetContext"<br>/*@C<br>    PCShellSetContext - sets the context for a shell PC<br><br>   Collective on PC<br><br>    Input Parameters:<br>+   pc - the shell PC<br>-   ctx - the context<br><br>   Level: advanced<br><br>   Fortran Notes: The context can only be an integer or a PetscObject<br>      unfortunately it cannot be a Fortran array or derived type.<br><br>.seealso: PCCreateShell(), PCShellGetContext()<br>@*/<br>PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetContext(PC pc,void *ctx)<br>{<br>  PC_Shell      *shell = (PC_Shell*)pc-&gt;data;<br>  PetscErrorCode ierr;<br>  PetscTruth     flg;<br><br>  PetscFunctionBegin;<br>  PetscValidHeaderSpecific(pc,PC_COOKIE,1);<br>  ierr = PetscTypeCompare((PetscObject)pc,PCSHELL,&amp;flg);CHKERRQ(ierr);<br>  if (flg) {<br>    shell-&gt;ctx = ctx;<br>  }<br>  PetscFunctionReturn(0);<br>}<br><br>#undef __FUNCT__  <br>#define __FUNCT__ "PCSetUp_Shell"<br>static PetscErrorCode PCSetUp_Shell(PC pc)<br>{<br> 
 PC_Shell       *shell;<br>  PetscErrorCode ierr;<br><br>  PetscFunctionBegin;<br>  shell = (PC_Shell*)pc-&gt;data;<br>  if (shell-&gt;setup) {<br>    CHKMEMQ;<br>    ierr  = (*shell-&gt;setup)(shell-&gt;ctx);CHKERRQ(ierr);<br>    CHKMEMQ;<br>  }<br>  PetscFunctionReturn(0);<br>}<br><br>#undef __FUNCT__  <br>#define __FUNCT__ "PCApply_Shell"<br>static PetscErrorCode PCApply_Shell(PC pc,Vec x,Vec y)<br>{<br>  PC_Shell       *shell;<br>  PetscErrorCode ierr;<br><br>  PetscFunctionBegin;<br>  shell = (PC_Shell*)pc-&gt;data;<br>  if (!shell-&gt;apply) SETERRQ(PETSC_ERR_USER,"No apply() routine provided to Shell PC");<br>  PetscStackPush("PCSHELL user function");<br>  CHKMEMQ;<br>  ierr  = (*shell-&gt;apply)(shell-&gt;ctx,x,y);CHKERRQ(ierr);<br>  CHKMEMQ;<br>  PetscStackPop;<br>  PetscFunctionReturn(0);<br>}<br><br>#undef __FUNCT__  <br>#define __FUNCT__ "PCApplyBA_Shell"<br>static PetscErrorCode PCApplyBA_Shell(PC pc,PCSide side,Vec x,Vec y,Vec w)<br>{<br>  PC_Shell      
 *shell;<br>  PetscErrorCode ierr;<br><br>  PetscFunctionBegin;<br>  shell = (PC_Shell*)pc-&gt;data;<br>  if (!shell-&gt;applyBA) SETERRQ(PETSC_ERR_USER,"No applyBA() routine provided to Shell PC");<br>  PetscStackPush("PCSHELL user function BA");<br>  CHKMEMQ;<br>  ierr  = (*shell-&gt;applyBA)(shell-&gt;ctx,side,x,y,w);CHKERRQ(ierr);<br>  CHKMEMQ;<br>  PetscStackPop;<br>  PetscFunctionReturn(0);<br>}<br><br>#undef __FUNCT__  <br>#define __FUNCT__ "PCPreSolve_Shell"<br>static PetscErrorCode PCPreSolve_Shell(PC pc,KSP ksp,Vec b,Vec x)<br>{<br>  PC_Shell       *shell;<br>  PetscErrorCode ierr;<br><br>  PetscFunctionBegin;<br>  shell = (PC_Shell*)pc-&gt;data;<br>  if (!shell-&gt;presolve) SETERRQ(PETSC_ERR_USER,"No presolve() routine provided to Shell PC");<br>  ierr  = (*shell-&gt;presolve)(shell-&gt;ctx,ksp,b,x);CHKERRQ(ierr);<br>  PetscFunctionReturn(0);<br>}<br><br>#undef __FUNCT__  <br>#define __FUNCT__ "PCPostSolve_Shell"<br>static PetscErrorCode PCPostSolve_Shell(PC
 pc,KSP ksp,Vec b,Vec x)<br>{<br>  PC_Shell       *shell;<br>  PetscErrorCode ierr;<br><br>  PetscFunctionBegin;<br>  shell = (PC_Shell*)pc-&gt;data;<br>  if (!shell-&gt;postsolve) SETERRQ(PETSC_ERR_USER,"No postsolve() routine provided to Shell PC");<br>  ierr  = (*shell-&gt;postsolve)(shell-&gt;ctx,ksp,b,x);CHKERRQ(ierr);<br>  PetscFunctionReturn(0);<br>}<br><br>#undef __FUNCT__  <br>#define __FUNCT__ "PCApplyTranspose_Shell"<br>static PetscErrorCode PCApplyTranspose_Shell(PC pc,Vec x,Vec y)<br>{<br>  PC_Shell       *shell;<br>  PetscErrorCode ierr;<br><br>  PetscFunctionBegin;<br>  shell = (PC_Shell*)pc-&gt;data;<br>  if (!shell-&gt;applytranspose) SETERRQ(PETSC_ERR_USER,"No applytranspose() routine provided to Shell PC");<br>  ierr  = (*shell-&gt;applytranspose)(shell-&gt;ctx,x,y);CHKERRQ(ierr);<br>  PetscFunctionReturn(0);<br>}<br><br>#undef __FUNCT__  <br>#define __FUNCT__ "PCApplyRichardson_Shell"<br>static PetscErrorCode PCApplyRichardson_Shell(PC pc,Vec x,Vec y,Vec
 w,PetscReal rtol,PetscReal abstol, PetscReal dtol,PetscInt it)<br>{<br>  PetscErrorCode ierr;<br>  PC_Shell       *shell;<br><br>  PetscFunctionBegin;<br>  shell = (PC_Shell*)pc-&gt;data;<br>  ierr  = (*shell-&gt;applyrich)(shell-&gt;ctx,x,y,w,rtol,abstol,dtol,it);CHKERRQ(ierr);<br>  PetscFunctionReturn(0);<br>}<br><br>#undef __FUNCT__  <br>#define __FUNCT__ "PCDestroy_Shell"<br>static PetscErrorCode PCDestroy_Shell(PC pc)<br>{<br>  PC_Shell       *shell = (PC_Shell*)pc-&gt;data;<br>  PetscErrorCode ierr;<br><br>  PetscFunctionBegin;<br>  ierr = PetscStrfree(shell-&gt;name);CHKERRQ(ierr);<br>  if (shell-&gt;destroy) {<br>    ierr  = (*shell-&gt;destroy)(shell-&gt;ctx);CHKERRQ(ierr);<br>  }<br>  ierr = PetscFree(shell);CHKERRQ(ierr);<br>  PetscFunctionReturn(0);<br>}<br><br>#undef __FUNCT__  <br>#define __FUNCT__ "PCView_Shell"<br>static PetscErrorCode PCView_Shell(PC pc,PetscViewer viewer)<br>{<br>  PC_Shell       *shell = (PC_Shell*)pc-&gt;data;<br>  PetscErrorCode
 ierr;<br>  PetscTruth     iascii;<br><br>  PetscFunctionBegin;<br>  ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&amp;iascii);CHKERRQ(ierr);<br>  if (iascii) {<br>    if (shell-&gt;name) {ierr = PetscViewerASCIIPrintf(viewer,"  Shell: %s\n",shell-&gt;name);CHKERRQ(ierr);}<br>    else             {ierr = PetscViewerASCIIPrintf(viewer,"  Shell: no name\n");CHKERRQ(ierr);}<br>  }<br>  if (shell-&gt;view) {<br>    ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);<br>    ierr  = (*shell-&gt;view)(shell-&gt;ctx,viewer);CHKERRQ(ierr);<br>    ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);<br>  }<br>  PetscFunctionReturn(0);<br>}<br><br>/* ------------------------------------------------------------------------------*/<br>EXTERN_C_BEGIN<br>#undef __FUNCT__  <br>#define __FUNCT__ "PCShellSetDestroy_Shell"<br>PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetDestroy_Shell(PC pc, PetscErrorCode (*destroy)(void*))<br>{<br>  PC_Shell *shell;<br><br> 
 PetscFunctionBegin;<br>  shell          = (PC_Shell*)pc-&gt;data;<br>  shell-&gt;destroy = destroy;<br>  PetscFunctionReturn(0);<br>}<br>EXTERN_C_END<br><br>EXTERN_C_BEGIN<br>#undef __FUNCT__  <br>#define __FUNCT__ "PCShellSetSetUp_Shell"<br>PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetSetUp_Shell(PC pc, PetscErrorCode (*setup)(void*))<br>{<br>  PC_Shell *shell;<br><br>  PetscFunctionBegin;<br>  shell        = (PC_Shell*)pc-&gt;data;<br>  shell-&gt;setup = setup;<br>  PetscFunctionReturn(0);<br>}<br>EXTERN_C_END<br><br>EXTERN_C_BEGIN<br>#undef __FUNCT__  <br>#define __FUNCT__ "PCShellSetApply_Shell"<br>PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetApply_Shell(PC pc,PetscErrorCode (*apply)(void*,Vec,Vec))<br>{<br>  PC_Shell *shell;<br><br>  PetscFunctionBegin;<br>  shell        = (PC_Shell*)pc-&gt;data;<br>  shell-&gt;apply = apply;<br>  PetscFunctionReturn(0);<br>}<br>EXTERN_C_END<br><br>EXTERN_C_BEGIN<br>#undef __FUNCT__  <br>#define __FUNCT__
 "PCShellSetApplyBA_Shell"<br>PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetApplyBA_Shell(PC pc,PetscErrorCode (*apply)(void*,PCSide,Vec,Vec,Vec))<br>{<br>  PC_Shell *shell;<br><br>  PetscFunctionBegin;<br>  shell          = (PC_Shell*)pc-&gt;data;<br>  shell-&gt;applyBA = apply;<br>  PetscFunctionReturn(0);<br>}<br>EXTERN_C_END<br><br>EXTERN_C_BEGIN<br>#undef __FUNCT__  <br>#define __FUNCT__ "PCShellSetPreSolve_Shell"<br>PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetPreSolve_Shell(PC pc,PetscErrorCode (*presolve)(void*,KSP,Vec,Vec))<br>{<br>  PC_Shell *shell;<br><br>  PetscFunctionBegin;<br>  shell             = (PC_Shell*)pc-&gt;data;<br>  shell-&gt;presolve   = presolve;<br>  if (presolve) {<br>    pc-&gt;ops-&gt;presolve = PCPreSolve_Shell;<br>  } else {<br>    pc-&gt;ops-&gt;presolve = 0;<br>  }<br>  PetscFunctionReturn(0);<br>}<br>EXTERN_C_END<br><br>EXTERN_C_BEGIN<br>#undef __FUNCT__  <br>#define __FUNCT__ "PCShellSetPostSolve_Shell"<br>PetscErrorCode PETSCKSP_DLLEXPORT
 PCShellSetPostSolve_Shell(PC pc,PetscErrorCode (*postsolve)(void*,KSP,Vec,Vec))<br>{<br>  PC_Shell *shell;<br><br>  PetscFunctionBegin;<br>  shell           = (PC_Shell*)pc-&gt;data;<br>  shell-&gt;postsolve = postsolve;<br>  if (postsolve) {<br>    pc-&gt;ops-&gt;postsolve = PCPostSolve_Shell;<br>  } else {<br>    pc-&gt;ops-&gt;postsolve = 0;<br>  }<br>  PetscFunctionReturn(0);<br>}<br>EXTERN_C_END<br><br>EXTERN_C_BEGIN<br>#undef __FUNCT__  <br>#define __FUNCT__ "PCShellSetView_Shell"<br>PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetView_Shell(PC pc,PetscErrorCode (*view)(void*,PetscViewer))<br>{<br>  PC_Shell *shell;<br><br>  PetscFunctionBegin;<br>  shell        = (PC_Shell*)pc-&gt;data;<br>  shell-&gt;view = view;<br>  PetscFunctionReturn(0);<br>}<br>EXTERN_C_END<br><br>EXTERN_C_BEGIN<br>#undef __FUNCT__  <br>#define __FUNCT__ "PCShellSetApplyTranspose_Shell"<br>PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetApplyTranspose_Shell(PC pc,PetscErrorCode
 (*applytranspose)(void*,Vec,Vec))<br>{<br>  PC_Shell *shell;<br><br>  PetscFunctionBegin;<br>  shell                 = (PC_Shell*)pc-&gt;data;<br>  shell-&gt;applytranspose = applytranspose;<br>  PetscFunctionReturn(0);<br>}<br>EXTERN_C_END<br><br>EXTERN_C_BEGIN<br>#undef __FUNCT__  <br>#define __FUNCT__ "PCShellSetName_Shell"<br>PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetName_Shell(PC pc,const char name[])<br>{<br>  PC_Shell       *shell;<br>  PetscErrorCode ierr;<br><br>  PetscFunctionBegin;<br>  shell = (PC_Shell*)pc-&gt;data;<br>  ierr = PetscStrfree(shell-&gt;name);CHKERRQ(ierr);    <br>  ierr = PetscStrallocpy(name,&amp;shell-&gt;name);CHKERRQ(ierr);<br>  PetscFunctionReturn(0);<br>}<br>EXTERN_C_END<br><br>EXTERN_C_BEGIN<br>#undef __FUNCT__  <br>#define __FUNCT__ "PCShellGetName_Shell"<br>PetscErrorCode PETSCKSP_DLLEXPORT PCShellGetName_Shell(PC pc,char *name[])<br>{<br>  PC_Shell *shell;<br><br>  PetscFunctionBegin;<br>  shell  = (PC_Shell*)pc-&gt;data;<br>  *name 
 = shell-&gt;name;<br>  PetscFunctionReturn(0);<br>}<br>EXTERN_C_END<br><br>EXTERN_C_BEGIN<br>#undef __FUNCT__  <br>#define __FUNCT__ "PCShellSetApplyRichardson_Shell"<br>PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetApplyRichardson_Shell(PC pc,PetscErrorCode (*apply)(void*,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,PetscInt))<br>{<br>  PC_Shell *shell;<br><br>  PetscFunctionBegin;<br>  shell                     = (PC_Shell*)pc-&gt;data;<br>  pc-&gt;ops-&gt;applyrichardson  = PCApplyRichardson_Shell;<br>  shell-&gt;applyrich          = apply;<br>  PetscFunctionReturn(0);<br>}<br>EXTERN_C_END<br><br>/* -------------------------------------------------------------------------------*/<br><br>#undef __FUNCT__  <br>#define __FUNCT__ "PCShellSetDestroy"<br>/*@C<br>   PCShellSetDestroy - Sets routine to use to destroy the user-provided <br>   application context.<br><br>   Collective on PC<br><br>   Input Parameters:<br>+  pc - the preconditioner context<br>.  destroy - the
 application-provided destroy routine<br><br>   Calling sequence of destroy:<br>.vb<br>   PetscErrorCode destroy (void *ptr)<br>.ve<br><br>.  ptr - the application context<br><br>   Level: developer<br><br>.keywords: PC, shell, set, destroy, user-provided<br><br>.seealso: PCShellSetApply(), PCShellSetContext()<br>@*/<br>PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetDestroy(PC pc,PetscErrorCode (*destroy)(void*))<br>{<br>  PetscErrorCode ierr,(*f)(PC,PetscErrorCode (*)(void*));<br><br>  PetscFunctionBegin;<br>  PetscValidHeaderSpecific(pc,PC_COOKIE,1);<br>  ierr = PetscObjectQueryFunction((PetscObject)pc,"PCShellSetDestroy_C",(void (**)(void))&amp;f);CHKERRQ(ierr);<br>  if (f) {<br>    ierr = (*f)(pc,destroy);CHKERRQ(ierr);<br>  }<br>  PetscFunctionReturn(0);<br>}<br><br><br>#undef __FUNCT__  <br>#define __FUNCT__ "PCShellSetSetUp"<br>/*@C<br>   PCShellSetSetUp - Sets routine to use to "setup" the preconditioner whenever the <br>   matrix operator is changed.<br><br>  
 Collective on PC<br><br>   Input Parameters:<br>+  pc - the preconditioner context<br>.  setup - the application-provided setup routine<br><br>   Calling sequence of setup:<br>.vb<br>   PetscErrorCode setup (void *ptr)<br>.ve<br><br>.  ptr - the application context<br><br>   Level: developer<br><br>.keywords: PC, shell, set, setup, user-provided<br><br>.seealso: PCShellSetApplyRichardson(), PCShellSetApply(), PCShellSetContext()<br>@*/<br>PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetSetUp(PC pc,PetscErrorCode (*setup)(void*))<br>{<br>  PetscErrorCode ierr,(*f)(PC,PetscErrorCode (*)(void*));<br><br>  PetscFunctionBegin;<br>  PetscValidHeaderSpecific(pc,PC_COOKIE,1);<br>  ierr = PetscObjectQueryFunction((PetscObject)pc,"PCShellSetSetUp_C",(void (**)(void))&amp;f);CHKERRQ(ierr);<br>  if (f) {<br>    ierr = (*f)(pc,setup);CHKERRQ(ierr);<br>  }<br>  PetscFunctionReturn(0);<br>}<br><br><br>#undef __FUNCT__  <br>#define __FUNCT__ "PCShellSetView"<br>/*@C<br>   PCShellSetView -
 Sets routine to use as viewer of shell preconditioner<br><br>   Collective on PC<br><br>   Input Parameters:<br>+  pc - the preconditioner context<br>-  view - the application-provided view routine<br><br>   Calling sequence of apply:<br>.vb<br>   PetscErrorCode view(void *ptr,PetscViewer v)<br>.ve<br><br>+  ptr - the application context<br>-  v   - viewer<br><br>   Level: developer<br><br>.keywords: PC, shell, set, apply, user-provided<br><br>.seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose()<br>@*/<br>PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetView(PC pc,PetscErrorCode (*view)(void*,PetscViewer))<br>{<br>  PetscErrorCode ierr,(*f)(PC,PetscErrorCode (*)(void*,PetscViewer));<br><br>  PetscFunctionBegin;<br>  PetscValidHeaderSpecific(pc,PC_COOKIE,1);<br>  ierr = PetscObjectQueryFunction((PetscObject)pc,"PCShellSetView_C",(void (**)(void))&amp;f);CHKERRQ(ierr);<br>  if (f) {<br>    ierr = (*f)(pc,view);CHKERRQ(ierr);<br>  }<br> 
 PetscFunctionReturn(0);<br>}<br><br>#undef __FUNCT__  <br>#define __FUNCT__ "PCShellSetApply"<br>/*@C<br>   PCShellSetApply - Sets routine to use as preconditioner.<br><br>   Collective on PC<br><br>   Input Parameters:<br>+  pc - the preconditioner context<br>-  apply - the application-provided preconditioning routine<br><br>   Calling sequence of apply:<br>.vb<br>   PetscErrorCode apply (void *ptr,Vec xin,Vec xout)<br>.ve<br><br>+  ptr - the application context<br>.  xin - input vector<br>-  xout - output vector<br><br>   Level: developer<br><br>.keywords: PC, shell, set, apply, user-provided<br><br>.seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose(), PCShellSetContext(), PCShellSetApplyBA()<br>@*/<br>PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetApply(PC pc,PetscErrorCode (*apply)(void*,Vec,Vec))<br>{<br>  PetscErrorCode ierr,(*f)(PC,PetscErrorCode (*)(void*,Vec,Vec));<br><br>  PetscFunctionBegin;<br> 
 PetscValidHeaderSpecific(pc,PC_COOKIE,1);<br>  ierr = PetscObjectQueryFunction((PetscObject)pc,"PCShellSetApply_C",(void (**)(void))&amp;f);CHKERRQ(ierr);<br>  if (f) {<br>    ierr = (*f)(pc,apply);CHKERRQ(ierr);<br>  }<br>  PetscFunctionReturn(0);<br>}<br><br>#undef __FUNCT__  <br>#define __FUNCT__ "PCShellSetApplyBA"<br>/*@C<br>   PCShellSetApplyBA - Sets routine to use as preconditioner times operator.<br><br>   Collective on PC<br><br>   Input Parameters:<br>+  pc - the preconditioner context<br>-  applyBA - the application-provided BA routine<br><br>   Calling sequence of apply:<br>.vb<br>   PetscErrorCode applyBA (void *ptr,Vec xin,Vec xout)<br>.ve<br><br>+  ptr - the application context<br>.  xin - input vector<br>-  xout - output vector<br><br>   Level: developer<br><br>.keywords: PC, shell, set, apply, user-provided<br><br>.seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose(), PCShellSetContext(),
 PCShellSetApply()<br>@*/<br>PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetApplyBA(PC pc,PetscErrorCode (*applyBA)(void*,PCSide,Vec,Vec,Vec))<br>{<br>  PetscErrorCode ierr,(*f)(PC,PetscErrorCode (*)(void*,PCSide,Vec,Vec,Vec));<br><br>  PetscFunctionBegin;<br>  PetscValidHeaderSpecific(pc,PC_COOKIE,1);<br>  ierr = PetscObjectQueryFunction((PetscObject)pc,"PCShellSetApplyBA_C",(void (**)(void))&amp;f);CHKERRQ(ierr);<br>  if (f) {<br>    ierr = (*f)(pc,applyBA);CHKERRQ(ierr);<br>  }<br>  PetscFunctionReturn(0);<br>}<br><br>#undef __FUNCT__  <br>#define __FUNCT__ "PCShellSetApplyTranspose"<br>/*@C<br>   PCShellSetApplyTranspose - Sets routine to use as preconditioner transpose.<br><br>   Collective on PC<br><br>   Input Parameters:<br>+  pc - the preconditioner context<br>-  apply - the application-provided preconditioning transpose routine<br><br>   Calling sequence of apply:<br>.vb<br>   PetscErrorCode applytranspose (void *ptr,Vec xin,Vec xout)<br>.ve<br><br>+  ptr - the
 application context<br>.  xin - input vector<br>-  xout - output vector<br><br>   Level: developer<br><br>   Notes: <br>   Uses the same context variable as PCShellSetApply().<br><br>.keywords: PC, shell, set, apply, user-provided<br><br>.seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApply(), PCSetContext(), PCShellSetApplyBA()<br>@*/<br>PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetApplyTranspose(PC pc,PetscErrorCode (*applytranspose)(void*,Vec,Vec))<br>{<br>  PetscErrorCode ierr,(*f)(PC,PetscErrorCode (*)(void*,Vec,Vec));<br><br>  PetscFunctionBegin;<br>  PetscValidHeaderSpecific(pc,PC_COOKIE,1);<br>  ierr = PetscObjectQueryFunction((PetscObject)pc,"PCShellSetApplyTranspose_C",(void (**)(void))&amp;f);CHKERRQ(ierr);<br>  if (f) {<br>    ierr = (*f)(pc,applytranspose);CHKERRQ(ierr);<br>  }<br>  PetscFunctionReturn(0);<br>}<br><br>#undef __FUNCT__  <br>#define __FUNCT__ "PCShellSetPreSolve"<br>/*@C<br>   PCShellSetPreSolve - Sets routine to apply to the
 operators/vectors before a KSPSolve() is<br>      applied. This usually does something like scale the linear system in some application <br>      specific way.<br><br>   Collective on PC<br><br>   Input Parameters:<br>+  pc - the preconditioner context<br>-  presolve - the application-provided presolve routine<br><br>   Calling sequence of presolve:<br>.vb<br>   PetscErrorCode presolve (void *ptr,KSP ksp,Vec b,Vec x)<br>.ve<br><br>+  ptr - the application context<br>.  xin - input vector<br>-  xout - output vector<br><br>   Level: developer<br><br>.keywords: PC, shell, set, apply, user-provided<br><br>.seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose(), PCShellSetPostSolve(), PCShellSetContext()<br>@*/<br>PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetPreSolve(PC pc,PetscErrorCode (*presolve)(void*,KSP,Vec,Vec))<br>{<br>  PetscErrorCode ierr,(*f)(PC,PetscErrorCode (*)(void*,KSP,Vec,Vec));<br><br>  PetscFunctionBegin;<br> 
 PetscValidHeaderSpecific(pc,PC_COOKIE,1);<br>  ierr = PetscObjectQueryFunction((PetscObject)pc,"PCShellSetPreSolve_C",(void (**)(void))&amp;f);CHKERRQ(ierr);<br>  if (f) {<br>    ierr = (*f)(pc,presolve);CHKERRQ(ierr);<br>  }<br>  PetscFunctionReturn(0);<br>}<br><br>#undef __FUNCT__  <br>#define __FUNCT__ "PCShellSetPostSolve"<br>/*@C<br>   PCShellSetPostSolve - Sets routine to apply to the operators/vectors before a KSPSolve() is<br>      applied. This usually does something like scale the linear system in some application <br>      specific way.<br><br>   Collective on PC<br><br>   Input Parameters:<br>+  pc - the preconditioner context<br>-  postsolve - the application-provided presolve routine<br><br>   Calling sequence of postsolve:<br>.vb<br>   PetscErrorCode postsolve(void *ptr,KSP ksp,Vec b,Vec x)<br>.ve<br><br>+  ptr - the application context<br>.  xin - input vector<br>-  xout - output vector<br><br>   Level: developer<br><br>.keywords: PC, shell, set, apply,
 user-provided<br><br>.seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose(), PCShellSetPreSolve(), PCShellSetContext()<br>@*/<br>PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetPostSolve(PC pc,PetscErrorCode (*postsolve)(void*,KSP,Vec,Vec))<br>{<br>  PetscErrorCode ierr,(*f)(PC,PetscErrorCode (*)(void*,KSP,Vec,Vec));<br><br>  PetscFunctionBegin;<br>  PetscValidHeaderSpecific(pc,PC_COOKIE,1);<br>  ierr = PetscObjectQueryFunction((PetscObject)pc,"PCShellSetPostSolve_C",(void (**)(void))&amp;f);CHKERRQ(ierr);<br>  if (f) {<br>    ierr = (*f)(pc,postsolve);CHKERRQ(ierr);<br>  }<br>  PetscFunctionReturn(0);<br>}<br><br>#undef __FUNCT__  <br>#define __FUNCT__ "PCShellSetName"<br>/*@C<br>   PCShellSetName - Sets an optional name to associate with a shell<br>   preconditioner.<br><br>   Not Collective<br><br>   Input Parameters:<br>+  pc - the preconditioner context<br>-  name - character string describing shell preconditioner<br><br>   Level:
 developer<br><br>.keywords: PC, shell, set, name, user-provided<br><br>.seealso: PCShellGetName()<br>@*/<br>PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetName(PC pc,const char name[])<br>{<br>  PetscErrorCode ierr,(*f)(PC,const char []);<br><br>  PetscFunctionBegin;<br>  PetscValidHeaderSpecific(pc,PC_COOKIE,1);<br>  ierr = PetscObjectQueryFunction((PetscObject)pc,"PCShellSetName_C",(void (**)(void))&amp;f);CHKERRQ(ierr);<br>  if (f) {<br>    ierr = (*f)(pc,name);CHKERRQ(ierr);<br>  }<br>  PetscFunctionReturn(0);<br>}<br><br>#undef __FUNCT__  <br>#define __FUNCT__ "PCShellGetName"<br>/*@C<br>   PCShellGetName - Gets an optional name that the user has set for a shell<br><br>=== message truncated ===</blockquote><br><p>&#32;__________________________________________________<br>¸Ï¿ì×¢²áÑÅ»¢³¬´óÈÝÁ¿Ãâ·ÑÓÊÏä?<br>http://cn.mail.yahoo.com