Actual source code: lmvmpc.c
petsc-3.14.6 2021-03-30
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: }