xref: /petsc/src/snes/impls/patch/snespatch.c (revision 3ba1676111f5c958fe6c2729b46ca4d523958bb3)
1561742edSMatthew G. Knepley /*
2561742edSMatthew G. Knepley       Defines a SNES that can consist of a collection of SNESes on patches of the domain
3561742edSMatthew G. Knepley */
4917d05d1SLawrence Mitchell #include <petsc/private/vecimpl.h>     /* For vec->map */
5561742edSMatthew G. Knepley #include <petsc/private/snesimpl.h>    /*I "petscsnes.h" I*/
6561742edSMatthew G. Knepley #include <petsc/private/pcpatchimpl.h> /* We need internal access to PCPatch right now, until that part is moved to Plex */
71202d238SPatrick Farrell #include <petscsf.h>
8ea844a1aSMatthew Knepley #include <petscsection.h>
9561742edSMatthew G. Knepley 
10561742edSMatthew G. Knepley typedef struct {
11561742edSMatthew G. Knepley   PC pc; /* The linear patch preconditioner */
12561742edSMatthew G. Knepley } SNES_Patch;
13561742edSMatthew G. Knepley 
14d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESPatchComputeResidual_Private(SNES snes, Vec x, Vec F, void *ctx)
15d71ae5a4SJacob Faibussowitsch {
16ab270f91SPatrick Farrell   PC                 pc      = (PC)ctx;
17ab270f91SPatrick Farrell   PC_PATCH          *pcpatch = (PC_PATCH *)pc->data;
1887050cfdSPatrick Farrell   PetscInt           pt, size, i;
1939fd2e8aSPatrick Farrell   const PetscInt    *indices;
2039fd2e8aSPatrick Farrell   const PetscScalar *X;
210904074fSPatrick Farrell   PetscScalar       *XWithAll;
22561742edSMatthew G. Knepley 
23561742edSMatthew G. Knepley   PetscFunctionBegin;
2439fd2e8aSPatrick Farrell 
250904074fSPatrick Farrell   /* scatter from x to patch->patchStateWithAll[pt] */
2639fd2e8aSPatrick Farrell   pt = pcpatch->currentPatch;
279566063dSJacob Faibussowitsch   PetscCall(ISGetSize(pcpatch->dofMappingWithoutToWithAll[pt], &size));
2839fd2e8aSPatrick Farrell 
299566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(pcpatch->dofMappingWithoutToWithAll[pt], &indices));
309566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(x, &X));
319566063dSJacob Faibussowitsch   PetscCall(VecGetArray(pcpatch->patchStateWithAll, &XWithAll));
3239fd2e8aSPatrick Farrell 
33ad540459SPierre Jolivet   for (i = 0; i < size; ++i) XWithAll[indices[i]] = X[i];
3439fd2e8aSPatrick Farrell 
359566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(pcpatch->patchStateWithAll, &XWithAll));
369566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(x, &X));
379566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(pcpatch->dofMappingWithoutToWithAll[pt], &indices));
3839fd2e8aSPatrick Farrell 
399566063dSJacob Faibussowitsch   PetscCall(PCPatchComputeFunction_Internal(pc, pcpatch->patchStateWithAll, F, pt));
40*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
41561742edSMatthew G. Knepley }
42561742edSMatthew G. Knepley 
43d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESPatchComputeJacobian_Private(SNES snes, Vec x, Mat J, Mat M, void *ctx)
44d71ae5a4SJacob Faibussowitsch {
45ab270f91SPatrick Farrell   PC                 pc      = (PC)ctx;
46ab270f91SPatrick Farrell   PC_PATCH          *pcpatch = (PC_PATCH *)pc->data;
4787050cfdSPatrick Farrell   PetscInt           pt, size, i;
484d04e9f1SPatrick Farrell   const PetscInt    *indices;
494d04e9f1SPatrick Farrell   const PetscScalar *X;
500904074fSPatrick Farrell   PetscScalar       *XWithAll;
51561742edSMatthew G. Knepley 
52561742edSMatthew G. Knepley   PetscFunctionBegin;
530904074fSPatrick Farrell   /* scatter from x to patch->patchStateWithAll[pt] */
544d04e9f1SPatrick Farrell   pt = pcpatch->currentPatch;
559566063dSJacob Faibussowitsch   PetscCall(ISGetSize(pcpatch->dofMappingWithoutToWithAll[pt], &size));
564d04e9f1SPatrick Farrell 
579566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(pcpatch->dofMappingWithoutToWithAll[pt], &indices));
589566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(x, &X));
599566063dSJacob Faibussowitsch   PetscCall(VecGetArray(pcpatch->patchStateWithAll, &XWithAll));
604d04e9f1SPatrick Farrell 
61ad540459SPierre Jolivet   for (i = 0; i < size; ++i) XWithAll[indices[i]] = X[i];
624d04e9f1SPatrick Farrell 
639566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(pcpatch->patchStateWithAll, &XWithAll));
649566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(x, &X));
659566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(pcpatch->dofMappingWithoutToWithAll[pt], &indices));
664d04e9f1SPatrick Farrell 
679566063dSJacob Faibussowitsch   PetscCall(PCPatchComputeOperator_Internal(pc, pcpatch->patchStateWithAll, M, pcpatch->currentPatch, PETSC_FALSE));
68*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
69561742edSMatthew G. Knepley }
70561742edSMatthew G. Knepley 
71d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetUp_PATCH_Nonlinear(PC pc)
72d71ae5a4SJacob Faibussowitsch {
73561742edSMatthew G. Knepley   PC_PATCH   *patch = (PC_PATCH *)pc->data;
74561742edSMatthew G. Knepley   const char *prefix;
759d4fc724SLawrence Mitchell   PetscInt    i, pStart, dof, maxDof = -1;
76561742edSMatthew G. Knepley 
77561742edSMatthew G. Knepley   PetscFunctionBegin;
78561742edSMatthew G. Knepley   if (!pc->setupcalled) {
799566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(patch->npatch, &patch->solver));
809566063dSJacob Faibussowitsch     PetscCall(PCGetOptionsPrefix(pc, &prefix));
819566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(patch->gtolCounts, &pStart, NULL));
82561742edSMatthew G. Knepley     for (i = 0; i < patch->npatch; ++i) {
83561742edSMatthew G. Knepley       SNES snes;
84561742edSMatthew G. Knepley 
859566063dSJacob Faibussowitsch       PetscCall(SNESCreate(PETSC_COMM_SELF, &snes));
869566063dSJacob Faibussowitsch       PetscCall(SNESSetOptionsPrefix(snes, prefix));
879566063dSJacob Faibussowitsch       PetscCall(SNESAppendOptionsPrefix(snes, "sub_"));
889566063dSJacob Faibussowitsch       PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes, (PetscObject)pc, 2));
89561742edSMatthew G. Knepley       patch->solver[i] = (PetscObject)snes;
9039fd2e8aSPatrick Farrell 
919566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(patch->gtolCountsWithAll, i + pStart, &dof));
929d4fc724SLawrence Mitchell       maxDof = PetscMax(maxDof, dof);
931202d238SPatrick Farrell     }
949566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(patch->localUpdate, &patch->localState));
959566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(patch->patchRHS, &patch->patchResidual));
969566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(patch->patchUpdate, &patch->patchState));
979d4fc724SLawrence Mitchell 
989566063dSJacob Faibussowitsch     PetscCall(VecCreateSeq(PETSC_COMM_SELF, maxDof, &patch->patchStateWithAll));
999566063dSJacob Faibussowitsch     PetscCall(VecSetUp(patch->patchStateWithAll));
100561742edSMatthew G. Knepley   }
101561742edSMatthew G. Knepley   for (i = 0; i < patch->npatch; ++i) {
102561742edSMatthew G. Knepley     SNES snes = (SNES)patch->solver[i];
103561742edSMatthew G. Knepley 
1049566063dSJacob Faibussowitsch     PetscCall(SNESSetFunction(snes, patch->patchResidual, SNESPatchComputeResidual_Private, pc));
1059566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, patch->mat[i], patch->mat[i], SNESPatchComputeJacobian_Private, pc));
106561742edSMatthew G. Knepley   }
1079371c9d4SSatish Balay   if (!pc->setupcalled && patch->optionsSet)
1089371c9d4SSatish Balay     for (i = 0; i < patch->npatch; ++i) PetscCall(SNESSetFromOptions((SNES)patch->solver[i]));
109*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
110561742edSMatthew G. Knepley }
111561742edSMatthew G. Knepley 
112d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApply_PATCH_Nonlinear(PC pc, PetscInt i, Vec patchRHS, Vec patchUpdate)
113d71ae5a4SJacob Faibussowitsch {
114561742edSMatthew G. Knepley   PC_PATCH *patch = (PC_PATCH *)pc->data;
115917d05d1SLawrence Mitchell   PetscInt  pStart, n;
116561742edSMatthew G. Knepley 
117561742edSMatthew G. Knepley   PetscFunctionBegin;
118561742edSMatthew G. Knepley   patch->currentPatch = i;
1199566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_Patch_Solve, pc, 0, 0, 0));
1201202d238SPatrick Farrell 
1211202d238SPatrick Farrell   /* Scatter the overlapped global state to our patch state vector */
1229566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(patch->gtolCounts, &pStart, NULL));
1239566063dSJacob Faibussowitsch   PetscCall(PCPatch_ScatterLocal_Private(pc, i + pStart, patch->localState, patch->patchState, INSERT_VALUES, SCATTER_FORWARD, SCATTER_INTERIOR));
1249566063dSJacob Faibussowitsch   PetscCall(PCPatch_ScatterLocal_Private(pc, i + pStart, patch->localState, patch->patchStateWithAll, INSERT_VALUES, SCATTER_FORWARD, SCATTER_WITHALL));
1251202d238SPatrick Farrell 
1269566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(patch->mat[i], NULL, &n));
127917d05d1SLawrence Mitchell   patch->patchState->map->n = n;
128917d05d1SLawrence Mitchell   patch->patchState->map->N = n;
129917d05d1SLawrence Mitchell   patchUpdate->map->n       = n;
130917d05d1SLawrence Mitchell   patchUpdate->map->N       = n;
131917d05d1SLawrence Mitchell   patchRHS->map->n          = n;
132917d05d1SLawrence Mitchell   patchRHS->map->N          = n;
1331202d238SPatrick Farrell   /* Set initial guess to be current state*/
1349566063dSJacob Faibussowitsch   PetscCall(VecCopy(patch->patchState, patchUpdate));
1351202d238SPatrick Farrell   /* Solve for new state */
1369566063dSJacob Faibussowitsch   PetscCall(SNESSolve((SNES)patch->solver[i], patchRHS, patchUpdate));
1371202d238SPatrick Farrell   /* To compute update, subtract off previous state */
1389566063dSJacob Faibussowitsch   PetscCall(VecAXPY(patchUpdate, -1.0, patch->patchState));
1391202d238SPatrick Farrell 
1409566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_Patch_Solve, pc, 0, 0, 0));
141*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
142561742edSMatthew G. Knepley }
143561742edSMatthew G. Knepley 
144d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCReset_PATCH_Nonlinear(PC pc)
145d71ae5a4SJacob Faibussowitsch {
146561742edSMatthew G. Knepley   PC_PATCH *patch = (PC_PATCH *)pc->data;
147561742edSMatthew G. Knepley   PetscInt  i;
148561742edSMatthew G. Knepley 
149561742edSMatthew G. Knepley   PetscFunctionBegin;
150561742edSMatthew G. Knepley   if (patch->solver) {
1519566063dSJacob Faibussowitsch     for (i = 0; i < patch->npatch; ++i) PetscCall(SNESReset((SNES)patch->solver[i]));
152561742edSMatthew G. Knepley   }
1531202d238SPatrick Farrell 
1549566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&patch->patchResidual));
1559566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&patch->patchState));
1569566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&patch->patchStateWithAll));
15739fd2e8aSPatrick Farrell 
1589566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&patch->localState));
159*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
160561742edSMatthew G. Knepley }
161561742edSMatthew G. Knepley 
162d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCDestroy_PATCH_Nonlinear(PC pc)
163d71ae5a4SJacob Faibussowitsch {
164561742edSMatthew G. Knepley   PC_PATCH *patch = (PC_PATCH *)pc->data;
165561742edSMatthew G. Knepley   PetscInt  i;
166561742edSMatthew G. Knepley 
167561742edSMatthew G. Knepley   PetscFunctionBegin;
168561742edSMatthew G. Knepley   if (patch->solver) {
1699566063dSJacob Faibussowitsch     for (i = 0; i < patch->npatch; ++i) PetscCall(SNESDestroy((SNES *)&patch->solver[i]));
1709566063dSJacob Faibussowitsch     PetscCall(PetscFree(patch->solver));
171561742edSMatthew G. Knepley   }
172*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
173561742edSMatthew G. Knepley }
174561742edSMatthew G. Knepley 
175d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCUpdateMultiplicative_PATCH_Nonlinear(PC pc, PetscInt i, PetscInt pStart)
176d71ae5a4SJacob Faibussowitsch {
1776c9c532dSPatrick Farrell   PC_PATCH *patch = (PC_PATCH *)pc->data;
1786c9c532dSPatrick Farrell 
1794d04e9f1SPatrick Farrell   PetscFunctionBegin;
1809566063dSJacob Faibussowitsch   PetscCall(PCPatch_ScatterLocal_Private(pc, i + pStart, patch->patchUpdate, patch->localState, ADD_VALUES, SCATTER_REVERSE, SCATTER_INTERIOR));
181*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1826c9c532dSPatrick Farrell }
1836c9c532dSPatrick Farrell 
184d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetUp_Patch(SNES snes)
185d71ae5a4SJacob Faibussowitsch {
186561742edSMatthew G. Knepley   SNES_Patch *patch = (SNES_Patch *)snes->data;
187561742edSMatthew G. Knepley   DM          dm;
188561742edSMatthew G. Knepley   Mat         dummy;
189561742edSMatthew G. Knepley   Vec         F;
190561742edSMatthew G. Knepley   PetscInt    n, N;
191561742edSMatthew G. Knepley 
192561742edSMatthew G. Knepley   PetscFunctionBegin;
1939566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
1949566063dSJacob Faibussowitsch   PetscCall(PCSetDM(patch->pc, dm));
1959566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &F, NULL, NULL));
1969566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(F, &n));
1979566063dSJacob Faibussowitsch   PetscCall(VecGetSize(F, &N));
1989566063dSJacob Faibussowitsch   PetscCall(MatCreateShell(PetscObjectComm((PetscObject)snes), n, n, N, N, (void *)snes, &dummy));
1999566063dSJacob Faibussowitsch   PetscCall(PCSetOperators(patch->pc, dummy, dummy));
2009566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&dummy));
2019566063dSJacob Faibussowitsch   PetscCall(PCSetUp(patch->pc));
202561742edSMatthew G. Knepley   /* allocate workspace */
203*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
204561742edSMatthew G. Knepley }
205561742edSMatthew G. Knepley 
206d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESReset_Patch(SNES snes)
207d71ae5a4SJacob Faibussowitsch {
208561742edSMatthew G. Knepley   SNES_Patch *patch = (SNES_Patch *)snes->data;
209561742edSMatthew G. Knepley 
210561742edSMatthew G. Knepley   PetscFunctionBegin;
2119566063dSJacob Faibussowitsch   PetscCall(PCReset(patch->pc));
212*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
213561742edSMatthew G. Knepley }
214561742edSMatthew G. Knepley 
215d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESDestroy_Patch(SNES snes)
216d71ae5a4SJacob Faibussowitsch {
217561742edSMatthew G. Knepley   SNES_Patch *patch = (SNES_Patch *)snes->data;
218561742edSMatthew G. Knepley 
219561742edSMatthew G. Knepley   PetscFunctionBegin;
2209566063dSJacob Faibussowitsch   PetscCall(SNESReset_Patch(snes));
2219566063dSJacob Faibussowitsch   PetscCall(PCDestroy(&patch->pc));
2229566063dSJacob Faibussowitsch   PetscCall(PetscFree(snes->data));
223*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
224561742edSMatthew G. Knepley }
225561742edSMatthew G. Knepley 
226d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetFromOptions_Patch(SNES snes, PetscOptionItems *PetscOptionsObject)
227d71ae5a4SJacob Faibussowitsch {
228561742edSMatthew G. Knepley   SNES_Patch *patch = (SNES_Patch *)snes->data;
2294aa795a7SPatrick Farrell   const char *prefix;
230561742edSMatthew G. Knepley 
231561742edSMatthew G. Knepley   PetscFunctionBegin;
2329566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)snes, &prefix));
2339566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)patch->pc, prefix));
2349566063dSJacob Faibussowitsch   PetscCall(PCSetFromOptions(patch->pc));
235*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
236561742edSMatthew G. Knepley }
237561742edSMatthew G. Knepley 
238d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESView_Patch(SNES snes, PetscViewer viewer)
239d71ae5a4SJacob Faibussowitsch {
240561742edSMatthew G. Knepley   SNES_Patch *patch = (SNES_Patch *)snes->data;
241561742edSMatthew G. Knepley   PetscBool   iascii;
242561742edSMatthew G. Knepley 
243561742edSMatthew G. Knepley   PetscFunctionBegin;
2449566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
24548a46eb9SPierre Jolivet   if (iascii) PetscCall(PetscViewerASCIIPrintf(viewer, "SNESPATCH\n"));
2469566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushTab(viewer));
2479566063dSJacob Faibussowitsch   PetscCall(PCView(patch->pc, viewer));
2489566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopTab(viewer));
249*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
250561742edSMatthew G. Knepley }
251561742edSMatthew G. Knepley 
252d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSolve_Patch(SNES snes)
253d71ae5a4SJacob Faibussowitsch {
254ab270f91SPatrick Farrell   SNES_Patch        *patch   = (SNES_Patch *)snes->data;
2551202d238SPatrick Farrell   PC_PATCH          *pcpatch = (PC_PATCH *)patch->pc->data;
256636c62a6SPatrick Farrell   SNESLineSearch     ls;
257636c62a6SPatrick Farrell   Vec                rhs, update, state, residual;
2581202d238SPatrick Farrell   const PetscScalar *globalState = NULL;
2591202d238SPatrick Farrell   PetscScalar       *localState  = NULL;
260636c62a6SPatrick Farrell   PetscInt           its         = 0;
261636c62a6SPatrick Farrell   PetscReal          xnorm = 0.0, ynorm = 0.0, fnorm = 0.0;
2624aa795a7SPatrick Farrell 
263561742edSMatthew G. Knepley   PetscFunctionBegin;
2649566063dSJacob Faibussowitsch   PetscCall(SNESGetSolution(snes, &state));
2659566063dSJacob Faibussowitsch   PetscCall(SNESGetSolutionUpdate(snes, &update));
2669566063dSJacob Faibussowitsch   PetscCall(SNESGetRhs(snes, &rhs));
2671202d238SPatrick Farrell 
2689566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &residual, NULL, NULL));
2699566063dSJacob Faibussowitsch   PetscCall(SNESGetLineSearch(snes, &ls));
270636c62a6SPatrick Farrell 
2719566063dSJacob Faibussowitsch   PetscCall(SNESSetConvergedReason(snes, SNES_CONVERGED_ITERATING));
2729566063dSJacob Faibussowitsch   PetscCall(VecSet(update, 0.0));
2739566063dSJacob Faibussowitsch   PetscCall(SNESComputeFunction(snes, state, residual));
274636c62a6SPatrick Farrell 
2759566063dSJacob Faibussowitsch   PetscCall(VecNorm(state, NORM_2, &xnorm));
2769566063dSJacob Faibussowitsch   PetscCall(VecNorm(residual, NORM_2, &fnorm));
277636c62a6SPatrick Farrell   snes->ttol = fnorm * snes->rtol;
278636c62a6SPatrick Farrell 
279636c62a6SPatrick Farrell   if (snes->ops->converged) {
280dbbe0bcdSBarry Smith     PetscUseTypeMethod(snes, converged, its, xnorm, ynorm, fnorm, &snes->reason, snes->cnvP);
281636c62a6SPatrick Farrell   } else {
2829566063dSJacob Faibussowitsch     PetscCall(SNESConvergedSkip(snes, its, xnorm, ynorm, fnorm, &snes->reason, NULL));
283636c62a6SPatrick Farrell   }
2849566063dSJacob Faibussowitsch   PetscCall(SNESLogConvergenceHistory(snes, fnorm, 0)); /* should we count lits from the patches? */
2859566063dSJacob Faibussowitsch   PetscCall(SNESMonitor(snes, its, fnorm));
286636c62a6SPatrick Farrell 
287636c62a6SPatrick Farrell   /* The main solver loop */
288636c62a6SPatrick Farrell   for (its = 0; its < snes->max_its; its++) {
2899566063dSJacob Faibussowitsch     PetscCall(SNESSetIterationNumber(snes, its));
290636c62a6SPatrick Farrell 
2911202d238SPatrick Farrell     /* Scatter state vector to overlapped vector on all patches.
2921202d238SPatrick Farrell        The vector pcpatch->localState is scattered to each patch
2931202d238SPatrick Farrell        in PCApply_PATCH_Nonlinear. */
2949566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(state, &globalState));
2959566063dSJacob Faibussowitsch     PetscCall(VecGetArray(pcpatch->localState, &localState));
2969566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(pcpatch->sectionSF, MPIU_SCALAR, globalState, localState, MPI_REPLACE));
2979566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(pcpatch->sectionSF, MPIU_SCALAR, globalState, localState, MPI_REPLACE));
2989566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(pcpatch->localState, &localState));
2999566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(state, &globalState));
3001202d238SPatrick Farrell 
301636c62a6SPatrick Farrell     /* The looping over patches happens here */
3029566063dSJacob Faibussowitsch     PetscCall(PCApply(patch->pc, rhs, update));
303636c62a6SPatrick Farrell 
304636c62a6SPatrick Farrell     /* Apply a line search. This will often be basic with
305636c62a6SPatrick Farrell        damping = 1/(max number of patches a dof can be in),
306636c62a6SPatrick Farrell        but not always */
3079566063dSJacob Faibussowitsch     PetscCall(VecScale(update, -1.0));
3089566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchApply(ls, state, residual, &fnorm, update));
309636c62a6SPatrick Farrell 
3109566063dSJacob Faibussowitsch     PetscCall(VecNorm(state, NORM_2, &xnorm));
3119566063dSJacob Faibussowitsch     PetscCall(VecNorm(update, NORM_2, &ynorm));
312636c62a6SPatrick Farrell 
313636c62a6SPatrick Farrell     if (snes->ops->converged) {
314dbbe0bcdSBarry Smith       PetscUseTypeMethod(snes, converged, its, xnorm, ynorm, fnorm, &snes->reason, snes->cnvP);
315636c62a6SPatrick Farrell     } else {
3169566063dSJacob Faibussowitsch       PetscCall(SNESConvergedSkip(snes, its, xnorm, ynorm, fnorm, &snes->reason, NULL));
317636c62a6SPatrick Farrell     }
3189566063dSJacob Faibussowitsch     PetscCall(SNESLogConvergenceHistory(snes, fnorm, 0)); /* FIXME: should we count lits? */
3199566063dSJacob Faibussowitsch     PetscCall(SNESMonitor(snes, its, fnorm));
3201202d238SPatrick Farrell   }
3211202d238SPatrick Farrell 
3229566063dSJacob Faibussowitsch   if (its == snes->max_its) PetscCall(SNESSetConvergedReason(snes, SNES_DIVERGED_MAX_IT));
323*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
324561742edSMatthew G. Knepley }
325561742edSMatthew G. Knepley 
326561742edSMatthew G. Knepley /*MC
327f6dfbefdSBarry Smith   SNESPATCH - Solve a nonlinear problem or apply a nonlinear smoother by composing together many nonlinear solvers on (often overlapping) patches
328561742edSMatthew G. Knepley 
329561742edSMatthew G. Knepley   Level: intermediate
330561742edSMatthew G. Knepley 
331561742edSMatthew G. Knepley    References:
332606c0280SSatish Balay .  * - Peter R. Brune, Matthew G. Knepley, Barry F. Smith, and Xuemin Tu, "Composing Scalable Nonlinear Algebraic Solvers", SIAM Review, 57(4), 2015
333561742edSMatthew G. Knepley 
334f6dfbefdSBarry Smith .seealso: `SNESFAS`, `SNESCreate()`, `SNESSetType()`, `SNESType`, `SNES`, `PCPATCH`
335561742edSMatthew G. Knepley M*/
336d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode SNESCreate_Patch(SNES snes)
337d71ae5a4SJacob Faibussowitsch {
338561742edSMatthew G. Knepley   SNES_Patch    *patch;
33910534d48SPatrick Farrell   PC_PATCH      *patchpc;
340d8d34be6SBarry Smith   SNESLineSearch linesearch;
341561742edSMatthew G. Knepley 
342561742edSMatthew G. Knepley   PetscFunctionBegin;
3434dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&patch));
344561742edSMatthew G. Knepley 
345561742edSMatthew G. Knepley   snes->ops->solve          = SNESSolve_Patch;
346561742edSMatthew G. Knepley   snes->ops->setup          = SNESSetUp_Patch;
347561742edSMatthew G. Knepley   snes->ops->reset          = SNESReset_Patch;
348561742edSMatthew G. Knepley   snes->ops->destroy        = SNESDestroy_Patch;
349561742edSMatthew G. Knepley   snes->ops->setfromoptions = SNESSetFromOptions_Patch;
350561742edSMatthew G. Knepley   snes->ops->view           = SNESView_Patch;
351561742edSMatthew G. Knepley 
3529566063dSJacob Faibussowitsch   PetscCall(SNESGetLineSearch(snes, &linesearch));
35348a46eb9SPierre Jolivet   if (!((PetscObject)linesearch)->type_name) PetscCall(SNESLineSearchSetType(linesearch, SNESLINESEARCHBASIC));
354d8d34be6SBarry Smith   snes->usesksp = PETSC_FALSE;
355d8d34be6SBarry Smith 
356561742edSMatthew G. Knepley   snes->alwayscomputesfinalresidual = PETSC_FALSE;
357561742edSMatthew G. Knepley 
358561742edSMatthew G. Knepley   snes->data = (void *)patch;
3599566063dSJacob Faibussowitsch   PetscCall(PCCreate(PetscObjectComm((PetscObject)snes), &patch->pc));
3609566063dSJacob Faibussowitsch   PetscCall(PCSetType(patch->pc, PCPATCH));
361561742edSMatthew G. Knepley 
36210534d48SPatrick Farrell   patchpc              = (PC_PATCH *)patch->pc->data;
36310534d48SPatrick Farrell   patchpc->classname   = "snes";
364debbdec3SPatrick Farrell   patchpc->isNonlinear = PETSC_TRUE;
36510534d48SPatrick Farrell 
36610534d48SPatrick Farrell   patchpc->setupsolver          = PCSetUp_PATCH_Nonlinear;
36710534d48SPatrick Farrell   patchpc->applysolver          = PCApply_PATCH_Nonlinear;
36810534d48SPatrick Farrell   patchpc->resetsolver          = PCReset_PATCH_Nonlinear;
36910534d48SPatrick Farrell   patchpc->destroysolver        = PCDestroy_PATCH_Nonlinear;
3706c9c532dSPatrick Farrell   patchpc->updatemultiplicative = PCUpdateMultiplicative_PATCH_Nonlinear;
371561742edSMatthew G. Knepley 
372*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
373561742edSMatthew G. Knepley }
3746c270751SPatrick Farrell 
375d71ae5a4SJacob Faibussowitsch PetscErrorCode 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)
376d71ae5a4SJacob Faibussowitsch {
3776c270751SPatrick Farrell   SNES_Patch *patch = (SNES_Patch *)snes->data;
378f08b3ad2SPatrick Farrell   DM          dm;
3796c270751SPatrick Farrell 
3806c270751SPatrick Farrell   PetscFunctionBegin;
3819566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
38228b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONGSTATE, "DM not yet set on patch SNES");
3839566063dSJacob Faibussowitsch   PetscCall(PCSetDM(patch->pc, dm));
3849566063dSJacob Faibussowitsch   PetscCall(PCPatchSetDiscretisationInfo(patch->pc, nsubspaces, dms, bs, nodesPerCell, cellNodeMap, subspaceOffsets, numGhostBcs, ghostBcNodes, numGlobalBcs, globalBcNodes));
385*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3866c270751SPatrick Farrell }
3876c270751SPatrick Farrell 
388d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPatchSetComputeOperator(SNES snes, PetscErrorCode (*func)(PC, PetscInt, Vec, Mat, IS, PetscInt, const PetscInt *, const PetscInt *, void *), void *ctx)
389d71ae5a4SJacob Faibussowitsch {
3906c270751SPatrick Farrell   SNES_Patch *patch = (SNES_Patch *)snes->data;
3916c270751SPatrick Farrell 
3926c270751SPatrick Farrell   PetscFunctionBegin;
3939566063dSJacob Faibussowitsch   PetscCall(PCPatchSetComputeOperator(patch->pc, func, ctx));
394*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3956c270751SPatrick Farrell }
3966c270751SPatrick Farrell 
397d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPatchSetComputeFunction(SNES snes, PetscErrorCode (*func)(PC, PetscInt, Vec, Vec, IS, PetscInt, const PetscInt *, const PetscInt *, void *), void *ctx)
398d71ae5a4SJacob Faibussowitsch {
3996c270751SPatrick Farrell   SNES_Patch *patch = (SNES_Patch *)snes->data;
4006c270751SPatrick Farrell 
4016c270751SPatrick Farrell   PetscFunctionBegin;
4029566063dSJacob Faibussowitsch   PetscCall(PCPatchSetComputeFunction(patch->pc, func, ctx));
403*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4046c270751SPatrick Farrell }
4056c270751SPatrick Farrell 
406d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPatchSetConstructType(SNES snes, PCPatchConstructType ctype, PetscErrorCode (*func)(PC, PetscInt *, IS **, IS *, void *), void *ctx)
407d71ae5a4SJacob Faibussowitsch {
4086c270751SPatrick Farrell   SNES_Patch *patch = (SNES_Patch *)snes->data;
4096c270751SPatrick Farrell 
4106c270751SPatrick Farrell   PetscFunctionBegin;
4119566063dSJacob Faibussowitsch   PetscCall(PCPatchSetConstructType(patch->pc, ctype, func, ctx));
412*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4136c270751SPatrick Farrell }
4146c270751SPatrick Farrell 
415d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPatchSetCellNumbering(SNES snes, PetscSection cellNumbering)
416d71ae5a4SJacob Faibussowitsch {
4176c270751SPatrick Farrell   SNES_Patch *patch = (SNES_Patch *)snes->data;
4186c270751SPatrick Farrell 
4196c270751SPatrick Farrell   PetscFunctionBegin;
4209566063dSJacob Faibussowitsch   PetscCall(PCPatchSetCellNumbering(patch->pc, cellNumbering));
421*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4226c270751SPatrick Farrell }
423