1b9ac7092SAlp Dener /* 2f7bf01afSAlp Dener This provides a thin wrapper around LMVM matrices in order to use their MatLMVMSolve 3b9ac7092SAlp Dener methods as preconditioner applications in KSP solves. 4b9ac7092SAlp Dener */ 5b9ac7092SAlp Dener 6b9ac7092SAlp Dener #include <petsc/private/pcimpl.h> /*I "petscpc.h" I*/ 7dbf6bb8dSprj- #include <petsc/private/matimpl.h> 8b9ac7092SAlp Dener 9b9ac7092SAlp Dener typedef struct { 10b9ac7092SAlp Dener Vec xwork, ywork; 11b9ac7092SAlp Dener IS inactive; 12b9ac7092SAlp Dener Mat B; 13b2d8c577SAlp Dener PetscBool allocated; 14b9ac7092SAlp Dener } PC_LMVM; 15b9ac7092SAlp Dener 16b9ac7092SAlp Dener /*@ 17b9ac7092SAlp Dener PCLMVMSetMatLMVM - Replaces the LMVM matrix inside the preconditioner with 18b9ac7092SAlp Dener the one provided by the user. 19b9ac7092SAlp Dener 20b9ac7092SAlp Dener Input Parameters: 21b9ac7092SAlp Dener + pc - An LMVM preconditioner 22b9ac7092SAlp Dener - B - An LMVM-type matrix (MATLDFP, MATLBFGS, MATLSR1, MATLBRDN, MATLMBRDN, MATLSBRDN) 23b9ac7092SAlp Dener 24b9ac7092SAlp Dener Level: intermediate 25b9ac7092SAlp Dener @*/ 269371c9d4SSatish Balay PetscErrorCode PCLMVMSetMatLMVM(PC pc, Mat B) { 27b9ac7092SAlp Dener PC_LMVM *ctx = (PC_LMVM *)pc->data; 28b9ac7092SAlp Dener PetscBool same; 29b9ac7092SAlp Dener 30b9ac7092SAlp Dener PetscFunctionBegin; 31b9ac7092SAlp Dener PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 32b9ac7092SAlp Dener PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 339566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCLMVM, &same)); 3428b400f6SJacob Faibussowitsch PetscCheck(same, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "PC must be a PCLMVM type."); 359566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)B, MATLMVM, &same)); 3628b400f6SJacob Faibussowitsch PetscCheck(same, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Matrix must be an LMVM-type."); 379566063dSJacob Faibussowitsch PetscCall(MatDestroy(&ctx->B)); 389566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)B)); 39b9ac7092SAlp Dener ctx->B = B; 40b9ac7092SAlp Dener PetscFunctionReturn(0); 41b9ac7092SAlp Dener } 42b9ac7092SAlp Dener 43b9ac7092SAlp Dener /*@ 44b9ac7092SAlp Dener PCLMVMGetMatLMVM - Returns a pointer to the underlying LMVM matrix. 45b9ac7092SAlp Dener 46b9ac7092SAlp Dener Input Parameters: 47b9ac7092SAlp Dener . pc - An LMVM preconditioner 48b9ac7092SAlp Dener 49b9ac7092SAlp Dener Output Parameters: 50b9ac7092SAlp Dener . B - LMVM matrix inside the preconditioner 51b9ac7092SAlp Dener 52b9ac7092SAlp Dener Level: intermediate 53b9ac7092SAlp Dener @*/ 549371c9d4SSatish Balay PetscErrorCode PCLMVMGetMatLMVM(PC pc, Mat *B) { 55b9ac7092SAlp Dener PC_LMVM *ctx = (PC_LMVM *)pc->data; 56b9ac7092SAlp Dener PetscBool same; 57b9ac7092SAlp Dener 58b9ac7092SAlp Dener PetscFunctionBegin; 59b9ac7092SAlp Dener PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 609566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCLMVM, &same)); 6128b400f6SJacob Faibussowitsch PetscCheck(same, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "PC must be a PCLMVM type."); 62b9ac7092SAlp Dener *B = ctx->B; 63b9ac7092SAlp Dener PetscFunctionReturn(0); 64b9ac7092SAlp Dener } 65b9ac7092SAlp Dener 66b9ac7092SAlp Dener /*@ 67b9ac7092SAlp Dener PCLMVMSetIS - Sets the index sets that reduce the PC application. 68b9ac7092SAlp Dener 69b9ac7092SAlp Dener Input Parameters: 70b9ac7092SAlp Dener + pc - An LMVM preconditioner 71b9ac7092SAlp Dener - inactive - Index set defining the variables removed from the problem 72b9ac7092SAlp Dener 73b9ac7092SAlp Dener Level: intermediate 74b9ac7092SAlp Dener 75db781477SPatrick Sanan .seealso: `MatLMVMUpdate()` 76b9ac7092SAlp Dener @*/ 779371c9d4SSatish Balay PetscErrorCode PCLMVMSetIS(PC pc, IS inactive) { 78b9ac7092SAlp Dener PC_LMVM *ctx = (PC_LMVM *)pc->data; 79b9ac7092SAlp Dener PetscBool same; 80b9ac7092SAlp Dener 81b9ac7092SAlp Dener PetscFunctionBegin; 82b9ac7092SAlp Dener PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 83b2d8c577SAlp Dener PetscValidHeaderSpecific(inactive, IS_CLASSID, 2); 849566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCLMVM, &same)); 8528b400f6SJacob Faibussowitsch PetscCheck(same, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "PC must be a PCLMVM type."); 869566063dSJacob Faibussowitsch PetscCall(PCLMVMClearIS(pc)); 879566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)inactive)); 88b9ac7092SAlp Dener ctx->inactive = inactive; 89b9ac7092SAlp Dener PetscFunctionReturn(0); 90b9ac7092SAlp Dener } 91b9ac7092SAlp Dener 92b9ac7092SAlp Dener /*@ 93b9ac7092SAlp Dener PCLMVMClearIS - Removes the inactive variable index set. 94b9ac7092SAlp Dener 95b9ac7092SAlp Dener Input Parameters: 96b9ac7092SAlp Dener . pc - An LMVM preconditioner 97b9ac7092SAlp Dener 98b9ac7092SAlp Dener Level: intermediate 99b9ac7092SAlp Dener 100db781477SPatrick Sanan .seealso: `MatLMVMUpdate()` 101b9ac7092SAlp Dener @*/ 1029371c9d4SSatish Balay PetscErrorCode PCLMVMClearIS(PC pc) { 103b9ac7092SAlp Dener PC_LMVM *ctx = (PC_LMVM *)pc->data; 104b9ac7092SAlp Dener PetscBool same; 105b9ac7092SAlp Dener 106b9ac7092SAlp Dener PetscFunctionBegin; 107b9ac7092SAlp Dener PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 1089566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCLMVM, &same)); 10928b400f6SJacob Faibussowitsch PetscCheck(same, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "PC must be a PCLMVM type."); 110*48a46eb9SPierre Jolivet if (ctx->inactive) PetscCall(ISDestroy(&ctx->inactive)); 111b9ac7092SAlp Dener PetscFunctionReturn(0); 112b9ac7092SAlp Dener } 113b9ac7092SAlp Dener 1149371c9d4SSatish Balay static PetscErrorCode PCApply_LMVM(PC pc, Vec x, Vec y) { 115b9ac7092SAlp Dener PC_LMVM *ctx = (PC_LMVM *)pc->data; 116b9ac7092SAlp Dener Vec xsub, ysub; 117b9ac7092SAlp Dener 118b9ac7092SAlp Dener PetscFunctionBegin; 119b9ac7092SAlp Dener if (ctx->inactive) { 1209566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(ctx->xwork)); 1219566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(ctx->xwork, ctx->inactive, &xsub)); 1229566063dSJacob Faibussowitsch PetscCall(VecCopy(x, xsub)); 1239566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(ctx->xwork, ctx->inactive, &xsub)); 124b9ac7092SAlp Dener } else { 1259566063dSJacob Faibussowitsch PetscCall(VecCopy(x, ctx->xwork)); 126b9ac7092SAlp Dener } 1279566063dSJacob Faibussowitsch PetscCall(MatSolve(ctx->B, ctx->xwork, ctx->ywork)); 128b9ac7092SAlp Dener if (ctx->inactive) { 1299566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(ctx->ywork, ctx->inactive, &ysub)); 1309566063dSJacob Faibussowitsch PetscCall(VecCopy(ysub, y)); 1319566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(ctx->ywork, ctx->inactive, &ysub)); 132b9ac7092SAlp Dener } else { 1339566063dSJacob Faibussowitsch PetscCall(VecCopy(ctx->ywork, y)); 134b9ac7092SAlp Dener } 135b9ac7092SAlp Dener PetscFunctionReturn(0); 136b9ac7092SAlp Dener } 137b9ac7092SAlp Dener 1389371c9d4SSatish Balay static PetscErrorCode PCReset_LMVM(PC pc) { 139b9ac7092SAlp Dener PC_LMVM *ctx = (PC_LMVM *)pc->data; 140b9ac7092SAlp Dener 141b9ac7092SAlp Dener PetscFunctionBegin; 142*48a46eb9SPierre Jolivet if (ctx->xwork) PetscCall(VecDestroy(&ctx->xwork)); 143*48a46eb9SPierre Jolivet if (ctx->ywork) PetscCall(VecDestroy(&ctx->ywork)); 144b9ac7092SAlp Dener PetscFunctionReturn(0); 145b9ac7092SAlp Dener } 146b9ac7092SAlp Dener 1479371c9d4SSatish Balay static PetscErrorCode PCSetUp_LMVM(PC pc) { 148b9ac7092SAlp Dener PC_LMVM *ctx = (PC_LMVM *)pc->data; 149b9ac7092SAlp Dener PetscInt n, N; 150b2d8c577SAlp Dener PetscBool allocated; 1510e02354eSStefano Zampini const char *prefix; 152b9ac7092SAlp Dener 153b9ac7092SAlp Dener PetscFunctionBegin; 1549566063dSJacob Faibussowitsch PetscCall(MatLMVMIsAllocated(ctx->B, &allocated)); 155b2d8c577SAlp Dener if (!allocated) { 1569566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(pc->mat, &ctx->xwork, &ctx->ywork)); 1579566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(ctx->xwork, &n)); 1589566063dSJacob Faibussowitsch PetscCall(VecGetSize(ctx->xwork, &N)); 1599566063dSJacob Faibussowitsch PetscCall(MatSetSizes(ctx->B, n, n, N, N)); 1609566063dSJacob Faibussowitsch PetscCall(MatLMVMAllocate(ctx->B, ctx->xwork, ctx->ywork)); 161b2d8c577SAlp Dener } else { 1629566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(ctx->B, &ctx->xwork, &ctx->ywork)); 163b2d8c577SAlp Dener } 1640e02354eSStefano Zampini PetscCall(PCGetOptionsPrefix(pc, &prefix)); 1650e02354eSStefano Zampini PetscCall(MatSetOptionsPrefix(ctx->B, prefix)); 1660e02354eSStefano Zampini PetscCall(MatAppendOptionsPrefix(ctx->B, "pc_lmvm_")); 167b9ac7092SAlp Dener PetscFunctionReturn(0); 168b9ac7092SAlp Dener } 169b9ac7092SAlp Dener 1709371c9d4SSatish Balay static PetscErrorCode PCView_LMVM(PC pc, PetscViewer viewer) { 171b9ac7092SAlp Dener PC_LMVM *ctx = (PC_LMVM *)pc->data; 172b9ac7092SAlp Dener PetscBool iascii; 173b9ac7092SAlp Dener 174b9ac7092SAlp Dener PetscFunctionBegin; 1759566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 176dbf6bb8dSprj- if (iascii && ctx->B->assembled) { 1779566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_ASCII_INFO)); 1789566063dSJacob Faibussowitsch PetscCall(MatView(ctx->B, viewer)); 1799566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer)); 180b9ac7092SAlp Dener } 181b9ac7092SAlp Dener PetscFunctionReturn(0); 182b9ac7092SAlp Dener } 183b9ac7092SAlp Dener 1849371c9d4SSatish Balay static PetscErrorCode PCSetFromOptions_LMVM(PC pc, PetscOptionItems *PetscOptionsObject) { 185b9ac7092SAlp Dener PC_LMVM *ctx = (PC_LMVM *)pc->data; 1860e02354eSStefano Zampini const char *prefix; 187b9ac7092SAlp Dener 188b9ac7092SAlp Dener PetscFunctionBegin; 1890e02354eSStefano Zampini PetscCall(PCGetOptionsPrefix(pc, &prefix)); 1900e02354eSStefano Zampini PetscCall(MatSetOptionsPrefix(ctx->B, prefix)); 1910e02354eSStefano Zampini PetscCall(MatAppendOptionsPrefix(ctx->B, "pc_lmvm_")); 1929566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(ctx->B)); 193b9ac7092SAlp Dener PetscFunctionReturn(0); 194b9ac7092SAlp Dener } 195b9ac7092SAlp Dener 1969371c9d4SSatish Balay static PetscErrorCode PCDestroy_LMVM(PC pc) { 197b9ac7092SAlp Dener PC_LMVM *ctx = (PC_LMVM *)pc->data; 198b9ac7092SAlp Dener 199b9ac7092SAlp Dener PetscFunctionBegin; 200*48a46eb9SPierre Jolivet if (ctx->inactive) PetscCall(ISDestroy(&ctx->inactive)); 201b9ac7092SAlp Dener if (pc->setupcalled) { 2029566063dSJacob Faibussowitsch PetscCall(VecDestroy(&ctx->xwork)); 2039566063dSJacob Faibussowitsch PetscCall(VecDestroy(&ctx->ywork)); 204b9ac7092SAlp Dener } 2059566063dSJacob Faibussowitsch PetscCall(MatDestroy(&ctx->B)); 2069566063dSJacob Faibussowitsch PetscCall(PetscFree(pc->data)); 207b9ac7092SAlp Dener PetscFunctionReturn(0); 208b9ac7092SAlp Dener } 209b9ac7092SAlp Dener 210b9ac7092SAlp Dener /*MC 211b9ac7092SAlp Dener PCLMVM - Creates a preconditioner around an LMVM matrix. Options for the 212b9ac7092SAlp Dener underlying LMVM matrix can be access with the "-pc_lmvm_" prefix. 213b9ac7092SAlp Dener 21406dd6b0eSSatish Balay Level: intermediate 21506dd6b0eSSatish Balay 216db781477SPatrick Sanan .seealso: `PCCreate()`, `PCSetType()`, `PCType`, 217db781477SPatrick Sanan `PC`, `MATLMVM`, `PCLMVMUpdate()`, `PCLMVMSetMatLMVM()`, `PCLMVMGetMatLMVM()` 218b9ac7092SAlp Dener M*/ 2199371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode PCCreate_LMVM(PC pc) { 220b9ac7092SAlp Dener PC_LMVM *ctx; 221b9ac7092SAlp Dener 222b9ac7092SAlp Dener PetscFunctionBegin; 2239566063dSJacob Faibussowitsch PetscCall(PetscNewLog(pc, &ctx)); 224b9ac7092SAlp Dener pc->data = (void *)ctx; 225b9ac7092SAlp Dener 226b9ac7092SAlp Dener pc->ops->reset = PCReset_LMVM; 227b9ac7092SAlp Dener pc->ops->setup = PCSetUp_LMVM; 228b9ac7092SAlp Dener pc->ops->destroy = PCDestroy_LMVM; 229b9ac7092SAlp Dener pc->ops->view = PCView_LMVM; 230b9ac7092SAlp Dener pc->ops->apply = PCApply_LMVM; 231b9ac7092SAlp Dener pc->ops->setfromoptions = PCSetFromOptions_LMVM; 2320a545947SLisandro Dalcin pc->ops->applysymmetricleft = NULL; 2330a545947SLisandro Dalcin pc->ops->applysymmetricright = NULL; 2340a545947SLisandro Dalcin pc->ops->applytranspose = NULL; 2350a545947SLisandro Dalcin pc->ops->applyrichardson = NULL; 2360a545947SLisandro Dalcin pc->ops->presolve = NULL; 2370a545947SLisandro Dalcin pc->ops->postsolve = NULL; 238b9ac7092SAlp Dener 2399566063dSJacob Faibussowitsch PetscCall(PCSetReusePreconditioner(pc, PETSC_TRUE)); 240b9ac7092SAlp Dener 2419566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)pc), &ctx->B)); 2429566063dSJacob Faibussowitsch PetscCall(MatSetType(ctx->B, MATLMVMBFGS)); 2439566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)ctx->B, (PetscObject)pc, 1)); 244b9ac7092SAlp Dener PetscFunctionReturn(0); 245b9ac7092SAlp Dener } 246