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

Actual source code: lmvmpc.c

      1: /*
      2:    This provides a thin wrapper around LMVM matrices in order to use their MatLMVMSolve
      3:    methods as preconditioner applications in KSP solves.
      4: */

      6: #include <petsc/private/pcimpl.h>
      7: #include <petsc/private/matimpl.h>

      9: typedef struct {
     10:   Vec  xwork, ywork;
     11:   IS   inactive;
     12:   Mat  B;
     13:   PetscBool allocated;
     14: } PC_LMVM;

     16: /*@
     17:    PCLMVMSetMatLMVM - Replaces the LMVM matrix inside the preconditioner with
     18:    the one provided by the user.

     20:    Input Parameters:
     21: +  pc - An LMVM preconditioner
     22: -  B  - An LMVM-type matrix (MATLDFP, MATLBFGS, MATLSR1, MATLBRDN, MATLMBRDN, MATLSBRDN)

     24:    Level: intermediate
     25: @*/
     26: PetscErrorCode PCLMVMSetMatLMVM(PC pc, Mat B)
     27: {
     28:   PC_LMVM          *ctx = (PC_LMVM*)pc->data;
     29:   PetscErrorCode   ierr;
     30:   PetscBool        same;

     35:   PetscObjectTypeCompare((PetscObject)pc, PCLMVM, &same);
     36:   if (!same) SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "PC must be a PCLMVM type.");
     37:   PetscObjectBaseTypeCompare((PetscObject)B, MATLMVM, &same);
     38:   if (!same) SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Matrix must be an LMVM-type.");
     39:   MatDestroy(&ctx->B);
     40:   PetscObjectReference((PetscObject)B);
     41:   ctx->B = B;
     42:   return(0);
     43: }

     45: /*@
     46:    PCLMVMGetMatLMVM - Returns a pointer to the underlying LMVM matrix.

     48:    Input Parameters:
     49: .  pc - An LMVM preconditioner

     51:    Output Parameters:
     52: .  B - LMVM matrix inside the preconditioner

     54:    Level: intermediate
     55: @*/
     56: PetscErrorCode PCLMVMGetMatLMVM(PC pc, Mat *B)
     57: {
     58:   PC_LMVM          *ctx = (PC_LMVM*)pc->data;
     59:   PetscErrorCode   ierr;
     60:   PetscBool        same;

     64:   PetscObjectTypeCompare((PetscObject)pc, PCLMVM, &same);
     65:   if (!same) SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "PC must be a PCLMVM type.");
     66:   *B = ctx->B;
     67:   return(0);
     68: }

     70: /*@
     71:    PCLMVMSetIS - Sets the index sets that reduce the PC application.

     73:    Input Parameters:
     74: +  pc - An LMVM preconditioner
     75: -  inactive - Index set defining the variables removed from the problem

     77:    Level: intermediate

     79: .seealso:  MatLMVMUpdate()
     80: @*/
     81: PetscErrorCode PCLMVMSetIS(PC pc, IS inactive)
     82: {
     83:   PC_LMVM          *ctx = (PC_LMVM*)pc->data;
     84:   PetscErrorCode   ierr;
     85:   PetscBool        same;

     90:   PetscObjectTypeCompare((PetscObject)pc, PCLMVM, &same);
     91:   if (!same) SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "PC must be a PCLMVM type.");
     92:   PCLMVMClearIS(pc);
     93:   PetscObjectReference((PetscObject)inactive);
     94:   ctx->inactive = inactive;
     95:   return(0);
     96: }

     98: /*@
     99:    PCLMVMClearIS - Removes the inactive variable index set.

    101:    Input Parameters:
    102: .  pc - An LMVM preconditioner

    104:    Level: intermediate

    106: .seealso:  MatLMVMUpdate()
    107: @*/
    108: PetscErrorCode PCLMVMClearIS(PC pc)
    109: {
    110:   PC_LMVM          *ctx = (PC_LMVM*)pc->data;
    111:   PetscErrorCode   ierr;
    112:   PetscBool        same;

    116:   PetscObjectTypeCompare((PetscObject)pc, PCLMVM, &same);
    117:   if (!same) SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "PC must be a PCLMVM type.");
    118:   if (ctx->inactive) {
    119:     ISDestroy(&ctx->inactive);
    120:   }
    121:   return(0);
    122: }

    124: static PetscErrorCode PCApply_LMVM(PC pc,Vec x,Vec y)
    125: {
    126:   PC_LMVM          *ctx = (PC_LMVM*)pc->data;
    127:   PetscErrorCode   ierr;
    128:   Vec              xsub, ysub;

    131:   if (ctx->inactive) {
    132:     VecZeroEntries(ctx->xwork);
    133:     VecGetSubVector(ctx->xwork, ctx->inactive, &xsub);
    134:     VecCopy(x, xsub);
    135:     VecRestoreSubVector(ctx->xwork, ctx->inactive, &xsub);
    136:   } else {
    137:     VecCopy(x, ctx->xwork);
    138:   }
    139:   MatSolve(ctx->B, ctx->xwork, ctx->ywork);
    140:   if (ctx->inactive) {
    141:     VecGetSubVector(ctx->ywork, ctx->inactive, &ysub);
    142:     VecCopy(ysub, y);
    143:     VecRestoreSubVector(ctx->ywork, ctx->inactive, &ysub);
    144:   } else {
    145:     VecCopy(ctx->ywork, y);
    146:   }
    147:   return(0);
    148: }

    150: static PetscErrorCode PCReset_LMVM(PC pc)
    151: {
    152:   PC_LMVM        *ctx = (PC_LMVM*)pc->data;

    156:   if (ctx->xwork) {
    157:     VecDestroy(&ctx->xwork);
    158:   }
    159:   if (ctx->ywork) {
    160:     VecDestroy(&ctx->ywork);
    161:   }
    162:   return(0);
    163: }

    165: static PetscErrorCode PCSetUp_LMVM(PC pc)
    166: {
    167:   PC_LMVM        *ctx = (PC_LMVM*)pc->data;
    169:   PetscInt       n, N;
    170:   PetscBool      allocated;

    173:   MatLMVMIsAllocated(ctx->B, &allocated);
    174:   if (!allocated) {
    175:     MatCreateVecs(pc->mat, &ctx->xwork, &ctx->ywork);
    176:     VecGetLocalSize(ctx->xwork, &n);
    177:     VecGetSize(ctx->xwork, &N);
    178:     MatSetSizes(ctx->B, n, n, N, N);
    179:     MatLMVMAllocate(ctx->B, ctx->xwork, ctx->ywork);
    180:   } else {
    181:     MatCreateVecs(ctx->B, &ctx->xwork, &ctx->ywork);
    182:   }
    183:   return(0);
    184: }

    186: static PetscErrorCode PCView_LMVM(PC pc,PetscViewer viewer)
    187: {
    188:   PC_LMVM        *ctx = (PC_LMVM*)pc->data;
    190:   PetscBool      iascii;

    193:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
    194:   if (iascii && ctx->B->assembled) {
    195:     PetscViewerPushFormat(viewer, PETSC_VIEWER_ASCII_INFO);
    196:     MatView(ctx->B, viewer);
    197:     PetscViewerPopFormat(viewer);
    198:   }
    199:   return(0);
    200: }

    202: static PetscErrorCode PCSetFromOptions_LMVM(PetscOptionItems* PetscOptionsObject, PC pc)
    203: {
    204:   PC_LMVM        *ctx = (PC_LMVM*)pc->data;

    208:   MatSetFromOptions(ctx->B);
    209:   return(0);
    210: }

    212: static PetscErrorCode PCDestroy_LMVM(PC pc)
    213: {
    214:   PC_LMVM        *ctx = (PC_LMVM*)pc->data;

    218:   if (ctx->inactive) {
    219:     ISDestroy(&ctx->inactive);
    220:   }
    221:   if (pc->setupcalled) {
    222:     VecDestroy(&ctx->xwork);
    223:     VecDestroy(&ctx->ywork);
    224:   }
    225:   MatDestroy(&ctx->B);
    226:   PetscFree(pc->data);
    227:   return(0);
    228: }

    230: /*MC
    231:    PCLMVM - Creates a preconditioner around an LMVM matrix. Options for the
    232:             underlying LMVM matrix can be access with the "-pc_lmvm_" prefix.

    234:    Level: intermediate

    236: .seealso:  PCCreate(), PCSetType(), PCType (for list of available types),
    237:            PC, MATLMVM, PCLMVMUpdate(), PCLMVMSetMatLMVM(), PCLMVMGetMatLMVM()
    238: M*/
    239: PETSC_EXTERN PetscErrorCode PCCreate_LMVM(PC pc)
    240: {
    242:   PC_LMVM        *ctx;

    245:   PetscNewLog(pc,&ctx);
    246:   pc->data = (void*)ctx;

    248:   pc->ops->reset           = PCReset_LMVM;
    249:   pc->ops->setup           = PCSetUp_LMVM;
    250:   pc->ops->destroy         = PCDestroy_LMVM;
    251:   pc->ops->view            = PCView_LMVM;
    252:   pc->ops->apply           = PCApply_LMVM;
    253:   pc->ops->setfromoptions  = PCSetFromOptions_LMVM;
    254:   pc->ops->applysymmetricleft  = NULL;
    255:   pc->ops->applysymmetricright = NULL;
    256:   pc->ops->applytranspose  = NULL;
    257:   pc->ops->applyrichardson = NULL;
    258:   pc->ops->presolve        = NULL;
    259:   pc->ops->postsolve       = NULL;

    261:   PCSetReusePreconditioner(pc, PETSC_TRUE);

    263:   MatCreate(PetscObjectComm((PetscObject)pc), &ctx->B);
    264:   MatSetType(ctx->B, MATLMVMBFGS);
    265:   PetscObjectIncrementTabLevel((PetscObject)ctx->B, (PetscObject)pc, 1);
    266:   MatSetOptionsPrefix(ctx->B, "pc_lmvm_");
    267:   return(0);
    268: }