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