Date: 2022-03-04T17:38:56+00:00

Actual source code: parms.c

      1: #define PETSCKSP_DLL

      3: /*
      4:    Provides an interface to pARMS.
      5:    Requires pARMS 3.2 or later.
      6: */

      8: #include <petsc/private/pcimpl.h>

     10: #if defined(PETSC_USE_COMPLEX)
     11: #define DBL_CMPLX
     12: #else
     13: #define DBL
     14: #endif
     15: #define USE_MPI
     16: #define REAL double
     17: #define HAS_BLAS
     18: #define FORTRAN_UNDERSCORE
     19: #include "parms_sys.h"
     20: #undef FLOAT
     21: #define FLOAT PetscScalar
     22: #include <parms.h>

     24: /*
     25:    Private context (data structure) for the  preconditioner.
     26: */
     27: typedef struct {
     28:   parms_Map         map;
     29:   parms_Mat         A;
     30:   parms_PC          pc;
     31:   PCPARMSGlobalType global;
     32:   PCPARMSLocalType  local;
     33:   PetscInt          levels, blocksize, maxdim, maxits, lfil[7];
     34:   PetscBool         nonsymperm, meth[8];
     35:   PetscReal         solvetol, indtol, droptol[7];
     36:   PetscScalar       *lvec0, *lvec1;
     37: } PC_PARMS;

     39: static PetscErrorCode PCSetUp_PARMS(PC pc)
     40: {
     41:   Mat               pmat;
     42:   PC_PARMS          *parms = (PC_PARMS*)pc->data;
     43:   const PetscInt    *mapptr0;
     44:   PetscInt          n, lsize, low, high, i, pos, ncols, length;
     45:   int               *maptmp, *mapptr, *ia, *ja, *ja1, *im;
     46:   PetscScalar       *aa, *aa1;
     47:   const PetscInt    *cols;
     48:   PetscInt          meth[8];
     49:   const PetscScalar *values;
     50:   PetscErrorCode    ierr;
     51:   MatInfo           matinfo;
     52:   PetscMPIInt       rank, npro;

     55:   /* Get preconditioner matrix from PETSc and setup pARMS structs */
     56:   PCGetOperators(pc,NULL,&pmat);
     57:   MPI_Comm_size(PetscObjectComm((PetscObject)pmat),&npro);
     58:   MPI_Comm_rank(PetscObjectComm((PetscObject)pmat),&rank);

     60:   MatGetSize(pmat,&n,NULL);
     61:   PetscMalloc1(npro+1,&mapptr);
     62:   PetscMalloc1(n,&maptmp);
     63:   MatGetOwnershipRanges(pmat,&mapptr0);
     64:   low   = mapptr0[rank];
     65:   high  = mapptr0[rank+1];
     66:   lsize = high - low;

     68:   for (i=0; i<npro+1; i++) mapptr[i] = mapptr0[i]+1;
     69:   for (i = 0; i<n; i++) maptmp[i] = i+1;

     71:   /* if created, destroy the previous map */
     72:   if (parms->map) {
     73:     parms_MapFree(&parms->map);
     74:     parms->map = NULL;
     75:   }

     77:   /* create pARMS map object */
     78:   parms_MapCreateFromPtr(&parms->map,(int)n,maptmp,mapptr,PetscObjectComm((PetscObject)pmat),1,NONINTERLACED);

     80:   /* if created, destroy the previous pARMS matrix */
     81:   if (parms->A) {
     82:     parms_MatFree(&parms->A);
     83:     parms->A = NULL;
     84:   }

     86:   /* create pARMS mat object */
     87:   parms_MatCreate(&parms->A,parms->map);

     89:   /* setup and copy csr data structure for pARMS */
     90:   PetscMalloc1(lsize+1,&ia);
     91:   ia[0]  = 1;
     92:   MatGetInfo(pmat,MAT_LOCAL,&matinfo);
     93:   length = matinfo.nz_used;
     94:   PetscMalloc1(length,&ja);
     95:   PetscMalloc1(length,&aa);

     97:   for (i = low; i<high; i++) {
     98:     pos         = ia[i-low]-1;
     99:     MatGetRow(pmat,i,&ncols,&cols,&values);
    100:     ia[i-low+1] = ia[i-low] + ncols;

    102:     if (ia[i-low+1] >= length) {
    103:       length += ncols;
    104:       PetscMalloc1(length,&ja1);
    105:       PetscArraycpy(ja1,ja,ia[i-low]-1);
    106:       PetscFree(ja);
    107:       ja      = ja1;
    108:       PetscMalloc1(length,&aa1);
    109:       PetscArraycpy(aa1,aa,ia[i-low]-1);
    110:       PetscFree(aa);
    111:       aa      = aa1;
    112:     }
    113:     PetscArraycpy(&ja[pos],cols,ncols);
    114:     PetscArraycpy(&aa[pos],values,ncols);
    115:     MatRestoreRow(pmat,i,&ncols,&cols,&values);
    116:   }

    118:   /* csr info is for local matrix so initialize im[] locally */
    119:   PetscMalloc1(lsize,&im);
    120:   PetscArraycpy(im,&maptmp[mapptr[rank]-1],lsize);

    122:   /* 1-based indexing */
    123:   for (i=0; i<ia[lsize]-1; i++) ja[i] = ja[i]+1;

    125:   /* Now copy csr matrix to parms_mat object */
    126:   parms_MatSetValues(parms->A,(int)lsize,im,ia,ja,aa,INSERT);

    128:   /* free memory */
    129:   PetscFree(maptmp);
    130:   PetscFree(mapptr);
    131:   PetscFree(aa);
    132:   PetscFree(ja);
    133:   PetscFree(ia);
    134:   PetscFree(im);

    136:   /* setup parms matrix */
    137:   parms_MatSetup(parms->A);

    139:   /* if created, destroy the previous pARMS pc */
    140:   if (parms->pc) {
    141:     parms_PCFree(&parms->pc);
    142:     parms->pc = NULL;
    143:   }

    145:   /* Now create pARMS preconditioner object based on A */
    146:   parms_PCCreate(&parms->pc,parms->A);

    148:   /* Transfer options from PC to pARMS */
    149:   switch (parms->global) {
    150:   case 0: parms_PCSetType(parms->pc, PCRAS); break;
    151:   case 1: parms_PCSetType(parms->pc, PCSCHUR); break;
    152:   case 2: parms_PCSetType(parms->pc, PCBJ); break;
    153:   }
    154:   switch (parms->local) {
    155:   case 0: parms_PCSetILUType(parms->pc, PCILU0); break;
    156:   case 1: parms_PCSetILUType(parms->pc, PCILUK); break;
    157:   case 2: parms_PCSetILUType(parms->pc, PCILUT); break;
    158:   case 3: parms_PCSetILUType(parms->pc, PCARMS); break;
    159:   }
    160:   parms_PCSetInnerEps(parms->pc, parms->solvetol);
    161:   parms_PCSetNlevels(parms->pc, parms->levels);
    162:   parms_PCSetPermType(parms->pc, parms->nonsymperm ? 1 : 0);
    163:   parms_PCSetBsize(parms->pc, parms->blocksize);
    164:   parms_PCSetTolInd(parms->pc, parms->indtol);
    165:   parms_PCSetInnerKSize(parms->pc, parms->maxdim);
    166:   parms_PCSetInnerMaxits(parms->pc, parms->maxits);
    167:   for (i=0; i<8; i++) meth[i] = parms->meth[i] ? 1 : 0;
    168:   parms_PCSetPermScalOptions(parms->pc, &meth[0], 1);
    169:   parms_PCSetPermScalOptions(parms->pc, &meth[4], 0);
    170:   parms_PCSetFill(parms->pc, parms->lfil);
    171:   parms_PCSetTol(parms->pc, parms->droptol);

    173:   parms_PCSetup(parms->pc);

    175:   /* Allocate two auxiliary vector of length lsize */
    176:   if (parms->lvec0) { PetscFree(parms->lvec0); }
    177:   PetscMalloc1(lsize, &parms->lvec0);
    178:   if (parms->lvec1) { PetscFree(parms->lvec1); }
    179:   PetscMalloc1(lsize, &parms->lvec1);
    180:   return(0);
    181: }

    183: static PetscErrorCode PCView_PARMS(PC pc,PetscViewer viewer)
    184: {
    186:   PetscBool      iascii;
    187:   PC_PARMS       *parms = (PC_PARMS*)pc->data;
    188:   char           *str;
    189:   double         fill_fact;

    192:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
    193:   if (iascii) {
    194:     parms_PCGetName(parms->pc,&str);
    195:     PetscViewerASCIIPrintf(viewer,"  global preconditioner: %s\n",str);
    196:     parms_PCILUGetName(parms->pc,&str);
    197:     PetscViewerASCIIPrintf(viewer,"  local preconditioner: %s\n",str);
    198:     parms_PCGetRatio(parms->pc,&fill_fact);
    199:     PetscViewerASCIIPrintf(viewer,"  non-zero elements/original non-zero entries: %-4.2f\n",fill_fact);
    200:     PetscViewerASCIIPrintf(viewer,"  Tolerance for local solve: %g\n",parms->solvetol);
    201:     PetscViewerASCIIPrintf(viewer,"  Number of levels: %d\n",parms->levels);
    202:     if (parms->nonsymperm) {
    203:       PetscViewerASCIIPrintf(viewer,"  Using nonsymmetric permutation\n");
    204:     }
    205:     PetscViewerASCIIPrintf(viewer,"  Block size: %d\n",parms->blocksize);
    206:     PetscViewerASCIIPrintf(viewer,"  Tolerance for independent sets: %g\n",parms->indtol);
    207:     PetscViewerASCIIPrintf(viewer,"  Inner Krylov dimension: %d\n",parms->maxdim);
    208:     PetscViewerASCIIPrintf(viewer,"  Maximum number of inner iterations: %d\n",parms->maxits);
    209:     if (parms->meth[0]) {
    210:       PetscViewerASCIIPrintf(viewer,"  Using nonsymmetric permutation for interlevel blocks\n");
    211:     }
    212:     if (parms->meth[1]) {
    213:       PetscViewerASCIIPrintf(viewer,"  Using column permutation for interlevel blocks\n");
    214:     }
    215:     if (parms->meth[2]) {
    216:       PetscViewerASCIIPrintf(viewer,"  Using row scaling for interlevel blocks\n");
    217:     }
    218:     if (parms->meth[3]) {
    219:       PetscViewerASCIIPrintf(viewer,"  Using column scaling for interlevel blocks\n");
    220:     }
    221:     if (parms->meth[4]) {
    222:       PetscViewerASCIIPrintf(viewer,"  Using nonsymmetric permutation for last level blocks\n");
    223:     }
    224:     if (parms->meth[5]) {
    225:       PetscViewerASCIIPrintf(viewer,"  Using column permutation for last level blocks\n");
    226:     }
    227:     if (parms->meth[6]) {
    228:       PetscViewerASCIIPrintf(viewer,"  Using row scaling for last level blocks\n");
    229:     }
    230:     if (parms->meth[7]) {
    231:       PetscViewerASCIIPrintf(viewer,"  Using column scaling for last level blocks\n");
    232:     }
    233:     PetscViewerASCIIPrintf(viewer,"  amount of fill-in for ilut, iluk and arms: %d\n",parms->lfil[0]);
    234:     PetscViewerASCIIPrintf(viewer,"  amount of fill-in for schur: %d\n",parms->lfil[4]);
    235:     PetscViewerASCIIPrintf(viewer,"  amount of fill-in for ILUT L and U: %d\n",parms->lfil[5]);
    236:     PetscViewerASCIIPrintf(viewer,"  drop tolerance for L, U, L^{-1}F and EU^{-1}: %g\n",parms->droptol[0]);
    237:     PetscViewerASCIIPrintf(viewer,"  drop tolerance for schur complement at each level: %g\n",parms->droptol[4]);
    238:     PetscViewerASCIIPrintf(viewer,"  drop tolerance for ILUT in last level schur complement: %g\n",parms->droptol[5]);
    239:   }
    240:   return(0);
    241: }

    243: static PetscErrorCode PCDestroy_PARMS(PC pc)
    244: {
    245:   PC_PARMS       *parms = (PC_PARMS*)pc->data;

    249:   if (parms->map) parms_MapFree(&parms->map);
    250:   if (parms->A) parms_MatFree(&parms->A);
    251:   if (parms->pc) parms_PCFree(&parms->pc);
    252:   if (parms->lvec0) {
    253:     PetscFree(parms->lvec0);
    254:   }
    255:   if (parms->lvec1) {
    256:     PetscFree(parms->lvec1);
    257:   }
    258:   PetscFree(pc->data);

    260:   PetscObjectChangeTypeName((PetscObject)pc,0);
    261:   PetscObjectComposeFunction((PetscObject)pc,"PCPARMSSetGlobal_C",NULL);
    262:   PetscObjectComposeFunction((PetscObject)pc,"PCPARMSSetLocal_C",NULL);
    263:   PetscObjectComposeFunction((PetscObject)pc,"PCPARMSSetSolveTolerances_C",NULL);
    264:   PetscObjectComposeFunction((PetscObject)pc,"PCPARMSSetSolveRestart_C",NULL);
    265:   PetscObjectComposeFunction((PetscObject)pc,"PCPARMSSetNonsymPerm_C",NULL);
    266:   PetscObjectComposeFunction((PetscObject)pc,"PCPARMSSetFill_C",NULL);
    267:   return(0);
    268: }

    270: static PetscErrorCode PCSetFromOptions_PARMS(PetscOptionItems *PetscOptionsObject,PC pc)
    271: {
    272:   PC_PARMS          *parms = (PC_PARMS*)pc->data;
    273:   PetscBool         flag;
    274:   PCPARMSGlobalType global;
    275:   PCPARMSLocalType  local;
    276:   PetscErrorCode    ierr;

    279:   PetscOptionsHead(PetscOptionsObject,"PARMS Options");
    280:   PetscOptionsEnum("-pc_parms_global","Global preconditioner","PCPARMSSetGlobal",PCPARMSGlobalTypes,(PetscEnum)parms->global,(PetscEnum*)&global,&flag);
    281:   if (flag) {PCPARMSSetGlobal(pc,global);}
    282:   PetscOptionsEnum("-pc_parms_local","Local preconditioner","PCPARMSSetLocal",PCPARMSLocalTypes,(PetscEnum)parms->local,(PetscEnum*)&local,&flag);
    283:   if (flag) {PCPARMSSetLocal(pc,local);}
    284:   PetscOptionsReal("-pc_parms_solve_tol","Tolerance for local solve","PCPARMSSetSolveTolerances",parms->solvetol,&parms->solvetol,NULL);
    285:   PetscOptionsInt("-pc_parms_levels","Number of levels","None",parms->levels,&parms->levels,NULL);
    286:   PetscOptionsBool("-pc_parms_nonsymmetric_perm","Use nonsymmetric permutation","PCPARMSSetNonsymPerm",parms->nonsymperm,&parms->nonsymperm,NULL);
    287:   PetscOptionsInt("-pc_parms_blocksize","Block size","None",parms->blocksize,&parms->blocksize,NULL);
    288:   PetscOptionsReal("-pc_parms_ind_tol","Tolerance for independent sets","None",parms->indtol,&parms->indtol,NULL);
    289:   PetscOptionsInt("-pc_parms_max_dim","Inner Krylov dimension","PCPARMSSetSolveRestart",parms->maxdim,&parms->maxdim,NULL);
    290:   PetscOptionsInt("-pc_parms_max_it","Maximum number of inner iterations","PCPARMSSetSolveTolerances",parms->maxits,&parms->maxits,NULL);
    291:   PetscOptionsBool("-pc_parms_inter_nonsymmetric_perm","nonsymmetric permutation for interlevel blocks","None",parms->meth[0],&parms->meth[0],NULL);
    292:   PetscOptionsBool("-pc_parms_inter_column_perm","column permutation for interlevel blocks","None",parms->meth[1],&parms->meth[1],NULL);
    293:   PetscOptionsBool("-pc_parms_inter_row_scaling","row scaling for interlevel blocks","None",parms->meth[2],&parms->meth[2],NULL);
    294:   PetscOptionsBool("-pc_parms_inter_column_scaling","column scaling for interlevel blocks","None",parms->meth[3],&parms->meth[3],NULL);
    295:   PetscOptionsBool("-pc_parms_last_nonsymmetric_perm","nonsymmetric permutation for last level blocks","None",parms->meth[4],&parms->meth[4],NULL);
    296:   PetscOptionsBool("-pc_parms_last_column_perm","column permutation for last level blocks","None",parms->meth[5],&parms->meth[5],NULL);
    297:   PetscOptionsBool("-pc_parms_last_row_scaling","row scaling for last level blocks","None",parms->meth[6],&parms->meth[6],NULL);
    298:   PetscOptionsBool("-pc_parms_last_column_scaling","column scaling for last level blocks","None",parms->meth[7],&parms->meth[7],NULL);
    299:   PetscOptionsInt("-pc_parms_lfil_ilu_arms","amount of fill-in for ilut, iluk and arms","PCPARMSSetFill",parms->lfil[0],&parms->lfil[0],&flag);
    300:   if (flag) parms->lfil[1] = parms->lfil[2] = parms->lfil[3] = parms->lfil[0];
    301:   PetscOptionsInt("-pc_parms_lfil_schur","amount of fill-in for schur","PCPARMSSetFill",parms->lfil[4],&parms->lfil[4],NULL);
    302:   PetscOptionsInt("-pc_parms_lfil_ilut_L_U","amount of fill-in for ILUT L and U","PCPARMSSetFill",parms->lfil[5],&parms->lfil[5],&flag);
    303:   if (flag) parms->lfil[6] = parms->lfil[5];
    304:   PetscOptionsReal("-pc_parms_droptol_factors","drop tolerance for L, U, L^{-1}F and EU^{-1}","None",parms->droptol[0],&parms->droptol[0],NULL);
    305:   PetscOptionsReal("-pc_parms_droptol_schur_compl","drop tolerance for schur complement at each level","None",parms->droptol[4],&parms->droptol[4],&flag);
    306:   if (flag) parms->droptol[1] = parms->droptol[2] = parms->droptol[3] = parms->droptol[0];
    307:   PetscOptionsReal("-pc_parms_droptol_last_schur","drop tolerance for ILUT in last level schur complement","None",parms->droptol[5],&parms->droptol[5],&flag);
    308:   if (flag) parms->droptol[6] = parms->droptol[5];
    309:   PetscOptionsTail();
    310:   return(0);
    311: }

    313: static PetscErrorCode PCApply_PARMS(PC pc,Vec b,Vec x)
    314: {
    315:   PetscErrorCode    ierr;
    316:   PC_PARMS          *parms = (PC_PARMS*)pc->data;
    317:   const PetscScalar *b1;
    318:   PetscScalar       *x1;

    321:   VecGetArrayRead(b,&b1);
    322:   VecGetArray(x,&x1);
    323:   parms_VecPermAux((PetscScalar*)b1,parms->lvec0,parms->map);
    324:   parms_PCApply(parms->pc,parms->lvec0,parms->lvec1);
    325:   parms_VecInvPermAux(parms->lvec1,x1,parms->map);
    326:   VecRestoreArrayRead(b,&b1);
    327:   VecRestoreArray(x,&x1);
    328:   return(0);
    329: }

    331: static PetscErrorCode PCPARMSSetGlobal_PARMS(PC pc,PCPARMSGlobalType type)
    332: {
    333:   PC_PARMS *parms = (PC_PARMS*)pc->data;

    336:   if (type != parms->global) {
    337:     parms->global   = type;
    338:     pc->setupcalled = 0;
    339:   }
    340:   return(0);
    341: }

    343: /*@
    344:    PCPARMSSetGlobal - Sets the global preconditioner to be used in PARMS.

    346:    Collective on PC

    348:    Input Parameters:
    349: +  pc - the preconditioner context
    350: -  type - the global preconditioner type, one of
    351: .vb
    352:      PC_PARMS_GLOBAL_RAS   - Restricted additive Schwarz
    353:      PC_PARMS_GLOBAL_SCHUR - Schur complement
    354:      PC_PARMS_GLOBAL_BJ    - Block Jacobi
    355: .ve

    357:    Options Database Keys:
    358:    -pc_parms_global [ras,schur,bj] - Sets global preconditioner

    360:    Level: intermediate

    362:    Notes:
    363:    See the pARMS function parms_PCSetType for more information.

    365: .seealso: PCPARMS, PCPARMSSetLocal()
    366: @*/
    367: PetscErrorCode PCPARMSSetGlobal(PC pc,PCPARMSGlobalType type)
    368: {

    374:   PetscTryMethod(pc,"PCPARMSSetGlobal_C",(PC,PCPARMSGlobalType),(pc,type));
    375:   return(0);
    376: }

    378: static PetscErrorCode PCPARMSSetLocal_PARMS(PC pc,PCPARMSLocalType type)
    379: {
    380:   PC_PARMS *parms = (PC_PARMS*)pc->data;

    383:   if (type != parms->local) {
    384:     parms->local    = type;
    385:     pc->setupcalled = 0;
    386:   }
    387:   return(0);
    388: }

    390: /*@
    391:    PCPARMSSetLocal - Sets the local preconditioner to be used in PARMS.

    393:    Collective on PC

    395:    Input Parameters:
    396: +  pc - the preconditioner context
    397: -  type - the local preconditioner type, one of
    398: .vb
    399:      PC_PARMS_LOCAL_ILU0   - ILU0 preconditioner
    400:      PC_PARMS_LOCAL_ILUK   - ILU(k) preconditioner
    401:      PC_PARMS_LOCAL_ILUT   - ILUT preconditioner
    402:      PC_PARMS_LOCAL_ARMS   - ARMS preconditioner
    403: .ve

    405:    Options Database Keys:
    406:    -pc_parms_local [ilu0,iluk,ilut,arms] - Sets local preconditioner

    408:    Level: intermediate

    410:    Notes:
    411:    For the ARMS preconditioner, one can use either the symmetric ARMS or the non-symmetric
    412:    variant (ARMS-ddPQ) by setting the permutation type with PCPARMSSetNonsymPerm().

    414:    See the pARMS function parms_PCILUSetType for more information.

    416: .seealso: PCPARMS, PCPARMSSetGlobal(), PCPARMSSetNonsymPerm()

    418: @*/
    419: PetscErrorCode PCPARMSSetLocal(PC pc,PCPARMSLocalType type)
    420: {

    426:   PetscTryMethod(pc,"PCPARMSSetLocal_C",(PC,PCPARMSLocalType),(pc,type));
    427:   return(0);
    428: }

    430: static PetscErrorCode PCPARMSSetSolveTolerances_PARMS(PC pc,PetscReal tol,PetscInt maxits)
    431: {
    432:   PC_PARMS *parms = (PC_PARMS*)pc->data;

    435:   if (tol != parms->solvetol) {
    436:     parms->solvetol = tol;
    437:     pc->setupcalled = 0;
    438:   }
    439:   if (maxits != parms->maxits) {
    440:     parms->maxits   = maxits;
    441:     pc->setupcalled = 0;
    442:   }
    443:   return(0);
    444: }

    446: /*@
    447:    PCPARMSSetSolveTolerances - Sets the convergence tolerance and the maximum iterations for the
    448:    inner GMRES solver, when the Schur global preconditioner is used.

    450:    Collective on PC

    452:    Input Parameters:
    453: +  pc - the preconditioner context
    454: .  tol - the convergence tolerance
    455: -  maxits - the maximum number of iterations to use

    457:    Options Database Keys:
    458: +  -pc_parms_solve_tol - set the tolerance for local solve
    459: -  -pc_parms_max_it - set the maximum number of inner iterations

    461:    Level: intermediate

    463:    Notes:
    464:    See the pARMS functions parms_PCSetInnerEps and parms_PCSetInnerMaxits for more information.

    466: .seealso: PCPARMS, PCPARMSSetSolveRestart()
    467: @*/
    468: PetscErrorCode PCPARMSSetSolveTolerances(PC pc,PetscReal tol,PetscInt maxits)
    469: {

    474:   PetscTryMethod(pc,"PCPARMSSetSolveTolerances_C",(PC,PetscReal,PetscInt),(pc,tol,maxits));
    475:   return(0);
    476: }

    478: static PetscErrorCode PCPARMSSetSolveRestart_PARMS(PC pc,PetscInt restart)
    479: {
    480:   PC_PARMS *parms = (PC_PARMS*)pc->data;

    483:   if (restart != parms->maxdim) {
    484:     parms->maxdim   = restart;
    485:     pc->setupcalled = 0;
    486:   }
    487:   return(0);
    488: }

    490: /*@
    491:    PCPARMSSetSolveRestart - Sets the number of iterations at which the
    492:    inner GMRES solver restarts.

    494:    Collective on PC

    496:    Input Parameters:
    497: +  pc - the preconditioner context
    498: -  restart - maximum dimension of the Krylov subspace

    500:    Options Database Keys:
    501: .  -pc_parms_max_dim - sets the inner Krylov dimension

    503:    Level: intermediate

    505:    Notes:
    506:    See the pARMS function parms_PCSetInnerKSize for more information.

    508: .seealso: PCPARMS, PCPARMSSetSolveTolerances()
    509: @*/
    510: PetscErrorCode PCPARMSSetSolveRestart(PC pc,PetscInt restart)
    511: {

    516:   PetscTryMethod(pc,"PCPARMSSetSolveRestart_C",(PC,PetscInt),(pc,restart));
    517:   return(0);
    518: }

    520: static PetscErrorCode PCPARMSSetNonsymPerm_PARMS(PC pc,PetscBool nonsym)
    521: {
    522:   PC_PARMS *parms = (PC_PARMS*)pc->data;

    525:   if ((nonsym && !parms->nonsymperm) || (!nonsym && parms->nonsymperm)) {
    526:     parms->nonsymperm = nonsym;
    527:     pc->setupcalled   = 0;
    528:   }
    529:   return(0);
    530: }

    532: /*@
    533:    PCPARMSSetNonsymPerm - Sets the type of permutation for the ARMS preconditioner: the standard
    534:    symmetric ARMS or the non-symmetric ARMS (ARMS-ddPQ).

    536:    Collective on PC

    538:    Input Parameters:
    539: +  pc - the preconditioner context
    540: -  nonsym - PETSC_TRUE indicates the non-symmetric ARMS is used;
    541:             PETSC_FALSE indicates the symmetric ARMS is used

    543:    Options Database Keys:
    544: .  -pc_parms_nonsymmetric_perm - sets the use of nonsymmetric permutation

    546:    Level: intermediate

    548:    Notes:
    549:    See the pARMS function parms_PCSetPermType for more information.

    551: .seealso: PCPARMS
    552: @*/
    553: PetscErrorCode PCPARMSSetNonsymPerm(PC pc,PetscBool nonsym)
    554: {

    559:   PetscTryMethod(pc,"PCPARMSSetNonsymPerm_C",(PC,PetscBool),(pc,nonsym));
    560:   return(0);
    561: }

    563: static PetscErrorCode PCPARMSSetFill_PARMS(PC pc,PetscInt lfil0,PetscInt lfil1,PetscInt lfil2)
    564: {
    565:   PC_PARMS *parms = (PC_PARMS*)pc->data;

    568:   if (lfil0 != parms->lfil[0] || lfil0 != parms->lfil[1] || lfil0 != parms->lfil[2] || lfil0 != parms->lfil[3]) {
    569:     parms->lfil[1]  = parms->lfil[2] = parms->lfil[3] = parms->lfil[0] = lfil0;
    570:     pc->setupcalled = 0;
    571:   }
    572:   if (lfil1 != parms->lfil[4]) {
    573:     parms->lfil[4]  = lfil1;
    574:     pc->setupcalled = 0;
    575:   }
    576:   if (lfil2 != parms->lfil[5] || lfil2 != parms->lfil[6]) {
    577:     parms->lfil[5]  = parms->lfil[6] = lfil2;
    578:     pc->setupcalled = 0;
    579:   }
    580:   return(0);
    581: }

    583: /*@
    584:    PCPARMSSetFill - Sets the fill-in parameters for ILUT, ILUK and ARMS preconditioners.
    585:    Consider the original matrix A = [B F; E C] and the approximate version
    586:    M = [LB 0; E/UB I]*[UB LB\F; 0 S].

    588:    Collective on PC

    590:    Input Parameters:
    591: +  pc - the preconditioner context
    592: .  fil0 - the level of fill-in kept in LB, UB, E/UB and LB\F
    593: .  fil1 - the level of fill-in kept in S
    594: -  fil2 - the level of fill-in kept in the L and U parts of the LU factorization of S

    596:    Options Database Keys:
    597: +  -pc_parms_lfil_ilu_arms - set the amount of fill-in for ilut, iluk and arms
    598: .  -pc_parms_lfil_schur - set the amount of fill-in for schur
    599: -  -pc_parms_lfil_ilut_L_U - set the amount of fill-in for ILUT L and U

    601:    Level: intermediate

    603:    Notes:
    604:    See the pARMS function parms_PCSetFill for more information.

    606: .seealso: PCPARMS
    607: @*/
    608: PetscErrorCode PCPARMSSetFill(PC pc,PetscInt lfil0,PetscInt lfil1,PetscInt lfil2)
    609: {

    614:   PetscTryMethod(pc,"PCPARMSSetFill_C",(PC,PetscInt,PetscInt,PetscInt),(pc,lfil0,lfil1,lfil2));
    615:   return(0);
    616: }

    618: /*MC
    619:    PCPARMS - Allows the use of the parallel Algebraic Recursive Multilevel Solvers
    620:       available in the package pARMS

    622:    Options Database Keys:
    623: +  -pc_parms_global - one of ras, schur, bj
    624: .  -pc_parms_local - one of ilu0, iluk, ilut, arms
    625: .  -pc_parms_solve_tol - set the tolerance for local solve
    626: .  -pc_parms_levels - set the number of levels
    627: .  -pc_parms_nonsymmetric_perm - set the use of nonsymmetric permutation
    628: .  -pc_parms_blocksize - set the block size
    629: .  -pc_parms_ind_tol - set the tolerance for independent sets
    630: .  -pc_parms_max_dim - set the inner krylov dimension
    631: .  -pc_parms_max_it - set the maximum number of inner iterations
    632: .  -pc_parms_inter_nonsymmetric_perm - set the use of nonsymmetric permutation for interlevel blocks
    633: .  -pc_parms_inter_column_perm - set the use of column permutation for interlevel blocks
    634: .  -pc_parms_inter_row_scaling - set the use of row scaling for interlevel blocks
    635: .  -pc_parms_inter_column_scaling - set the use of column scaling for interlevel blocks
    636: .  -pc_parms_last_nonsymmetric_perm - set the use of nonsymmetric permutation for last level blocks
    637: .  -pc_parms_last_column_perm - set the use of column permutation for last level blocks
    638: .  -pc_parms_last_row_scaling - set the use of row scaling for last level blocks
    639: .  -pc_parms_last_column_scaling - set the use of column scaling for last level blocks
    640: .  -pc_parms_lfil_ilu_arms - set the amount of fill-in for ilut, iluk and arms
    641: .  -pc_parms_lfil_schur - set the amount of fill-in for schur
    642: .  -pc_parms_lfil_ilut_L_U - set the amount of fill-in for ILUT L and U
    643: .  -pc_parms_droptol_factors - set the drop tolerance for L, U, L^{-1}F and EU^{-1}
    644: .  -pc_parms_droptol_schur_compl - set the drop tolerance for schur complement at each level
    645: -  -pc_parms_droptol_last_schur - set the drop tolerance for ILUT in last level schur complement

    647:    IMPORTANT:
    648:    Unless configured appropriately, this preconditioner performs an inexact solve
    649:    as part of the preconditioner application. Therefore, it must be used in combination
    650:    with flexible variants of iterative solvers, such as KSPFGMRES or KSPGCR.

    652:    Level: intermediate

    654: .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC
    655: M*/

    657: PETSC_EXTERN PetscErrorCode PCCreate_PARMS(PC pc)
    658: {
    659:   PC_PARMS       *parms;

    663:   PetscNewLog(pc,&parms);

    665:   parms->map        = 0;
    666:   parms->A          = 0;
    667:   parms->pc         = 0;
    668:   parms->global     = PC_PARMS_GLOBAL_RAS;
    669:   parms->local      = PC_PARMS_LOCAL_ARMS;
    670:   parms->levels     = 10;
    671:   parms->nonsymperm = PETSC_TRUE;
    672:   parms->blocksize  = 250;
    673:   parms->maxdim     = 0;
    674:   parms->maxits     = 0;
    675:   parms->meth[0]    = PETSC_FALSE;
    676:   parms->meth[1]    = PETSC_FALSE;
    677:   parms->meth[2]    = PETSC_FALSE;
    678:   parms->meth[3]    = PETSC_FALSE;
    679:   parms->meth[4]    = PETSC_FALSE;
    680:   parms->meth[5]    = PETSC_FALSE;
    681:   parms->meth[6]    = PETSC_FALSE;
    682:   parms->meth[7]    = PETSC_FALSE;
    683:   parms->solvetol   = 0.01;
    684:   parms->indtol     = 0.4;
    685:   parms->lfil[0]    = parms->lfil[1] = parms->lfil[2] = parms->lfil[3] = 20;
    686:   parms->lfil[4]    = parms->lfil[5] = parms->lfil[6] = 20;
    687:   parms->droptol[0] = parms->droptol[1] = parms->droptol[2] = parms->droptol[3] = 0.00001;
    688:   parms->droptol[4] = 0.001;
    689:   parms->droptol[5] = parms->droptol[6] = 0.001;

    691:   pc->data                = parms;
    692:   pc->ops->destroy        = PCDestroy_PARMS;
    693:   pc->ops->setfromoptions = PCSetFromOptions_PARMS;
    694:   pc->ops->setup          = PCSetUp_PARMS;
    695:   pc->ops->apply          = PCApply_PARMS;
    696:   pc->ops->view           = PCView_PARMS;

    698:   PetscObjectComposeFunction((PetscObject)pc,"PCPARMSSetGlobal_C",PCPARMSSetGlobal_PARMS);
    699:   PetscObjectComposeFunction((PetscObject)pc,"PCPARMSSetLocal_C",PCPARMSSetLocal_PARMS);
    700:   PetscObjectComposeFunction((PetscObject)pc,"PCPARMSSetSolveTolerances_C",PCPARMSSetSolveTolerances_PARMS);
    701:   PetscObjectComposeFunction((PetscObject)pc,"PCPARMSSetSolveRestart_C",PCPARMSSetSolveRestart_PARMS);
    702:   PetscObjectComposeFunction((PetscObject)pc,"PCPARMSSetNonsymPerm_C",PCPARMSSetNonsymPerm_PARMS);
    703:   PetscObjectComposeFunction((PetscObject)pc,"PCPARMSSetFill_C",PCPARMSSetFill_PARMS);
    704:   return(0);
    705: }