xref: /petsc/src/ksp/pc/impls/lmvm/lmvmpc.c (revision 48a46eb9bd028bec07ec0f396b1a3abb43f14558)
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