1 /*
2 Defines a SNES that can consist of a collection of SNESes on patches of the domain
3 */
4 #include <petsc/private/vecimpl.h> /* For vec->map */
5 #include <petsc/private/snesimpl.h> /*I "petscsnes.h" I*/
6 #include <petsc/private/pcpatchimpl.h> /* We need internal access to PCPatch right now, until that part is moved to Plex */
7 #include <petscsf.h>
8 #include <petscsection.h>
9
10 typedef struct {
11 PC pc; /* The linear patch preconditioner */
12 } SNES_Patch;
13
SNESPatchComputeResidual_Private(SNES snes,Vec x,Vec F,void * ctx)14 static PetscErrorCode SNESPatchComputeResidual_Private(SNES snes, Vec x, Vec F, void *ctx)
15 {
16 PC pc = (PC) ctx;
17 PC_PATCH *pcpatch = (PC_PATCH *) pc->data;
18 PetscInt pt, size, i;
19 const PetscInt *indices;
20 const PetscScalar *X;
21 PetscScalar *XWithAll;
22 PetscErrorCode ierr;
23
24 PetscFunctionBegin;
25
26 /* scatter from x to patch->patchStateWithAll[pt] */
27 pt = pcpatch->currentPatch;
28 ierr = ISGetSize(pcpatch->dofMappingWithoutToWithAll[pt], &size);CHKERRQ(ierr);
29
30 ierr = ISGetIndices(pcpatch->dofMappingWithoutToWithAll[pt], &indices);CHKERRQ(ierr);
31 ierr = VecGetArrayRead(x, &X);CHKERRQ(ierr);
32 ierr = VecGetArray(pcpatch->patchStateWithAll, &XWithAll);CHKERRQ(ierr);
33
34 for (i = 0; i < size; ++i) {
35 XWithAll[indices[i]] = X[i];
36 }
37
38 ierr = VecRestoreArray(pcpatch->patchStateWithAll, &XWithAll);CHKERRQ(ierr);
39 ierr = VecRestoreArrayRead(x, &X);CHKERRQ(ierr);
40 ierr = ISRestoreIndices(pcpatch->dofMappingWithoutToWithAll[pt], &indices);CHKERRQ(ierr);
41
42 ierr = PCPatchComputeFunction_Internal(pc, pcpatch->patchStateWithAll, F, pt);CHKERRQ(ierr);
43 PetscFunctionReturn(0);
44 }
45
SNESPatchComputeJacobian_Private(SNES snes,Vec x,Mat J,Mat M,void * ctx)46 static PetscErrorCode SNESPatchComputeJacobian_Private(SNES snes, Vec x, Mat J, Mat M, void *ctx)
47 {
48 PC pc = (PC) ctx;
49 PC_PATCH *pcpatch = (PC_PATCH *) pc->data;
50 PetscInt pt, size, i;
51 const PetscInt *indices;
52 const PetscScalar *X;
53 PetscScalar *XWithAll;
54 PetscErrorCode ierr;
55
56 PetscFunctionBegin;
57 /* scatter from x to patch->patchStateWithAll[pt] */
58 pt = pcpatch->currentPatch;
59 ierr = ISGetSize(pcpatch->dofMappingWithoutToWithAll[pt], &size);CHKERRQ(ierr);
60
61 ierr = ISGetIndices(pcpatch->dofMappingWithoutToWithAll[pt], &indices);CHKERRQ(ierr);
62 ierr = VecGetArrayRead(x, &X);CHKERRQ(ierr);
63 ierr = VecGetArray(pcpatch->patchStateWithAll, &XWithAll);CHKERRQ(ierr);
64
65 for (i = 0; i < size; ++i) {
66 XWithAll[indices[i]] = X[i];
67 }
68
69 ierr = VecRestoreArray(pcpatch->patchStateWithAll, &XWithAll);CHKERRQ(ierr);
70 ierr = VecRestoreArrayRead(x, &X);CHKERRQ(ierr);
71 ierr = ISRestoreIndices(pcpatch->dofMappingWithoutToWithAll[pt], &indices);CHKERRQ(ierr);
72
73 ierr = PCPatchComputeOperator_Internal(pc, pcpatch->patchStateWithAll, M, pcpatch->currentPatch, PETSC_FALSE);CHKERRQ(ierr);
74 PetscFunctionReturn(0);
75 }
76
PCSetUp_PATCH_Nonlinear(PC pc)77 static PetscErrorCode PCSetUp_PATCH_Nonlinear(PC pc)
78 {
79 PC_PATCH *patch = (PC_PATCH *) pc->data;
80 const char *prefix;
81 PetscInt i, pStart, dof, maxDof = -1;
82 PetscErrorCode ierr;
83
84 PetscFunctionBegin;
85 if (!pc->setupcalled) {
86 ierr = PetscMalloc1(patch->npatch, &patch->solver);CHKERRQ(ierr);
87 ierr = PCGetOptionsPrefix(pc, &prefix);CHKERRQ(ierr);
88 ierr = PetscSectionGetChart(patch->gtolCounts, &pStart, NULL);CHKERRQ(ierr);
89 for (i = 0; i < patch->npatch; ++i) {
90 SNES snes;
91
92 ierr = SNESCreate(PETSC_COMM_SELF, &snes);CHKERRQ(ierr);
93 ierr = SNESSetOptionsPrefix(snes, prefix);CHKERRQ(ierr);
94 ierr = SNESAppendOptionsPrefix(snes, "sub_");CHKERRQ(ierr);
95 ierr = PetscObjectIncrementTabLevel((PetscObject) snes, (PetscObject) pc, 2);CHKERRQ(ierr);
96 ierr = PetscLogObjectParent((PetscObject) pc, (PetscObject) snes);CHKERRQ(ierr);
97 patch->solver[i] = (PetscObject) snes;
98
99 ierr = PetscSectionGetDof(patch->gtolCountsWithAll, i+pStart, &dof);CHKERRQ(ierr);
100 maxDof = PetscMax(maxDof, dof);
101 }
102 ierr = VecDuplicate(patch->localUpdate, &patch->localState);CHKERRQ(ierr);
103 ierr = VecDuplicate(patch->patchRHS, &patch->patchResidual);CHKERRQ(ierr);
104 ierr = VecDuplicate(patch->patchUpdate, &patch->patchState);CHKERRQ(ierr);
105
106 ierr = VecCreateSeq(PETSC_COMM_SELF, maxDof, &patch->patchStateWithAll);CHKERRQ(ierr);
107 ierr = VecSetUp(patch->patchStateWithAll);CHKERRQ(ierr);
108 }
109 for (i = 0; i < patch->npatch; ++i) {
110 SNES snes = (SNES) patch->solver[i];
111
112 ierr = SNESSetFunction(snes, patch->patchResidual, SNESPatchComputeResidual_Private, pc);CHKERRQ(ierr);
113 ierr = SNESSetJacobian(snes, patch->mat[i], patch->mat[i], SNESPatchComputeJacobian_Private, pc);CHKERRQ(ierr);
114 }
115 if (!pc->setupcalled && patch->optionsSet) for (i = 0; i < patch->npatch; ++i) {ierr = SNESSetFromOptions((SNES) patch->solver[i]);CHKERRQ(ierr);}
116 PetscFunctionReturn(0);
117 }
118
PCApply_PATCH_Nonlinear(PC pc,PetscInt i,Vec patchRHS,Vec patchUpdate)119 static PetscErrorCode PCApply_PATCH_Nonlinear(PC pc, PetscInt i, Vec patchRHS, Vec patchUpdate)
120 {
121 PC_PATCH *patch = (PC_PATCH *) pc->data;
122 PetscInt pStart, n;
123 PetscErrorCode ierr;
124
125 PetscFunctionBegin;
126 patch->currentPatch = i;
127 ierr = PetscLogEventBegin(PC_Patch_Solve, pc, 0, 0, 0);CHKERRQ(ierr);
128
129 /* Scatter the overlapped global state to our patch state vector */
130 ierr = PetscSectionGetChart(patch->gtolCounts, &pStart, NULL);CHKERRQ(ierr);
131 ierr = PCPatch_ScatterLocal_Private(pc, i+pStart, patch->localState, patch->patchState, INSERT_VALUES, SCATTER_FORWARD, SCATTER_INTERIOR);CHKERRQ(ierr);
132 ierr = PCPatch_ScatterLocal_Private(pc, i+pStart, patch->localState, patch->patchStateWithAll, INSERT_VALUES, SCATTER_FORWARD, SCATTER_WITHALL);CHKERRQ(ierr);
133
134 ierr = MatGetLocalSize(patch->mat[i], NULL, &n);CHKERRQ(ierr);
135 patch->patchState->map->n = n;
136 patch->patchState->map->N = n;
137 patchUpdate->map->n = n;
138 patchUpdate->map->N = n;
139 patchRHS->map->n = n;
140 patchRHS->map->N = n;
141 /* Set initial guess to be current state*/
142 ierr = VecCopy(patch->patchState, patchUpdate);CHKERRQ(ierr);
143 /* Solve for new state */
144 ierr = SNESSolve((SNES) patch->solver[i], patchRHS, patchUpdate);CHKERRQ(ierr);
145 /* To compute update, subtract off previous state */
146 ierr = VecAXPY(patchUpdate, -1.0, patch->patchState);CHKERRQ(ierr);
147
148 ierr = PetscLogEventEnd(PC_Patch_Solve, pc, 0, 0, 0);CHKERRQ(ierr);
149 PetscFunctionReturn(0);
150 }
151
PCReset_PATCH_Nonlinear(PC pc)152 static PetscErrorCode PCReset_PATCH_Nonlinear(PC pc)
153 {
154 PC_PATCH *patch = (PC_PATCH *) pc->data;
155 PetscInt i;
156 PetscErrorCode ierr;
157
158 PetscFunctionBegin;
159 if (patch->solver) {
160 for (i = 0; i < patch->npatch; ++i) {ierr = SNESReset((SNES) patch->solver[i]);CHKERRQ(ierr);}
161 }
162
163 ierr = VecDestroy(&patch->patchResidual);CHKERRQ(ierr);
164 ierr = VecDestroy(&patch->patchState);CHKERRQ(ierr);
165 ierr = VecDestroy(&patch->patchStateWithAll);CHKERRQ(ierr);
166
167 ierr = VecDestroy(&patch->localState);CHKERRQ(ierr);
168 PetscFunctionReturn(0);
169 }
170
PCDestroy_PATCH_Nonlinear(PC pc)171 static PetscErrorCode PCDestroy_PATCH_Nonlinear(PC pc)
172 {
173 PC_PATCH *patch = (PC_PATCH *) pc->data;
174 PetscInt i;
175 PetscErrorCode ierr;
176
177 PetscFunctionBegin;
178 if (patch->solver) {
179 for (i = 0; i < patch->npatch; ++i) {ierr = SNESDestroy((SNES *) &patch->solver[i]);CHKERRQ(ierr);}
180 ierr = PetscFree(patch->solver);CHKERRQ(ierr);
181 }
182 PetscFunctionReturn(0);
183 }
184
PCUpdateMultiplicative_PATCH_Nonlinear(PC pc,PetscInt i,PetscInt pStart)185 static PetscErrorCode PCUpdateMultiplicative_PATCH_Nonlinear(PC pc, PetscInt i, PetscInt pStart)
186 {
187 PC_PATCH *patch = (PC_PATCH *) pc->data;
188 PetscErrorCode ierr;
189
190 PetscFunctionBegin;
191 ierr = PCPatch_ScatterLocal_Private(pc, i + pStart, patch->patchUpdate, patch->localState, ADD_VALUES, SCATTER_REVERSE, SCATTER_INTERIOR);CHKERRQ(ierr);
192 PetscFunctionReturn(0);
193 }
194
SNESSetUp_Patch(SNES snes)195 static PetscErrorCode SNESSetUp_Patch(SNES snes)
196 {
197 SNES_Patch *patch = (SNES_Patch *) snes->data;
198 DM dm;
199 Mat dummy;
200 Vec F;
201 PetscInt n, N;
202 PetscErrorCode ierr;
203
204 PetscFunctionBegin;
205 ierr = SNESGetDM(snes, &dm);CHKERRQ(ierr);
206 ierr = PCSetDM(patch->pc, dm);CHKERRQ(ierr);
207 ierr = SNESGetFunction(snes, &F, NULL, NULL);CHKERRQ(ierr);
208 ierr = VecGetLocalSize(F, &n);CHKERRQ(ierr);
209 ierr = VecGetSize(F, &N);CHKERRQ(ierr);
210 ierr = MatCreateShell(PetscObjectComm((PetscObject) snes), n, n, N, N, (void *) snes, &dummy);CHKERRQ(ierr);
211 ierr = PCSetOperators(patch->pc, dummy, dummy);CHKERRQ(ierr);
212 ierr = MatDestroy(&dummy);CHKERRQ(ierr);
213 ierr = PCSetUp(patch->pc);CHKERRQ(ierr);
214 /* allocate workspace */
215 PetscFunctionReturn(0);
216 }
217
SNESReset_Patch(SNES snes)218 static PetscErrorCode SNESReset_Patch(SNES snes)
219 {
220 SNES_Patch *patch = (SNES_Patch *) snes->data;
221 PetscErrorCode ierr;
222
223 PetscFunctionBegin;
224 ierr = PCReset(patch->pc);CHKERRQ(ierr);
225 PetscFunctionReturn(0);
226 }
227
SNESDestroy_Patch(SNES snes)228 static PetscErrorCode SNESDestroy_Patch(SNES snes)
229 {
230 SNES_Patch *patch = (SNES_Patch *) snes->data;
231 PetscErrorCode ierr;
232
233 PetscFunctionBegin;
234 ierr = SNESReset_Patch(snes);CHKERRQ(ierr);
235 ierr = PCDestroy(&patch->pc);CHKERRQ(ierr);
236 ierr = PetscFree(snes->data);CHKERRQ(ierr);
237 PetscFunctionReturn(0);
238 }
239
SNESSetFromOptions_Patch(PetscOptionItems * PetscOptionsObject,SNES snes)240 static PetscErrorCode SNESSetFromOptions_Patch(PetscOptionItems *PetscOptionsObject, SNES snes)
241 {
242 SNES_Patch *patch = (SNES_Patch *) snes->data;
243 const char *prefix;
244 PetscErrorCode ierr;
245
246 PetscFunctionBegin;
247 ierr = PetscObjectGetOptionsPrefix((PetscObject)snes, &prefix);CHKERRQ(ierr);
248 ierr = PetscObjectSetOptionsPrefix((PetscObject)patch->pc, prefix);CHKERRQ(ierr);
249 ierr = PCSetFromOptions(patch->pc);CHKERRQ(ierr);
250 PetscFunctionReturn(0);
251 }
252
SNESView_Patch(SNES snes,PetscViewer viewer)253 static PetscErrorCode SNESView_Patch(SNES snes,PetscViewer viewer)
254 {
255 SNES_Patch *patch = (SNES_Patch *) snes->data;
256 PetscBool iascii;
257 PetscErrorCode ierr;
258
259 PetscFunctionBegin;
260 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
261 if (iascii) {
262 ierr = PetscViewerASCIIPrintf(viewer,"SNESPATCH\n");CHKERRQ(ierr);
263 }
264 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
265 ierr = PCView(patch->pc, viewer);CHKERRQ(ierr);
266 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
267 PetscFunctionReturn(0);
268 }
269
SNESSolve_Patch(SNES snes)270 static PetscErrorCode SNESSolve_Patch(SNES snes)
271 {
272 SNES_Patch *patch = (SNES_Patch *) snes->data;
273 PC_PATCH *pcpatch = (PC_PATCH *) patch->pc->data;
274 SNESLineSearch ls;
275 Vec rhs, update, state, residual;
276 const PetscScalar *globalState = NULL;
277 PetscScalar *localState = NULL;
278 PetscInt its = 0;
279 PetscReal xnorm = 0.0, ynorm = 0.0, fnorm = 0.0;
280 PetscErrorCode ierr;
281
282 PetscFunctionBegin;
283 ierr = SNESGetSolution(snes, &state);CHKERRQ(ierr);
284 ierr = SNESGetSolutionUpdate(snes, &update);CHKERRQ(ierr);
285 ierr = SNESGetRhs(snes, &rhs);CHKERRQ(ierr);
286
287 ierr = SNESGetFunction(snes, &residual, NULL, NULL);CHKERRQ(ierr);
288 ierr = SNESGetLineSearch(snes, &ls);CHKERRQ(ierr);
289
290 ierr = SNESSetConvergedReason(snes, SNES_CONVERGED_ITERATING);CHKERRQ(ierr);
291 ierr = VecSet(update, 0.0);CHKERRQ(ierr);
292 ierr = SNESComputeFunction(snes, state, residual);CHKERRQ(ierr);
293
294 ierr = VecNorm(state, NORM_2, &xnorm);CHKERRQ(ierr);
295 ierr = VecNorm(residual, NORM_2, &fnorm);CHKERRQ(ierr);
296 snes->ttol = fnorm*snes->rtol;
297
298 if (snes->ops->converged) {
299 ierr = (*snes->ops->converged)(snes,its,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
300 } else {
301 ierr = SNESConvergedSkip(snes,its,xnorm,ynorm,fnorm,&snes->reason,NULL);CHKERRQ(ierr);
302 }
303 ierr = SNESLogConvergenceHistory(snes, fnorm, 0);CHKERRQ(ierr); /* should we count lits from the patches? */
304 ierr = SNESMonitor(snes, its, fnorm);CHKERRQ(ierr);
305
306 /* The main solver loop */
307 for (its = 0; its < snes->max_its; its++) {
308
309 ierr = SNESSetIterationNumber(snes, its);CHKERRQ(ierr);
310
311 /* Scatter state vector to overlapped vector on all patches.
312 The vector pcpatch->localState is scattered to each patch
313 in PCApply_PATCH_Nonlinear. */
314 ierr = VecGetArrayRead(state, &globalState);CHKERRQ(ierr);
315 ierr = VecGetArray(pcpatch->localState, &localState);CHKERRQ(ierr);
316 ierr = PetscSFBcastBegin(pcpatch->sectionSF, MPIU_SCALAR, globalState, localState);CHKERRQ(ierr);
317 ierr = PetscSFBcastEnd(pcpatch->sectionSF, MPIU_SCALAR, globalState, localState);CHKERRQ(ierr);
318 ierr = VecRestoreArray(pcpatch->localState, &localState);CHKERRQ(ierr);
319 ierr = VecRestoreArrayRead(state, &globalState);CHKERRQ(ierr);
320
321 /* The looping over patches happens here */
322 ierr = PCApply(patch->pc, rhs, update);CHKERRQ(ierr);
323
324 /* Apply a line search. This will often be basic with
325 damping = 1/(max number of patches a dof can be in),
326 but not always */
327 ierr = VecScale(update, -1.0);CHKERRQ(ierr);
328 ierr = SNESLineSearchApply(ls, state, residual, &fnorm, update);CHKERRQ(ierr);
329
330 ierr = VecNorm(state, NORM_2, &xnorm);CHKERRQ(ierr);
331 ierr = VecNorm(update, NORM_2, &ynorm);CHKERRQ(ierr);
332
333 if (snes->ops->converged) {
334 ierr = (*snes->ops->converged)(snes,its,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
335 } else {
336 ierr = SNESConvergedSkip(snes,its,xnorm,ynorm,fnorm,&snes->reason,NULL);CHKERRQ(ierr);
337 }
338 ierr = SNESLogConvergenceHistory(snes, fnorm, 0);CHKERRQ(ierr); /* FIXME: should we count lits? */
339 ierr = SNESMonitor(snes, its, fnorm);CHKERRQ(ierr);
340 }
341
342 if (its == snes->max_its) { ierr = SNESSetConvergedReason(snes, SNES_DIVERGED_MAX_IT);CHKERRQ(ierr); }
343 PetscFunctionReturn(0);
344 }
345
346 /*MC
347 SNESPATCH - Solve a nonlinear problem by composing together many nonlinear solvers on patches
348
349 Level: intermediate
350
351 .seealso: SNESCreate(), SNESSetType(), SNESType (for list of available types), SNES,
352 PCPATCH
353
354 References:
355 . 1. - Peter R. Brune, Matthew G. Knepley, Barry F. Smith, and Xuemin Tu, "Composing Scalable Nonlinear Algebraic Solvers", SIAM Review, 57(4), 2015
356
357 M*/
SNESCreate_Patch(SNES snes)358 PETSC_EXTERN PetscErrorCode SNESCreate_Patch(SNES snes)
359 {
360 PetscErrorCode ierr;
361 SNES_Patch *patch;
362 PC_PATCH *patchpc;
363 SNESLineSearch linesearch;
364
365 PetscFunctionBegin;
366 ierr = PetscNewLog(snes, &patch);CHKERRQ(ierr);
367
368 snes->ops->solve = SNESSolve_Patch;
369 snes->ops->setup = SNESSetUp_Patch;
370 snes->ops->reset = SNESReset_Patch;
371 snes->ops->destroy = SNESDestroy_Patch;
372 snes->ops->setfromoptions = SNESSetFromOptions_Patch;
373 snes->ops->view = SNESView_Patch;
374
375 ierr = SNESGetLineSearch(snes,&linesearch);CHKERRQ(ierr);
376 if (!((PetscObject)linesearch)->type_name) {
377 ierr = SNESLineSearchSetType(linesearch,SNESLINESEARCHBASIC);CHKERRQ(ierr);
378 }
379 snes->usesksp = PETSC_FALSE;
380
381 snes->alwayscomputesfinalresidual = PETSC_FALSE;
382
383 snes->data = (void *) patch;
384 ierr = PCCreate(PetscObjectComm((PetscObject) snes), &patch->pc);CHKERRQ(ierr);
385 ierr = PCSetType(patch->pc, PCPATCH);CHKERRQ(ierr);
386
387 patchpc = (PC_PATCH*) patch->pc->data;
388 patchpc->classname = "snes";
389 patchpc->isNonlinear = PETSC_TRUE;
390
391 patchpc->setupsolver = PCSetUp_PATCH_Nonlinear;
392 patchpc->applysolver = PCApply_PATCH_Nonlinear;
393 patchpc->resetsolver = PCReset_PATCH_Nonlinear;
394 patchpc->destroysolver = PCDestroy_PATCH_Nonlinear;
395 patchpc->updatemultiplicative = PCUpdateMultiplicative_PATCH_Nonlinear;
396
397 PetscFunctionReturn(0);
398 }
399
SNESPatchSetDiscretisationInfo(SNES snes,PetscInt nsubspaces,DM * dms,PetscInt * bs,PetscInt * nodesPerCell,const PetscInt ** cellNodeMap,const PetscInt * subspaceOffsets,PetscInt numGhostBcs,const PetscInt * ghostBcNodes,PetscInt numGlobalBcs,const PetscInt * globalBcNodes)400 PetscErrorCode SNESPatchSetDiscretisationInfo(SNES snes, PetscInt nsubspaces, DM *dms, PetscInt *bs, PetscInt *nodesPerCell, const PetscInt **cellNodeMap,
401 const PetscInt *subspaceOffsets, PetscInt numGhostBcs, const PetscInt *ghostBcNodes, PetscInt numGlobalBcs, const PetscInt *globalBcNodes)
402 {
403 SNES_Patch *patch = (SNES_Patch *) snes->data;
404 PetscErrorCode ierr;
405 DM dm;
406
407 PetscFunctionBegin;
408 ierr = SNESGetDM(snes, &dm);CHKERRQ(ierr);
409 if (!dm) SETERRQ(PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONGSTATE, "DM not yet set on patch SNES\n");
410 ierr = PCSetDM(patch->pc, dm);CHKERRQ(ierr);
411 ierr = PCPatchSetDiscretisationInfo(patch->pc, nsubspaces, dms, bs, nodesPerCell, cellNodeMap, subspaceOffsets, numGhostBcs, ghostBcNodes, numGlobalBcs, globalBcNodes);CHKERRQ(ierr);
412 PetscFunctionReturn(0);
413 }
414
SNESPatchSetComputeOperator(SNES snes,PetscErrorCode (* func)(PC,PetscInt,Vec,Mat,IS,PetscInt,const PetscInt *,const PetscInt *,void *),void * ctx)415 PetscErrorCode SNESPatchSetComputeOperator(SNES snes, PetscErrorCode (*func)(PC, PetscInt, Vec, Mat, IS, PetscInt, const PetscInt *, const PetscInt *, void *), void *ctx)
416 {
417 SNES_Patch *patch = (SNES_Patch *) snes->data;
418 PetscErrorCode ierr;
419
420 PetscFunctionBegin;
421 ierr = PCPatchSetComputeOperator(patch->pc, func, ctx);CHKERRQ(ierr);
422 PetscFunctionReturn(0);
423 }
424
SNESPatchSetComputeFunction(SNES snes,PetscErrorCode (* func)(PC,PetscInt,Vec,Vec,IS,PetscInt,const PetscInt *,const PetscInt *,void *),void * ctx)425 PetscErrorCode SNESPatchSetComputeFunction(SNES snes, PetscErrorCode (*func)(PC, PetscInt, Vec, Vec, IS, PetscInt, const PetscInt *, const PetscInt *, void *), void *ctx)
426 {
427 SNES_Patch *patch = (SNES_Patch *) snes->data;
428 PetscErrorCode ierr;
429
430 PetscFunctionBegin;
431 ierr = PCPatchSetComputeFunction(patch->pc, func, ctx);CHKERRQ(ierr);
432 PetscFunctionReturn(0);
433 }
434
SNESPatchSetConstructType(SNES snes,PCPatchConstructType ctype,PetscErrorCode (* func)(PC,PetscInt *,IS **,IS *,void *),void * ctx)435 PetscErrorCode SNESPatchSetConstructType(SNES snes, PCPatchConstructType ctype, PetscErrorCode (*func)(PC, PetscInt *, IS **, IS *, void *), void *ctx)
436 {
437 SNES_Patch *patch = (SNES_Patch *) snes->data;
438 PetscErrorCode ierr;
439
440 PetscFunctionBegin;
441 ierr = PCPatchSetConstructType(patch->pc, ctype, func, ctx);CHKERRQ(ierr);
442 PetscFunctionReturn(0);
443 }
444
SNESPatchSetCellNumbering(SNES snes,PetscSection cellNumbering)445 PetscErrorCode SNESPatchSetCellNumbering(SNES snes, PetscSection cellNumbering)
446 {
447 SNES_Patch *patch = (SNES_Patch *) snes->data;
448 PetscErrorCode ierr;
449
450 PetscFunctionBegin;
451 ierr = PCPatchSetCellNumbering(patch->pc, cellNumbering);CHKERRQ(ierr);
452 PetscFunctionReturn(0);
453 }
454