xref: /petsc/src/snes/impls/patch/snespatch.c (revision 561742ed26eb17eb473b7929d5a9b68d57686b79)
1*561742edSMatthew G. Knepley /*
2*561742edSMatthew G. Knepley       Defines a SNES that can consist of a collection of SNESes on patches of the domain
3*561742edSMatthew G. Knepley */
4*561742edSMatthew G. Knepley #include <petsc/private/snesimpl.h> /*I "petscsnes.h" I*/
5*561742edSMatthew G. Knepley #include <petsc/private/pcpatchimpl.h> /* We need internal access to PCPatch right now, until that part is moved to Plex */
6*561742edSMatthew G. Knepley 
7*561742edSMatthew G. Knepley typedef struct {
8*561742edSMatthew G. Knepley   PC pc; /* The linear patch preconditioner */
9*561742edSMatthew G. Knepley   SNESCompositeType type;
10*561742edSMatthew G. Knepley } SNES_Patch;
11*561742edSMatthew G. Knepley 
12*561742edSMatthew G. Knepley static PetscErrorCode SNESPatchComputeResidual_Private(SNES snes, Vec x, Vec F, void *ctx)
13*561742edSMatthew G. Knepley {
14*561742edSMatthew G. Knepley   SNES           patchsolver = (SNES) ctx;
15*561742edSMatthew G. Knepley   SNES_Patch    *patch       = (SNES_Patch *) patchsolver->data;
16*561742edSMatthew G. Knepley   PC_PATCH      *pcpatch     = (PC_PATCH *) patch->pc->data;
17*561742edSMatthew G. Knepley   PetscErrorCode ierr;
18*561742edSMatthew G. Knepley 
19*561742edSMatthew G. Knepley   PetscFunctionBegin;
20*561742edSMatthew G. Knepley   ierr = PCPatchComputeFunction_Internal(patch->pc, x, F, pcpatch->currentPatch);CHKERRQ(ierr);
21*561742edSMatthew G. Knepley   PetscFunctionReturn(0);
22*561742edSMatthew G. Knepley }
23*561742edSMatthew G. Knepley 
24*561742edSMatthew G. Knepley static PetscErrorCode SNESPatchComputeJacobian_Private(SNES snes, Vec x, Mat J, Mat M, void *ctx)
25*561742edSMatthew G. Knepley {
26*561742edSMatthew G. Knepley   SNES           patchsolver = (SNES) ctx;
27*561742edSMatthew G. Knepley   SNES_Patch    *patch       = (SNES_Patch *) patchsolver->data;
28*561742edSMatthew G. Knepley   PC_PATCH      *pcpatch     = (PC_PATCH *) patch->pc->data;
29*561742edSMatthew G. Knepley   PetscErrorCode ierr;
30*561742edSMatthew G. Knepley 
31*561742edSMatthew G. Knepley   PetscFunctionBegin;
32*561742edSMatthew G. Knepley   ierr = PCPatchComputeOperator_Internal(patch->pc, x, M, pcpatch->currentPatch);CHKERRQ(ierr);
33*561742edSMatthew G. Knepley   PetscFunctionReturn(0);
34*561742edSMatthew G. Knepley }
35*561742edSMatthew G. Knepley 
36*561742edSMatthew G. Knepley static PetscErrorCode PCSetUp_PATCH_Nonlinear(PC pc)
37*561742edSMatthew G. Knepley {
38*561742edSMatthew G. Knepley   PC_PATCH      *patch = (PC_PATCH *) pc->data;
39*561742edSMatthew G. Knepley   const char    *prefix;
40*561742edSMatthew G. Knepley   PetscInt       i;
41*561742edSMatthew G. Knepley   PetscErrorCode ierr;
42*561742edSMatthew G. Knepley 
43*561742edSMatthew G. Knepley   PetscFunctionBegin;
44*561742edSMatthew G. Knepley   if (!pc->setupcalled) {
45*561742edSMatthew G. Knepley     ierr = PetscMalloc1(patch->npatch, &patch->solver);CHKERRQ(ierr);
46*561742edSMatthew G. Knepley     ierr = PCGetOptionsPrefix(pc, &prefix);CHKERRQ(ierr);
47*561742edSMatthew G. Knepley     for (i = 0; i < patch->npatch; ++i) {
48*561742edSMatthew G. Knepley       SNES snes;
49*561742edSMatthew G. Knepley       KSP  subksp;
50*561742edSMatthew G. Knepley 
51*561742edSMatthew G. Knepley       ierr = SNESCreate(PETSC_COMM_SELF, &snes);CHKERRQ(ierr);
52*561742edSMatthew G. Knepley       ierr = SNESSetOptionsPrefix(snes, prefix);CHKERRQ(ierr);
53*561742edSMatthew G. Knepley       ierr = SNESAppendOptionsPrefix(snes, "sub_");CHKERRQ(ierr);
54*561742edSMatthew G. Knepley       ierr = PetscObjectIncrementTabLevel((PetscObject) snes, (PetscObject) pc, 1);CHKERRQ(ierr);
55*561742edSMatthew G. Knepley       ierr = SNESGetKSP(snes, &subksp);CHKERRQ(ierr);
56*561742edSMatthew G. Knepley       ierr = PetscObjectIncrementTabLevel((PetscObject) subksp, (PetscObject) pc, 1);CHKERRQ(ierr);
57*561742edSMatthew G. Knepley       ierr = PetscLogObjectParent((PetscObject) pc, (PetscObject) snes);CHKERRQ(ierr);
58*561742edSMatthew G. Knepley       patch->solver[i] = (PetscObject) snes;
59*561742edSMatthew G. Knepley     }
60*561742edSMatthew G. Knepley   }
61*561742edSMatthew G. Knepley   for (i = 0; i < patch->npatch; ++i) {
62*561742edSMatthew G. Knepley     SNES snes = (SNES) patch->solver[i];
63*561742edSMatthew G. Knepley 
64*561742edSMatthew G. Knepley     ierr = SNESSetFunction(snes, patch->patchX[i], SNESPatchComputeResidual_Private, snes);CHKERRQ(ierr);
65*561742edSMatthew G. Knepley     ierr = SNESSetJacobian(snes, patch->mat[i], patch->mat[i], SNESPatchComputeJacobian_Private, snes);CHKERRQ(ierr);
66*561742edSMatthew G. Knepley   }
67*561742edSMatthew G. Knepley   if (!pc->setupcalled && patch->optionsSet) for (i = 0; i < patch->npatch; ++i) {ierr = SNESSetFromOptions((SNES) patch->solver[i]);CHKERRQ(ierr);}
68*561742edSMatthew G. Knepley   PetscFunctionReturn(0);
69*561742edSMatthew G. Knepley }
70*561742edSMatthew G. Knepley 
71*561742edSMatthew G. Knepley static PetscErrorCode PCApply_PATCH_Nonlinear(PC pc, PetscInt i, Vec x, Vec y)
72*561742edSMatthew G. Knepley {
73*561742edSMatthew G. Knepley   PC_PATCH      *patch = (PC_PATCH *) pc->data;
74*561742edSMatthew G. Knepley   PetscErrorCode ierr;
75*561742edSMatthew G. Knepley 
76*561742edSMatthew G. Knepley   PetscFunctionBegin;
77*561742edSMatthew G. Knepley   patch->currentPatch = i;
78*561742edSMatthew G. Knepley   ierr = PetscLogEventBegin(PC_Patch_Solve, pc, 0, 0, 0);CHKERRQ(ierr);
79*561742edSMatthew G. Knepley   ierr = SNESSolve((SNES) patch->solver[i], x, y);CHKERRQ(ierr);
80*561742edSMatthew G. Knepley   ierr = PetscLogEventEnd(PC_Patch_Solve, pc, 0, 0, 0);CHKERRQ(ierr);
81*561742edSMatthew G. Knepley   PetscFunctionReturn(0);
82*561742edSMatthew G. Knepley }
83*561742edSMatthew G. Knepley 
84*561742edSMatthew G. Knepley static PetscErrorCode PCReset_PATCH_Nonlinear(PC pc)
85*561742edSMatthew G. Knepley {
86*561742edSMatthew G. Knepley   PC_PATCH      *patch = (PC_PATCH *) pc->data;
87*561742edSMatthew G. Knepley   PetscInt       i;
88*561742edSMatthew G. Knepley   PetscErrorCode ierr;
89*561742edSMatthew G. Knepley 
90*561742edSMatthew G. Knepley   PetscFunctionBegin;
91*561742edSMatthew G. Knepley   if (patch->solver) {
92*561742edSMatthew G. Knepley     for (i = 0; i < patch->npatch; ++i) {ierr = SNESReset((SNES) patch->solver[i]);CHKERRQ(ierr);}
93*561742edSMatthew G. Knepley   }
94*561742edSMatthew G. Knepley   PetscFunctionReturn(0);
95*561742edSMatthew G. Knepley }
96*561742edSMatthew G. Knepley 
97*561742edSMatthew G. Knepley static PetscErrorCode PCDestroy_PATCH_Nonlinear(PC pc)
98*561742edSMatthew G. Knepley {
99*561742edSMatthew G. Knepley   PC_PATCH      *patch = (PC_PATCH *) pc->data;
100*561742edSMatthew G. Knepley   PetscInt       i;
101*561742edSMatthew G. Knepley   PetscErrorCode ierr;
102*561742edSMatthew G. Knepley 
103*561742edSMatthew G. Knepley   PetscFunctionBegin;
104*561742edSMatthew G. Knepley   if (patch->solver) {
105*561742edSMatthew G. Knepley     for (i = 0; i < patch->npatch; ++i) {ierr = SNESDestroy((SNES *) &patch->solver[i]);CHKERRQ(ierr);}
106*561742edSMatthew G. Knepley     ierr = PetscFree(patch->solver);CHKERRQ(ierr);
107*561742edSMatthew G. Knepley   }
108*561742edSMatthew G. Knepley   PetscFunctionReturn(0);
109*561742edSMatthew G. Knepley }
110*561742edSMatthew G. Knepley 
111*561742edSMatthew G. Knepley static PetscErrorCode SNESSetUp_Patch(SNES snes)
112*561742edSMatthew G. Knepley {
113*561742edSMatthew G. Knepley   SNES_Patch    *patch = (SNES_Patch *) snes->data;
114*561742edSMatthew G. Knepley   DM             dm;
115*561742edSMatthew G. Knepley   Mat            dummy;
116*561742edSMatthew G. Knepley   Vec            F;
117*561742edSMatthew G. Knepley   PetscInt       n, N;
118*561742edSMatthew G. Knepley   PetscErrorCode ierr;
119*561742edSMatthew G. Knepley 
120*561742edSMatthew G. Knepley   PetscFunctionBegin;
121*561742edSMatthew G. Knepley   ierr = SNESGetDM(snes, &dm);CHKERRQ(ierr);
122*561742edSMatthew G. Knepley   ierr = PCSetDM(patch->pc, dm);CHKERRQ(ierr);
123*561742edSMatthew G. Knepley   ierr = SNESGetFunction(snes, &F, NULL, NULL);CHKERRQ(ierr);
124*561742edSMatthew G. Knepley   ierr = VecGetLocalSize(F, &n);CHKERRQ(ierr);
125*561742edSMatthew G. Knepley   ierr = VecGetSize(F, &N);CHKERRQ(ierr);
126*561742edSMatthew G. Knepley   ierr = MatCreateShell(PetscObjectComm((PetscObject) snes), n, n, N, N, (void *) snes, &dummy);CHKERRQ(ierr);
127*561742edSMatthew G. Knepley   ierr = PCSetOperators(patch->pc, dummy, dummy);CHKERRQ(ierr);
128*561742edSMatthew G. Knepley   ierr = MatDestroy(&dummy);CHKERRQ(ierr);
129*561742edSMatthew G. Knepley   ierr = PCSetUp(patch->pc);CHKERRQ(ierr);
130*561742edSMatthew G. Knepley   /* allocate workspace */
131*561742edSMatthew G. Knepley   PetscFunctionReturn(0);
132*561742edSMatthew G. Knepley }
133*561742edSMatthew G. Knepley 
134*561742edSMatthew G. Knepley static PetscErrorCode SNESReset_Patch(SNES snes)
135*561742edSMatthew G. Knepley {
136*561742edSMatthew G. Knepley   SNES_Patch    *patch = (SNES_Patch *) snes->data;
137*561742edSMatthew G. Knepley   PetscErrorCode ierr;
138*561742edSMatthew G. Knepley 
139*561742edSMatthew G. Knepley   PetscFunctionBegin;
140*561742edSMatthew G. Knepley   ierr = PCReset(patch->pc);CHKERRQ(ierr);
141*561742edSMatthew G. Knepley   PetscFunctionReturn(0);
142*561742edSMatthew G. Knepley }
143*561742edSMatthew G. Knepley 
144*561742edSMatthew G. Knepley static PetscErrorCode SNESDestroy_Patch(SNES snes)
145*561742edSMatthew G. Knepley {
146*561742edSMatthew G. Knepley   SNES_Patch    *patch = (SNES_Patch *) snes->data;
147*561742edSMatthew G. Knepley   PetscErrorCode ierr;
148*561742edSMatthew G. Knepley 
149*561742edSMatthew G. Knepley   PetscFunctionBegin;
150*561742edSMatthew G. Knepley   ierr = SNESReset_Patch(snes);CHKERRQ(ierr);
151*561742edSMatthew G. Knepley   ierr = PCDestroy(&patch->pc);CHKERRQ(ierr);
152*561742edSMatthew G. Knepley   ierr = PetscFree(snes->data);CHKERRQ(ierr);
153*561742edSMatthew G. Knepley   PetscFunctionReturn(0);
154*561742edSMatthew G. Knepley }
155*561742edSMatthew G. Knepley 
156*561742edSMatthew G. Knepley static PetscErrorCode SNESSetFromOptions_Patch(PetscOptionItems *PetscOptionsObject, SNES snes)
157*561742edSMatthew G. Knepley {
158*561742edSMatthew G. Knepley   SNES_Patch     *patch = (SNES_Patch *) snes->data;
159*561742edSMatthew G. Knepley   PetscBool      flg;
160*561742edSMatthew G. Knepley   PetscErrorCode ierr;
161*561742edSMatthew G. Knepley 
162*561742edSMatthew G. Knepley   PetscFunctionBegin;
163*561742edSMatthew G. Knepley   ierr = PetscOptionsHead(PetscOptionsObject, "Patch nonlinear preconditioner options");CHKERRQ(ierr);
164*561742edSMatthew G. Knepley   ierr = PetscOptionsEnum("-snes_patch_type", "Type of composition", "SNESPatchSetType", SNESCompositeTypes, (PetscEnum) patch->type, (PetscEnum *) &patch->type, &flg);CHKERRQ(ierr);
165*561742edSMatthew G. Knepley   if (flg) {ierr = SNESPatchSetType(snes, patch->type);CHKERRQ(ierr);}
166*561742edSMatthew G. Knepley   ierr = PetscOptionsTail();CHKERRQ(ierr);
167*561742edSMatthew G. Knepley 
168*561742edSMatthew G. Knepley   ierr = PCSetFromOptions(patch->pc);CHKERRQ(ierr);
169*561742edSMatthew G. Knepley   PetscFunctionReturn(0);
170*561742edSMatthew G. Knepley }
171*561742edSMatthew G. Knepley 
172*561742edSMatthew G. Knepley static PetscErrorCode SNESView_Patch(SNES snes,PetscViewer viewer)
173*561742edSMatthew G. Knepley {
174*561742edSMatthew G. Knepley   SNES_Patch    *patch = (SNES_Patch *) snes->data;
175*561742edSMatthew G. Knepley   PetscBool      iascii;
176*561742edSMatthew G. Knepley   PetscErrorCode ierr;
177*561742edSMatthew G. Knepley 
178*561742edSMatthew G. Knepley   PetscFunctionBegin;
179*561742edSMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
180*561742edSMatthew G. Knepley   if (iascii) {
181*561742edSMatthew G. Knepley     ierr = PetscViewerASCIIPrintf(viewer,"  type - %s\n",SNESCompositeTypes[patch->type]);CHKERRQ(ierr);
182*561742edSMatthew G. Knepley   }
183*561742edSMatthew G. Knepley   ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
184*561742edSMatthew G. Knepley   ierr = PCView(patch->pc, viewer);CHKERRQ(ierr);
185*561742edSMatthew G. Knepley   ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
186*561742edSMatthew G. Knepley   PetscFunctionReturn(0);
187*561742edSMatthew G. Knepley }
188*561742edSMatthew G. Knepley 
189*561742edSMatthew G. Knepley static PetscErrorCode SNESSolve_Patch(SNES snes)
190*561742edSMatthew G. Knepley {
191*561742edSMatthew G. Knepley   PetscFunctionBegin;
192*561742edSMatthew G. Knepley   PetscFunctionReturn(0);
193*561742edSMatthew G. Knepley }
194*561742edSMatthew G. Knepley 
195*561742edSMatthew G. Knepley static PetscErrorCode SNESPatchSetType_Patch(SNES snes, SNESCompositeType type)
196*561742edSMatthew G. Knepley {
197*561742edSMatthew G. Knepley   SNES_Patch *patch = (SNES_Patch *) snes->data;
198*561742edSMatthew G. Knepley 
199*561742edSMatthew G. Knepley   PetscFunctionBegin;
200*561742edSMatthew G. Knepley   patch->type = type;
201*561742edSMatthew G. Knepley   PetscFunctionReturn(0);
202*561742edSMatthew G. Knepley }
203*561742edSMatthew G. Knepley 
204*561742edSMatthew G. Knepley /*MC
205*561742edSMatthew G. Knepley   SNESPATCH - Build a preconditioner by composing together many nonlinear solvers on patches
206*561742edSMatthew G. Knepley 
207*561742edSMatthew G. Knepley   Options Database Keys:
208*561742edSMatthew G. Knepley . -snes_patch_type <type: one of additive, multiplicative, symmetric_multiplicative> - Sets composition type
209*561742edSMatthew G. Knepley 
210*561742edSMatthew G. Knepley   Level: intermediate
211*561742edSMatthew G. Knepley 
212*561742edSMatthew G. Knepley   Concepts: composing solvers
213*561742edSMatthew G. Knepley 
214*561742edSMatthew G. Knepley .seealso:  SNESCreate(), SNESSetType(), SNESType (for list of available types), SNES,
215*561742edSMatthew G. Knepley            PCPATCH
216*561742edSMatthew G. Knepley 
217*561742edSMatthew G. Knepley    References:
218*561742edSMatthew G. Knepley .  1. - Peter R. Brune, Matthew G. Knepley, Barry F. Smith, and Xuemin Tu, "Composing Scalable Nonlinear Algebraic Solvers", SIAM Review, 57(4), 2015
219*561742edSMatthew G. Knepley 
220*561742edSMatthew G. Knepley M*/
221*561742edSMatthew G. Knepley PETSC_EXTERN PetscErrorCode SNESCreate_Patch(SNES snes)
222*561742edSMatthew G. Knepley {
223*561742edSMatthew G. Knepley   PetscErrorCode ierr;
224*561742edSMatthew G. Knepley   SNES_Patch    *patch;
225*561742edSMatthew G. Knepley 
226*561742edSMatthew G. Knepley   PetscFunctionBegin;
227*561742edSMatthew G. Knepley   ierr = PetscNewLog(snes, &patch);CHKERRQ(ierr);
228*561742edSMatthew G. Knepley 
229*561742edSMatthew G. Knepley   snes->ops->solve          = SNESSolve_Patch;
230*561742edSMatthew G. Knepley   snes->ops->setup          = SNESSetUp_Patch;
231*561742edSMatthew G. Knepley   snes->ops->reset          = SNESReset_Patch;
232*561742edSMatthew G. Knepley   snes->ops->destroy        = SNESDestroy_Patch;
233*561742edSMatthew G. Knepley   snes->ops->setfromoptions = SNESSetFromOptions_Patch;
234*561742edSMatthew G. Knepley   snes->ops->view           = SNESView_Patch;
235*561742edSMatthew G. Knepley 
236*561742edSMatthew G. Knepley   snes->alwayscomputesfinalresidual = PETSC_FALSE;
237*561742edSMatthew G. Knepley 
238*561742edSMatthew G. Knepley   snes->data = (void *) patch;
239*561742edSMatthew G. Knepley   patch->type = SNES_COMPOSITE_ADDITIVE;
240*561742edSMatthew G. Knepley   ierr = PCCreate(PetscObjectComm((PetscObject) snes), &patch->pc);CHKERRQ(ierr);
241*561742edSMatthew G. Knepley   ierr = PCSetType(patch->pc, PCPATCH);CHKERRQ(ierr);
242*561742edSMatthew G. Knepley 
243*561742edSMatthew G. Knepley   ((PC_PATCH *) patch->pc->data)->setupsolver   = PCSetUp_PATCH_Nonlinear;
244*561742edSMatthew G. Knepley   ((PC_PATCH *) patch->pc->data)->applysolver   = PCApply_PATCH_Nonlinear;
245*561742edSMatthew G. Knepley   ((PC_PATCH *) patch->pc->data)->resetsolver   = PCReset_PATCH_Nonlinear;
246*561742edSMatthew G. Knepley   ((PC_PATCH *) patch->pc->data)->destroysolver = PCDestroy_PATCH_Nonlinear;
247*561742edSMatthew G. Knepley 
248*561742edSMatthew G. Knepley   ierr = PetscObjectComposeFunction((PetscObject) snes, "SNESPatchSetType_C", SNESPatchSetType_Patch);CHKERRQ(ierr);
249*561742edSMatthew G. Knepley   PetscFunctionReturn(0);
250*561742edSMatthew G. Knepley }
251*561742edSMatthew G. Knepley 
252*561742edSMatthew G. Knepley /*@
253*561742edSMatthew G. Knepley   SNESPatchSetType - Sets the type of composition.
254*561742edSMatthew G. Knepley 
255*561742edSMatthew G. Knepley   Logically Collective on SNES
256*561742edSMatthew G. Knepley 
257*561742edSMatthew G. Knepley   Input Parameter:
258*561742edSMatthew G. Knepley + snes - the preconditioner context
259*561742edSMatthew G. Knepley - type - SNES_COMPOSITE_ADDITIVE (default), SNES_COMPOSITE_MULTIPLICATIVE, etc.
260*561742edSMatthew G. Knepley 
261*561742edSMatthew G. Knepley   Options Database Key:
262*561742edSMatthew G. Knepley . -snes_composite_type <type: one of additive, multiplicative, etc> - Sets composite preconditioner type
263*561742edSMatthew G. Knepley 
264*561742edSMatthew G. Knepley   Level: Developer
265*561742edSMatthew G. Knepley 
266*561742edSMatthew G. Knepley .keywords: SNES, set, type, composite preconditioner, additive, multiplicative
267*561742edSMatthew G. Knepley @*/
268*561742edSMatthew G. Knepley PetscErrorCode SNESPatchSetType(SNES snes, SNESCompositeType type)
269*561742edSMatthew G. Knepley {
270*561742edSMatthew G. Knepley   PetscErrorCode ierr;
271*561742edSMatthew G. Knepley 
272*561742edSMatthew G. Knepley   PetscFunctionBegin;
273*561742edSMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
274*561742edSMatthew G. Knepley   PetscValidLogicalCollectiveEnum(snes,type, 2);
275*561742edSMatthew G. Knepley   ierr = PetscTryMethod(snes, "SNESPatchSetType_C", (SNES,SNESCompositeType), (snes,type));CHKERRQ(ierr);
276*561742edSMatthew G. Knepley   PetscFunctionReturn(0);
277*561742edSMatthew G. Knepley }
278