1*b9ac7092SAlp Dener /* 2*b9ac7092SAlp Dener This provides a thin wrapper around LMVM matrices in order to use their MatSolve 3*b9ac7092SAlp Dener methods as preconditioner applications in KSP solves. 4*b9ac7092SAlp Dener */ 5*b9ac7092SAlp Dener 6*b9ac7092SAlp Dener #include <petsc/private/pcimpl.h> /*I "petscpc.h" I*/ 7*b9ac7092SAlp Dener 8*b9ac7092SAlp Dener typedef struct { 9*b9ac7092SAlp Dener Vec xwork, ywork; 10*b9ac7092SAlp Dener IS inactive; 11*b9ac7092SAlp Dener Mat B; 12*b9ac7092SAlp Dener } PC_LMVM; 13*b9ac7092SAlp Dener 14*b9ac7092SAlp Dener /*@ 15*b9ac7092SAlp Dener PCLMVMSetMatLMVM - Replaces the LMVM matrix inside the preconditioner with 16*b9ac7092SAlp Dener the one provided by the user. 17*b9ac7092SAlp Dener 18*b9ac7092SAlp Dener Input Parameters: 19*b9ac7092SAlp Dener + pc - An LMVM preconditioner 20*b9ac7092SAlp Dener - B - An LMVM-type matrix (MATLDFP, MATLBFGS, MATLSR1, MATLBRDN, MATLMBRDN, MATLSBRDN) 21*b9ac7092SAlp Dener 22*b9ac7092SAlp Dener Level: intermediate 23*b9ac7092SAlp Dener @*/ 24*b9ac7092SAlp Dener PetscErrorCode PCLMVMSetMatLMVM(PC pc, Mat B) 25*b9ac7092SAlp Dener { 26*b9ac7092SAlp Dener PC_LMVM *ctx = (PC_LMVM*)pc->data; 27*b9ac7092SAlp Dener PetscErrorCode ierr; 28*b9ac7092SAlp Dener PetscBool same; 29*b9ac7092SAlp Dener 30*b9ac7092SAlp Dener PetscFunctionBegin; 31*b9ac7092SAlp Dener PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 32*b9ac7092SAlp Dener PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 33*b9ac7092SAlp Dener ierr = PetscObjectTypeCompare((PetscObject)pc, PCLMVM, &same);CHKERRQ(ierr); 34*b9ac7092SAlp Dener if (!same) SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "PC must be a PCLMVM type."); 35*b9ac7092SAlp Dener ierr = PetscObjectBaseTypeCompare((PetscObject)B, MATLMVM, &same);CHKERRQ(ierr); 36*b9ac7092SAlp Dener if (!same) SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Matrix must be an LMVM-type."); 37*b9ac7092SAlp Dener ierr = MatDestroy(&ctx->B);CHKERRQ(ierr); 38*b9ac7092SAlp Dener ierr = PetscObjectReference((PetscObject)B);CHKERRQ(ierr); 39*b9ac7092SAlp Dener ctx->B = B; 40*b9ac7092SAlp Dener PetscFunctionReturn(0); 41*b9ac7092SAlp Dener } 42*b9ac7092SAlp Dener 43*b9ac7092SAlp Dener /*@ 44*b9ac7092SAlp Dener PCLMVMGetMatLMVM - Returns a pointer to the underlying LMVM matrix. 45*b9ac7092SAlp Dener 46*b9ac7092SAlp Dener Input Parameters: 47*b9ac7092SAlp Dener . pc - An LMVM preconditioner 48*b9ac7092SAlp Dener 49*b9ac7092SAlp Dener Output Parameters: 50*b9ac7092SAlp Dener . B - LMVM matrix inside the preconditioner 51*b9ac7092SAlp Dener 52*b9ac7092SAlp Dener Level: intermediate 53*b9ac7092SAlp Dener @*/ 54*b9ac7092SAlp Dener PetscErrorCode PCLMVMGetMatLMVM(PC pc, Mat *B) 55*b9ac7092SAlp Dener { 56*b9ac7092SAlp Dener PC_LMVM *ctx = (PC_LMVM*)pc->data; 57*b9ac7092SAlp Dener PetscErrorCode ierr; 58*b9ac7092SAlp Dener PetscBool same; 59*b9ac7092SAlp Dener 60*b9ac7092SAlp Dener PetscFunctionBegin; 61*b9ac7092SAlp Dener PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 62*b9ac7092SAlp Dener ierr = PetscObjectTypeCompare((PetscObject)pc, PCLMVM, &same);CHKERRQ(ierr); 63*b9ac7092SAlp Dener if (!same) SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "PC must be a PCLMVM type."); 64*b9ac7092SAlp Dener *B = ctx->B; 65*b9ac7092SAlp Dener PetscFunctionReturn(0); 66*b9ac7092SAlp Dener } 67*b9ac7092SAlp Dener 68*b9ac7092SAlp Dener /*@ 69*b9ac7092SAlp Dener PCLMVMSetIS - Sets the index sets that reduce the PC application. 70*b9ac7092SAlp Dener 71*b9ac7092SAlp Dener Input Parameters: 72*b9ac7092SAlp Dener + pc - An LMVM preconditioner 73*b9ac7092SAlp Dener - inactive - Index set defining the variables removed from the problem 74*b9ac7092SAlp Dener 75*b9ac7092SAlp Dener Level: intermediate 76*b9ac7092SAlp Dener 77*b9ac7092SAlp Dener .seealso: MatLMVMUpdate() 78*b9ac7092SAlp Dener @*/ 79*b9ac7092SAlp Dener PetscErrorCode PCLMVMSetIS(PC pc, IS inactive) 80*b9ac7092SAlp Dener { 81*b9ac7092SAlp Dener PC_LMVM *ctx = (PC_LMVM*)pc->data; 82*b9ac7092SAlp Dener PetscErrorCode ierr; 83*b9ac7092SAlp Dener PetscBool same; 84*b9ac7092SAlp Dener 85*b9ac7092SAlp Dener PetscFunctionBegin; 86*b9ac7092SAlp Dener PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 87*b9ac7092SAlp Dener PetscValidHeaderSpecific(pc, IS_CLASSID, 2); 88*b9ac7092SAlp Dener ierr = PetscObjectTypeCompare((PetscObject)pc, PCLMVM, &same);CHKERRQ(ierr); 89*b9ac7092SAlp Dener if (!same) SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "PC must be a PCLMVM type."); 90*b9ac7092SAlp Dener ierr = PCLMVMClearIS(pc); 91*b9ac7092SAlp Dener ierr = PetscObjectReference((PetscObject)inactive);CHKERRQ(ierr); 92*b9ac7092SAlp Dener ctx->inactive = inactive; 93*b9ac7092SAlp Dener PetscFunctionReturn(0); 94*b9ac7092SAlp Dener } 95*b9ac7092SAlp Dener 96*b9ac7092SAlp Dener /*@ 97*b9ac7092SAlp Dener PCLMVMClearIS - Removes the inactive variable index set. 98*b9ac7092SAlp Dener 99*b9ac7092SAlp Dener Input Parameters: 100*b9ac7092SAlp Dener . pc - An LMVM preconditioner 101*b9ac7092SAlp Dener 102*b9ac7092SAlp Dener Level: intermediate 103*b9ac7092SAlp Dener 104*b9ac7092SAlp Dener .seealso: MatLMVMUpdate() 105*b9ac7092SAlp Dener @*/ 106*b9ac7092SAlp Dener PetscErrorCode PCLMVMClearIS(PC pc) 107*b9ac7092SAlp Dener { 108*b9ac7092SAlp Dener PC_LMVM *ctx = (PC_LMVM*)pc->data; 109*b9ac7092SAlp Dener PetscErrorCode ierr; 110*b9ac7092SAlp Dener PetscBool same; 111*b9ac7092SAlp Dener 112*b9ac7092SAlp Dener PetscFunctionBegin; 113*b9ac7092SAlp Dener PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 114*b9ac7092SAlp Dener ierr = PetscObjectTypeCompare((PetscObject)pc, PCLMVM, &same);CHKERRQ(ierr); 115*b9ac7092SAlp Dener if (!same) SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "PC must be a PCLMVM type."); 116*b9ac7092SAlp Dener if (ctx->inactive) { 117*b9ac7092SAlp Dener ierr = ISDestroy(&ctx->inactive);CHKERRQ(ierr); 118*b9ac7092SAlp Dener } 119*b9ac7092SAlp Dener PetscFunctionReturn(0); 120*b9ac7092SAlp Dener } 121*b9ac7092SAlp Dener 122*b9ac7092SAlp Dener static PetscErrorCode PCApply_LMVM(PC pc,Vec x,Vec y) 123*b9ac7092SAlp Dener { 124*b9ac7092SAlp Dener PC_LMVM *ctx = (PC_LMVM*)pc->data; 125*b9ac7092SAlp Dener PetscErrorCode ierr; 126*b9ac7092SAlp Dener Vec xsub, ysub; 127*b9ac7092SAlp Dener 128*b9ac7092SAlp Dener PetscFunctionBegin; 129*b9ac7092SAlp Dener if (ctx->inactive) { 130*b9ac7092SAlp Dener ierr = VecZeroEntries(ctx->xwork);CHKERRQ(ierr); 131*b9ac7092SAlp Dener ierr = VecGetSubVector(ctx->xwork, ctx->inactive, &xsub);CHKERRQ(ierr); 132*b9ac7092SAlp Dener ierr = VecCopy(x, xsub);CHKERRQ(ierr); 133*b9ac7092SAlp Dener ierr = VecRestoreSubVector(ctx->xwork, ctx->inactive, &xsub);CHKERRQ(ierr); 134*b9ac7092SAlp Dener } else { 135*b9ac7092SAlp Dener ierr = VecCopy(x, ctx->xwork);CHKERRQ(ierr); 136*b9ac7092SAlp Dener } 137*b9ac7092SAlp Dener ierr = MatSolve(ctx->B, ctx->xwork, ctx->ywork);CHKERRQ(ierr); 138*b9ac7092SAlp Dener if (ctx->inactive) { 139*b9ac7092SAlp Dener ierr = VecGetSubVector(ctx->ywork, ctx->inactive, &ysub);CHKERRQ(ierr); 140*b9ac7092SAlp Dener ierr = VecCopy(ysub, y);CHKERRQ(ierr); 141*b9ac7092SAlp Dener ierr = VecRestoreSubVector(ctx->ywork, ctx->inactive, &ysub);CHKERRQ(ierr); 142*b9ac7092SAlp Dener } else { 143*b9ac7092SAlp Dener ierr = VecCopy(ctx->ywork, y);CHKERRQ(ierr); 144*b9ac7092SAlp Dener } 145*b9ac7092SAlp Dener PetscFunctionReturn(0); 146*b9ac7092SAlp Dener } 147*b9ac7092SAlp Dener 148*b9ac7092SAlp Dener static PetscErrorCode PCReset_LMVM(PC pc) 149*b9ac7092SAlp Dener { 150*b9ac7092SAlp Dener PC_LMVM *ctx = (PC_LMVM*)pc->data; 151*b9ac7092SAlp Dener PetscErrorCode ierr; 152*b9ac7092SAlp Dener 153*b9ac7092SAlp Dener PetscFunctionBegin; 154*b9ac7092SAlp Dener if (ctx->xwork) { 155*b9ac7092SAlp Dener ierr = VecDestroy(&ctx->xwork);CHKERRQ(ierr); 156*b9ac7092SAlp Dener } 157*b9ac7092SAlp Dener if (ctx->ywork) { 158*b9ac7092SAlp Dener ierr = VecDestroy(&ctx->ywork);CHKERRQ(ierr); 159*b9ac7092SAlp Dener } 160*b9ac7092SAlp Dener PetscFunctionReturn(0); 161*b9ac7092SAlp Dener } 162*b9ac7092SAlp Dener 163*b9ac7092SAlp Dener static PetscErrorCode PCSetUp_LMVM(PC pc) 164*b9ac7092SAlp Dener { 165*b9ac7092SAlp Dener PC_LMVM *ctx = (PC_LMVM*)pc->data; 166*b9ac7092SAlp Dener PetscErrorCode ierr; 167*b9ac7092SAlp Dener PetscInt n, N; 168*b9ac7092SAlp Dener 169*b9ac7092SAlp Dener PetscFunctionBegin; 170*b9ac7092SAlp Dener ierr = MatCreateVecs(pc->mat, &ctx->xwork, &ctx->ywork);CHKERRQ(ierr); 171*b9ac7092SAlp Dener ierr = VecGetLocalSize(ctx->xwork, &n);CHKERRQ(ierr); 172*b9ac7092SAlp Dener ierr = VecGetSize(ctx->xwork, &N);CHKERRQ(ierr); 173*b9ac7092SAlp Dener ierr = MatSetSizes(ctx->B, n, n, N, N);CHKERRQ(ierr); 174*b9ac7092SAlp Dener ierr = MatLMVMAllocate(ctx->B, ctx->xwork, ctx->ywork);CHKERRQ(ierr); 175*b9ac7092SAlp Dener PetscFunctionReturn(0); 176*b9ac7092SAlp Dener } 177*b9ac7092SAlp Dener 178*b9ac7092SAlp Dener static PetscErrorCode PCView_LMVM(PC pc,PetscViewer viewer) 179*b9ac7092SAlp Dener { 180*b9ac7092SAlp Dener PC_LMVM *ctx = (PC_LMVM*)pc->data; 181*b9ac7092SAlp Dener PetscErrorCode ierr; 182*b9ac7092SAlp Dener PetscBool iascii; 183*b9ac7092SAlp Dener 184*b9ac7092SAlp Dener PetscFunctionBegin; 185*b9ac7092SAlp Dener ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 186*b9ac7092SAlp Dener if (iascii) { 187*b9ac7092SAlp Dener ierr = PetscViewerPushFormat(viewer, PETSC_VIEWER_ASCII_INFO);CHKERRQ(ierr); 188*b9ac7092SAlp Dener ierr = MatView(ctx->B, viewer);CHKERRQ(ierr); 189*b9ac7092SAlp Dener ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 190*b9ac7092SAlp Dener } 191*b9ac7092SAlp Dener PetscFunctionReturn(0); 192*b9ac7092SAlp Dener } 193*b9ac7092SAlp Dener 194*b9ac7092SAlp Dener static PetscErrorCode PCSetFromOptions_LMVM(PetscOptionItems* PetscOptionsObject, PC pc) 195*b9ac7092SAlp Dener { 196*b9ac7092SAlp Dener PC_LMVM *ctx = (PC_LMVM*)pc->data; 197*b9ac7092SAlp Dener PetscErrorCode ierr; 198*b9ac7092SAlp Dener 199*b9ac7092SAlp Dener PetscFunctionBegin; 200*b9ac7092SAlp Dener ierr = MatSetFromOptions(ctx->B);CHKERRQ(ierr); 201*b9ac7092SAlp Dener PetscFunctionReturn(0); 202*b9ac7092SAlp Dener } 203*b9ac7092SAlp Dener 204*b9ac7092SAlp Dener static PetscErrorCode PCDestroy_LMVM(PC pc) 205*b9ac7092SAlp Dener { 206*b9ac7092SAlp Dener PC_LMVM *ctx = (PC_LMVM*)pc->data; 207*b9ac7092SAlp Dener PetscErrorCode ierr; 208*b9ac7092SAlp Dener 209*b9ac7092SAlp Dener PetscFunctionBegin; 210*b9ac7092SAlp Dener if (ctx->inactive) { 211*b9ac7092SAlp Dener ierr = ISDestroy(&ctx->inactive);CHKERRQ(ierr); 212*b9ac7092SAlp Dener } 213*b9ac7092SAlp Dener if (pc->setupcalled) { 214*b9ac7092SAlp Dener ierr = VecDestroy(&ctx->xwork);CHKERRQ(ierr); 215*b9ac7092SAlp Dener ierr = VecDestroy(&ctx->ywork);CHKERRQ(ierr); 216*b9ac7092SAlp Dener } 217*b9ac7092SAlp Dener ierr = MatDestroy(&ctx->B);CHKERRQ(ierr); 218*b9ac7092SAlp Dener ierr = PetscFree(pc->data);CHKERRQ(ierr); 219*b9ac7092SAlp Dener PetscFunctionReturn(0); 220*b9ac7092SAlp Dener } 221*b9ac7092SAlp Dener 222*b9ac7092SAlp Dener /*MC 223*b9ac7092SAlp Dener PCLMVM - Creates a preconditioner around an LMVM matrix. Options for the 224*b9ac7092SAlp Dener underlying LMVM matrix can be access with the "-pc_lmvm_" prefix. 225*b9ac7092SAlp Dener 226*b9ac7092SAlp Dener .seealso: PCCreate(), PCSetType(), PCType (for list of available types), 227*b9ac7092SAlp Dener PC, MATLMVM, PCLMVMUpdate(), PCLMVMSetMatLMVM(), PCLMVMGetMatLMVM() 228*b9ac7092SAlp Dener M*/ 229*b9ac7092SAlp Dener PETSC_EXTERN PetscErrorCode PCCreate_LMVM(PC pc) 230*b9ac7092SAlp Dener { 231*b9ac7092SAlp Dener PetscErrorCode ierr; 232*b9ac7092SAlp Dener PC_LMVM *ctx; 233*b9ac7092SAlp Dener 234*b9ac7092SAlp Dener PetscFunctionBegin; 235*b9ac7092SAlp Dener ierr = PetscNewLog(pc,&ctx);CHKERRQ(ierr); 236*b9ac7092SAlp Dener pc->data = (void*)ctx; 237*b9ac7092SAlp Dener 238*b9ac7092SAlp Dener pc->ops->reset = PCReset_LMVM; 239*b9ac7092SAlp Dener pc->ops->setup = PCSetUp_LMVM; 240*b9ac7092SAlp Dener pc->ops->destroy = PCDestroy_LMVM; 241*b9ac7092SAlp Dener pc->ops->view = PCView_LMVM; 242*b9ac7092SAlp Dener pc->ops->apply = PCApply_LMVM; 243*b9ac7092SAlp Dener pc->ops->setfromoptions = PCSetFromOptions_LMVM; 244*b9ac7092SAlp Dener pc->ops->applysymmetricleft = 0; 245*b9ac7092SAlp Dener pc->ops->applysymmetricright = 0; 246*b9ac7092SAlp Dener pc->ops->applytranspose = 0; 247*b9ac7092SAlp Dener pc->ops->applyrichardson = 0; 248*b9ac7092SAlp Dener pc->ops->presolve = 0; 249*b9ac7092SAlp Dener pc->ops->postsolve = 0; 250*b9ac7092SAlp Dener 251*b9ac7092SAlp Dener ierr = PCSetReusePreconditioner(pc, PETSC_TRUE); 252*b9ac7092SAlp Dener 253*b9ac7092SAlp Dener ierr = MatCreate(PetscObjectComm((PetscObject)pc), &ctx->B);CHKERRQ(ierr); 254*b9ac7092SAlp Dener ierr = MatSetType(ctx->B, MATLBFGS);CHKERRQ(ierr); 255*b9ac7092SAlp Dener ierr = PetscObjectIncrementTabLevel((PetscObject)ctx->B, (PetscObject)pc, 1);CHKERRQ(ierr); 256*b9ac7092SAlp Dener ierr = MatSetOptionsPrefix(ctx->B, "pc_lmvm_");CHKERRQ(ierr); 257*b9ac7092SAlp Dener PetscFunctionReturn(0); 258*b9ac7092SAlp Dener } 259*b9ac7092SAlp Dener 260*b9ac7092SAlp Dener 261*b9ac7092SAlp Dener 262*b9ac7092SAlp Dener 263*b9ac7092SAlp Dener 264*b9ac7092SAlp Dener 265