xref: /petsc/src/snes/impls/patch/snespatch.c (revision 5f80ce2ab25dff0f4601e710601cbbcecf323266)
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 
14561742edSMatthew G. Knepley static PetscErrorCode SNESPatchComputeResidual_Private(SNES snes, Vec x, Vec F, void *ctx)
15561742edSMatthew G. Knepley {
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;
27*5f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGetSize(pcpatch->dofMappingWithoutToWithAll[pt], &size));
2839fd2e8aSPatrick Farrell 
29*5f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGetIndices(pcpatch->dofMappingWithoutToWithAll[pt], &indices));
30*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayRead(x, &X));
31*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(pcpatch->patchStateWithAll, &XWithAll));
3239fd2e8aSPatrick Farrell 
3387050cfdSPatrick Farrell   for (i = 0; i < size; ++i) {
340904074fSPatrick Farrell     XWithAll[indices[i]] = X[i];
3539fd2e8aSPatrick Farrell   }
3639fd2e8aSPatrick Farrell 
37*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(pcpatch->patchStateWithAll, &XWithAll));
38*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayRead(x, &X));
39*5f80ce2aSJacob Faibussowitsch   CHKERRQ(ISRestoreIndices(pcpatch->dofMappingWithoutToWithAll[pt], &indices));
4039fd2e8aSPatrick Farrell 
41*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PCPatchComputeFunction_Internal(pc, pcpatch->patchStateWithAll, F, pt));
42561742edSMatthew G. Knepley   PetscFunctionReturn(0);
43561742edSMatthew G. Knepley }
44561742edSMatthew G. Knepley 
45561742edSMatthew G. Knepley static PetscErrorCode SNESPatchComputeJacobian_Private(SNES snes, Vec x, Mat J, Mat M, void *ctx)
46561742edSMatthew G. Knepley {
47ab270f91SPatrick Farrell   PC                pc      = (PC) ctx;
48ab270f91SPatrick Farrell   PC_PATCH          *pcpatch = (PC_PATCH *) pc->data;
4987050cfdSPatrick Farrell   PetscInt          pt, size, i;
504d04e9f1SPatrick Farrell   const PetscInt    *indices;
514d04e9f1SPatrick Farrell   const PetscScalar *X;
520904074fSPatrick Farrell   PetscScalar       *XWithAll;
53561742edSMatthew G. Knepley 
54561742edSMatthew G. Knepley   PetscFunctionBegin;
550904074fSPatrick Farrell   /* scatter from x to patch->patchStateWithAll[pt] */
564d04e9f1SPatrick Farrell   pt = pcpatch->currentPatch;
57*5f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGetSize(pcpatch->dofMappingWithoutToWithAll[pt], &size));
584d04e9f1SPatrick Farrell 
59*5f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGetIndices(pcpatch->dofMappingWithoutToWithAll[pt], &indices));
60*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayRead(x, &X));
61*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(pcpatch->patchStateWithAll, &XWithAll));
624d04e9f1SPatrick Farrell 
6387050cfdSPatrick Farrell   for (i = 0; i < size; ++i) {
640904074fSPatrick Farrell     XWithAll[indices[i]] = X[i];
654d04e9f1SPatrick Farrell   }
664d04e9f1SPatrick Farrell 
67*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(pcpatch->patchStateWithAll, &XWithAll));
68*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayRead(x, &X));
69*5f80ce2aSJacob Faibussowitsch   CHKERRQ(ISRestoreIndices(pcpatch->dofMappingWithoutToWithAll[pt], &indices));
704d04e9f1SPatrick Farrell 
71*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PCPatchComputeOperator_Internal(pc, pcpatch->patchStateWithAll, M, pcpatch->currentPatch, PETSC_FALSE));
72561742edSMatthew G. Knepley   PetscFunctionReturn(0);
73561742edSMatthew G. Knepley }
74561742edSMatthew G. Knepley 
75561742edSMatthew G. Knepley static PetscErrorCode PCSetUp_PATCH_Nonlinear(PC pc)
76561742edSMatthew G. Knepley {
77561742edSMatthew G. Knepley   PC_PATCH       *patch = (PC_PATCH *) pc->data;
78561742edSMatthew G. Knepley   const char     *prefix;
799d4fc724SLawrence Mitchell   PetscInt       i, pStart, dof, maxDof = -1;
80561742edSMatthew G. Knepley 
81561742edSMatthew G. Knepley   PetscFunctionBegin;
82561742edSMatthew G. Knepley   if (!pc->setupcalled) {
83*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(patch->npatch, &patch->solver));
84*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PCGetOptionsPrefix(pc, &prefix));
85*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetChart(patch->gtolCounts, &pStart, NULL));
86561742edSMatthew G. Knepley     for (i = 0; i < patch->npatch; ++i) {
87561742edSMatthew G. Knepley       SNES snes;
88561742edSMatthew G. Knepley 
89*5f80ce2aSJacob Faibussowitsch       CHKERRQ(SNESCreate(PETSC_COMM_SELF, &snes));
90*5f80ce2aSJacob Faibussowitsch       CHKERRQ(SNESSetOptionsPrefix(snes, prefix));
91*5f80ce2aSJacob Faibussowitsch       CHKERRQ(SNESAppendOptionsPrefix(snes, "sub_"));
92*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscObjectIncrementTabLevel((PetscObject) snes, (PetscObject) pc, 2));
93*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscLogObjectParent((PetscObject) pc, (PetscObject) snes));
94561742edSMatthew G. Knepley       patch->solver[i] = (PetscObject) snes;
9539fd2e8aSPatrick Farrell 
96*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetDof(patch->gtolCountsWithAll, i+pStart, &dof));
979d4fc724SLawrence Mitchell       maxDof = PetscMax(maxDof, dof);
981202d238SPatrick Farrell     }
99*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecDuplicate(patch->localUpdate, &patch->localState));
100*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecDuplicate(patch->patchRHS, &patch->patchResidual));
101*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecDuplicate(patch->patchUpdate, &patch->patchState));
1029d4fc724SLawrence Mitchell 
103*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecCreateSeq(PETSC_COMM_SELF, maxDof, &patch->patchStateWithAll));
104*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecSetUp(patch->patchStateWithAll));
105561742edSMatthew G. Knepley   }
106561742edSMatthew G. Knepley   for (i = 0; i < patch->npatch; ++i) {
107561742edSMatthew G. Knepley     SNES snes = (SNES) patch->solver[i];
108561742edSMatthew G. Knepley 
109*5f80ce2aSJacob Faibussowitsch     CHKERRQ(SNESSetFunction(snes, patch->patchResidual, SNESPatchComputeResidual_Private, pc));
110*5f80ce2aSJacob Faibussowitsch     CHKERRQ(SNESSetJacobian(snes, patch->mat[i], patch->mat[i], SNESPatchComputeJacobian_Private, pc));
111561742edSMatthew G. Knepley   }
112*5f80ce2aSJacob Faibussowitsch   if (!pc->setupcalled && patch->optionsSet) for (i = 0; i < patch->npatch; ++i) CHKERRQ(SNESSetFromOptions((SNES) patch->solver[i]));
113561742edSMatthew G. Knepley   PetscFunctionReturn(0);
114561742edSMatthew G. Knepley }
115561742edSMatthew G. Knepley 
1161202d238SPatrick Farrell static PetscErrorCode PCApply_PATCH_Nonlinear(PC pc, PetscInt i, Vec patchRHS, Vec patchUpdate)
117561742edSMatthew G. Knepley {
118561742edSMatthew G. Knepley   PC_PATCH      *patch = (PC_PATCH *) pc->data;
119917d05d1SLawrence Mitchell   PetscInt       pStart, n;
120561742edSMatthew G. Knepley 
121561742edSMatthew G. Knepley   PetscFunctionBegin;
122561742edSMatthew G. Knepley   patch->currentPatch = i;
123*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(PC_Patch_Solve, pc, 0, 0, 0));
1241202d238SPatrick Farrell 
1251202d238SPatrick Farrell   /* Scatter the overlapped global state to our patch state vector */
126*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetChart(patch->gtolCounts, &pStart, NULL));
127*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PCPatch_ScatterLocal_Private(pc, i+pStart, patch->localState, patch->patchState, INSERT_VALUES, SCATTER_FORWARD, SCATTER_INTERIOR));
128*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PCPatch_ScatterLocal_Private(pc, i+pStart, patch->localState, patch->patchStateWithAll, INSERT_VALUES, SCATTER_FORWARD, SCATTER_WITHALL));
1291202d238SPatrick Farrell 
130*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetLocalSize(patch->mat[i], NULL, &n));
131917d05d1SLawrence Mitchell   patch->patchState->map->n = n;
132917d05d1SLawrence Mitchell   patch->patchState->map->N = n;
133917d05d1SLawrence Mitchell   patchUpdate->map->n = n;
134917d05d1SLawrence Mitchell   patchUpdate->map->N = n;
135917d05d1SLawrence Mitchell   patchRHS->map->n = n;
136917d05d1SLawrence Mitchell   patchRHS->map->N = n;
1371202d238SPatrick Farrell   /* Set initial guess to be current state*/
138*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecCopy(patch->patchState, patchUpdate));
1391202d238SPatrick Farrell   /* Solve for new state */
140*5f80ce2aSJacob Faibussowitsch   CHKERRQ(SNESSolve((SNES) patch->solver[i], patchRHS, patchUpdate));
1411202d238SPatrick Farrell   /* To compute update, subtract off previous state */
142*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecAXPY(patchUpdate, -1.0, patch->patchState));
1431202d238SPatrick Farrell 
144*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(PC_Patch_Solve, pc, 0, 0, 0));
145561742edSMatthew G. Knepley   PetscFunctionReturn(0);
146561742edSMatthew G. Knepley }
147561742edSMatthew G. Knepley 
148561742edSMatthew G. Knepley static PetscErrorCode PCReset_PATCH_Nonlinear(PC pc)
149561742edSMatthew G. Knepley {
150561742edSMatthew G. Knepley   PC_PATCH      *patch = (PC_PATCH *) pc->data;
151561742edSMatthew G. Knepley   PetscInt       i;
152561742edSMatthew G. Knepley 
153561742edSMatthew G. Knepley   PetscFunctionBegin;
154561742edSMatthew G. Knepley   if (patch->solver) {
155*5f80ce2aSJacob Faibussowitsch     for (i = 0; i < patch->npatch; ++i) CHKERRQ(SNESReset((SNES) patch->solver[i]));
156561742edSMatthew G. Knepley   }
1571202d238SPatrick Farrell 
158*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&patch->patchResidual));
159*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&patch->patchState));
160*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&patch->patchStateWithAll));
16139fd2e8aSPatrick Farrell 
162*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&patch->localState));
163561742edSMatthew G. Knepley   PetscFunctionReturn(0);
164561742edSMatthew G. Knepley }
165561742edSMatthew G. Knepley 
166561742edSMatthew G. Knepley static PetscErrorCode PCDestroy_PATCH_Nonlinear(PC pc)
167561742edSMatthew G. Knepley {
168561742edSMatthew G. Knepley   PC_PATCH      *patch = (PC_PATCH *) pc->data;
169561742edSMatthew G. Knepley   PetscInt       i;
170561742edSMatthew G. Knepley 
171561742edSMatthew G. Knepley   PetscFunctionBegin;
172561742edSMatthew G. Knepley   if (patch->solver) {
173*5f80ce2aSJacob Faibussowitsch     for (i = 0; i < patch->npatch; ++i) CHKERRQ(SNESDestroy((SNES *) &patch->solver[i]));
174*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(patch->solver));
175561742edSMatthew G. Knepley   }
176561742edSMatthew G. Knepley   PetscFunctionReturn(0);
177561742edSMatthew G. Knepley }
178561742edSMatthew G. Knepley 
1796c9c532dSPatrick Farrell static PetscErrorCode PCUpdateMultiplicative_PATCH_Nonlinear(PC pc, PetscInt i, PetscInt pStart)
1806c9c532dSPatrick Farrell {
1816c9c532dSPatrick Farrell   PC_PATCH      *patch = (PC_PATCH *) pc->data;
1826c9c532dSPatrick Farrell 
1834d04e9f1SPatrick Farrell   PetscFunctionBegin;
184*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PCPatch_ScatterLocal_Private(pc, i + pStart, patch->patchUpdate, patch->localState, ADD_VALUES, SCATTER_REVERSE, SCATTER_INTERIOR));
1854d04e9f1SPatrick Farrell   PetscFunctionReturn(0);
1866c9c532dSPatrick Farrell }
1876c9c532dSPatrick Farrell 
188561742edSMatthew G. Knepley static PetscErrorCode SNESSetUp_Patch(SNES snes)
189561742edSMatthew G. Knepley {
190561742edSMatthew G. Knepley   SNES_Patch    *patch = (SNES_Patch *) snes->data;
191561742edSMatthew G. Knepley   DM             dm;
192561742edSMatthew G. Knepley   Mat            dummy;
193561742edSMatthew G. Knepley   Vec            F;
194561742edSMatthew G. Knepley   PetscInt       n, N;
195561742edSMatthew G. Knepley 
196561742edSMatthew G. Knepley   PetscFunctionBegin;
197*5f80ce2aSJacob Faibussowitsch   CHKERRQ(SNESGetDM(snes, &dm));
198*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PCSetDM(patch->pc, dm));
199*5f80ce2aSJacob Faibussowitsch   CHKERRQ(SNESGetFunction(snes, &F, NULL, NULL));
200*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetLocalSize(F, &n));
201*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetSize(F, &N));
202*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreateShell(PetscObjectComm((PetscObject) snes), n, n, N, N, (void *) snes, &dummy));
203*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PCSetOperators(patch->pc, dummy, dummy));
204*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDestroy(&dummy));
205*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PCSetUp(patch->pc));
206561742edSMatthew G. Knepley   /* allocate workspace */
207561742edSMatthew G. Knepley   PetscFunctionReturn(0);
208561742edSMatthew G. Knepley }
209561742edSMatthew G. Knepley 
210561742edSMatthew G. Knepley static PetscErrorCode SNESReset_Patch(SNES snes)
211561742edSMatthew G. Knepley {
212561742edSMatthew G. Knepley   SNES_Patch    *patch = (SNES_Patch *) snes->data;
213561742edSMatthew G. Knepley 
214561742edSMatthew G. Knepley   PetscFunctionBegin;
215*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PCReset(patch->pc));
216561742edSMatthew G. Knepley   PetscFunctionReturn(0);
217561742edSMatthew G. Knepley }
218561742edSMatthew G. Knepley 
219561742edSMatthew G. Knepley static PetscErrorCode SNESDestroy_Patch(SNES snes)
220561742edSMatthew G. Knepley {
221561742edSMatthew G. Knepley   SNES_Patch    *patch = (SNES_Patch *) snes->data;
222561742edSMatthew G. Knepley 
223561742edSMatthew G. Knepley   PetscFunctionBegin;
224*5f80ce2aSJacob Faibussowitsch   CHKERRQ(SNESReset_Patch(snes));
225*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PCDestroy(&patch->pc));
226*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(snes->data));
227561742edSMatthew G. Knepley   PetscFunctionReturn(0);
228561742edSMatthew G. Knepley }
229561742edSMatthew G. Knepley 
230561742edSMatthew G. Knepley static PetscErrorCode SNESSetFromOptions_Patch(PetscOptionItems *PetscOptionsObject, SNES snes)
231561742edSMatthew G. Knepley {
232561742edSMatthew G. Knepley   SNES_Patch    *patch = (SNES_Patch *) snes->data;
2334aa795a7SPatrick Farrell   const char    *prefix;
234561742edSMatthew G. Knepley 
235561742edSMatthew G. Knepley   PetscFunctionBegin;
236*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetOptionsPrefix((PetscObject)snes, &prefix));
237*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetOptionsPrefix((PetscObject)patch->pc, prefix));
238*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PCSetFromOptions(patch->pc));
239561742edSMatthew G. Knepley   PetscFunctionReturn(0);
240561742edSMatthew G. Knepley }
241561742edSMatthew G. Knepley 
242561742edSMatthew G. Knepley static PetscErrorCode SNESView_Patch(SNES snes,PetscViewer viewer)
243561742edSMatthew G. Knepley {
244561742edSMatthew G. Knepley   SNES_Patch    *patch = (SNES_Patch *) snes->data;
245561742edSMatthew G. Knepley   PetscBool      iascii;
246561742edSMatthew G. Knepley 
247561742edSMatthew G. Knepley   PetscFunctionBegin;
248*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii));
249561742edSMatthew G. Knepley   if (iascii) {
250*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"SNESPATCH\n"));
251561742edSMatthew G. Knepley   }
252*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerASCIIPushTab(viewer));
253*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PCView(patch->pc, viewer));
254*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerASCIIPopTab(viewer));
255561742edSMatthew G. Knepley   PetscFunctionReturn(0);
256561742edSMatthew G. Knepley }
257561742edSMatthew G. Knepley 
258561742edSMatthew G. Knepley static PetscErrorCode SNESSolve_Patch(SNES snes)
259561742edSMatthew G. Knepley {
260ab270f91SPatrick Farrell   SNES_Patch        *patch = (SNES_Patch *) snes->data;
2611202d238SPatrick Farrell   PC_PATCH          *pcpatch = (PC_PATCH *) patch->pc->data;
262636c62a6SPatrick Farrell   SNESLineSearch    ls;
263636c62a6SPatrick Farrell   Vec               rhs, update, state, residual;
2641202d238SPatrick Farrell   const PetscScalar *globalState  = NULL;
2651202d238SPatrick Farrell   PetscScalar       *localState   = NULL;
266636c62a6SPatrick Farrell   PetscInt          its = 0;
267636c62a6SPatrick Farrell   PetscReal         xnorm = 0.0, ynorm = 0.0, fnorm = 0.0;
2684aa795a7SPatrick Farrell 
269561742edSMatthew G. Knepley   PetscFunctionBegin;
270*5f80ce2aSJacob Faibussowitsch   CHKERRQ(SNESGetSolution(snes, &state));
271*5f80ce2aSJacob Faibussowitsch   CHKERRQ(SNESGetSolutionUpdate(snes, &update));
272*5f80ce2aSJacob Faibussowitsch   CHKERRQ(SNESGetRhs(snes, &rhs));
2731202d238SPatrick Farrell 
274*5f80ce2aSJacob Faibussowitsch   CHKERRQ(SNESGetFunction(snes, &residual, NULL, NULL));
275*5f80ce2aSJacob Faibussowitsch   CHKERRQ(SNESGetLineSearch(snes, &ls));
276636c62a6SPatrick Farrell 
277*5f80ce2aSJacob Faibussowitsch   CHKERRQ(SNESSetConvergedReason(snes, SNES_CONVERGED_ITERATING));
278*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSet(update, 0.0));
279*5f80ce2aSJacob Faibussowitsch   CHKERRQ(SNESComputeFunction(snes, state, residual));
280636c62a6SPatrick Farrell 
281*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecNorm(state, NORM_2, &xnorm));
282*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecNorm(residual, NORM_2, &fnorm));
283636c62a6SPatrick Farrell   snes->ttol = fnorm*snes->rtol;
284636c62a6SPatrick Farrell 
285636c62a6SPatrick Farrell   if (snes->ops->converged) {
286*5f80ce2aSJacob Faibussowitsch     CHKERRQ((*snes->ops->converged)(snes,its,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP));
287636c62a6SPatrick Farrell   } else {
288*5f80ce2aSJacob Faibussowitsch     CHKERRQ(SNESConvergedSkip(snes,its,xnorm,ynorm,fnorm,&snes->reason,NULL));
289636c62a6SPatrick Farrell   }
290*5f80ce2aSJacob Faibussowitsch   CHKERRQ(SNESLogConvergenceHistory(snes, fnorm, 0)); /* should we count lits from the patches? */
291*5f80ce2aSJacob Faibussowitsch   CHKERRQ(SNESMonitor(snes, its, fnorm));
292636c62a6SPatrick Farrell 
293636c62a6SPatrick Farrell   /* The main solver loop */
294636c62a6SPatrick Farrell   for (its = 0; its < snes->max_its; its++) {
295636c62a6SPatrick Farrell 
296*5f80ce2aSJacob Faibussowitsch     CHKERRQ(SNESSetIterationNumber(snes, its));
297636c62a6SPatrick Farrell 
2981202d238SPatrick Farrell     /* Scatter state vector to overlapped vector on all patches.
2991202d238SPatrick Farrell        The vector pcpatch->localState is scattered to each patch
3001202d238SPatrick Farrell        in PCApply_PATCH_Nonlinear. */
301*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArrayRead(state, &globalState));
302*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArray(pcpatch->localState, &localState));
303*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFBcastBegin(pcpatch->sectionSF, MPIU_SCALAR, globalState, localState,MPI_REPLACE));
304*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFBcastEnd(pcpatch->sectionSF, MPIU_SCALAR, globalState, localState,MPI_REPLACE));
305*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArray(pcpatch->localState, &localState));
306*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArrayRead(state, &globalState));
3071202d238SPatrick Farrell 
308636c62a6SPatrick Farrell     /* The looping over patches happens here */
309*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PCApply(patch->pc, rhs, update));
310636c62a6SPatrick Farrell 
311636c62a6SPatrick Farrell     /* Apply a line search. This will often be basic with
312636c62a6SPatrick Farrell        damping = 1/(max number of patches a dof can be in),
313636c62a6SPatrick Farrell        but not always */
314*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScale(update, -1.0));
315*5f80ce2aSJacob Faibussowitsch     CHKERRQ(SNESLineSearchApply(ls, state, residual, &fnorm, update));
316636c62a6SPatrick Farrell 
317*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecNorm(state, NORM_2, &xnorm));
318*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecNorm(update, NORM_2, &ynorm));
319636c62a6SPatrick Farrell 
320636c62a6SPatrick Farrell     if (snes->ops->converged) {
321*5f80ce2aSJacob Faibussowitsch       CHKERRQ((*snes->ops->converged)(snes,its,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP));
322636c62a6SPatrick Farrell     } else {
323*5f80ce2aSJacob Faibussowitsch       CHKERRQ(SNESConvergedSkip(snes,its,xnorm,ynorm,fnorm,&snes->reason,NULL));
324636c62a6SPatrick Farrell     }
325*5f80ce2aSJacob Faibussowitsch     CHKERRQ(SNESLogConvergenceHistory(snes, fnorm, 0)); /* FIXME: should we count lits? */
326*5f80ce2aSJacob Faibussowitsch     CHKERRQ(SNESMonitor(snes, its, fnorm));
3271202d238SPatrick Farrell   }
3281202d238SPatrick Farrell 
329*5f80ce2aSJacob Faibussowitsch   if (its == snes->max_its) CHKERRQ(SNESSetConvergedReason(snes, SNES_DIVERGED_MAX_IT));
330561742edSMatthew G. Knepley   PetscFunctionReturn(0);
331561742edSMatthew G. Knepley }
332561742edSMatthew G. Knepley 
333561742edSMatthew G. Knepley /*MC
334ab270f91SPatrick Farrell   SNESPATCH - Solve a nonlinear problem by composing together many nonlinear solvers on patches
335561742edSMatthew G. Knepley 
336561742edSMatthew G. Knepley   Level: intermediate
337561742edSMatthew G. Knepley 
338561742edSMatthew G. Knepley .seealso:  SNESCreate(), SNESSetType(), SNESType (for list of available types), SNES,
339561742edSMatthew G. Knepley            PCPATCH
340561742edSMatthew G. Knepley 
341561742edSMatthew G. Knepley    References:
342606c0280SSatish Balay .  * - Peter R. Brune, Matthew G. Knepley, Barry F. Smith, and Xuemin Tu, "Composing Scalable Nonlinear Algebraic Solvers", SIAM Review, 57(4), 2015
343561742edSMatthew G. Knepley 
344561742edSMatthew G. Knepley M*/
345561742edSMatthew G. Knepley PETSC_EXTERN PetscErrorCode SNESCreate_Patch(SNES snes)
346561742edSMatthew G. Knepley {
347561742edSMatthew G. Knepley   SNES_Patch     *patch;
34810534d48SPatrick Farrell   PC_PATCH       *patchpc;
349d8d34be6SBarry Smith   SNESLineSearch linesearch;
350561742edSMatthew G. Knepley 
351561742edSMatthew G. Knepley   PetscFunctionBegin;
352*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscNewLog(snes, &patch));
353561742edSMatthew G. Knepley 
354561742edSMatthew G. Knepley   snes->ops->solve          = SNESSolve_Patch;
355561742edSMatthew G. Knepley   snes->ops->setup          = SNESSetUp_Patch;
356561742edSMatthew G. Knepley   snes->ops->reset          = SNESReset_Patch;
357561742edSMatthew G. Knepley   snes->ops->destroy        = SNESDestroy_Patch;
358561742edSMatthew G. Knepley   snes->ops->setfromoptions = SNESSetFromOptions_Patch;
359561742edSMatthew G. Knepley   snes->ops->view           = SNESView_Patch;
360561742edSMatthew G. Knepley 
361*5f80ce2aSJacob Faibussowitsch   CHKERRQ(SNESGetLineSearch(snes,&linesearch));
362ec786807SJed Brown   if (!((PetscObject)linesearch)->type_name) {
363*5f80ce2aSJacob Faibussowitsch     CHKERRQ(SNESLineSearchSetType(linesearch,SNESLINESEARCHBASIC));
364ec786807SJed Brown   }
365d8d34be6SBarry Smith   snes->usesksp        = PETSC_FALSE;
366d8d34be6SBarry Smith 
367561742edSMatthew G. Knepley   snes->alwayscomputesfinalresidual = PETSC_FALSE;
368561742edSMatthew G. Knepley 
369561742edSMatthew G. Knepley   snes->data = (void *) patch;
370*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PCCreate(PetscObjectComm((PetscObject) snes), &patch->pc));
371*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PCSetType(patch->pc, PCPATCH));
372561742edSMatthew G. Knepley 
37310534d48SPatrick Farrell   patchpc = (PC_PATCH*) patch->pc->data;
37410534d48SPatrick Farrell   patchpc->classname = "snes";
375debbdec3SPatrick Farrell   patchpc->isNonlinear = PETSC_TRUE;
37610534d48SPatrick Farrell 
37710534d48SPatrick Farrell   patchpc->setupsolver   = PCSetUp_PATCH_Nonlinear;
37810534d48SPatrick Farrell   patchpc->applysolver   = PCApply_PATCH_Nonlinear;
37910534d48SPatrick Farrell   patchpc->resetsolver   = PCReset_PATCH_Nonlinear;
38010534d48SPatrick Farrell   patchpc->destroysolver = PCDestroy_PATCH_Nonlinear;
3816c9c532dSPatrick Farrell   patchpc->updatemultiplicative = PCUpdateMultiplicative_PATCH_Nonlinear;
382561742edSMatthew G. Knepley 
383561742edSMatthew G. Knepley   PetscFunctionReturn(0);
384561742edSMatthew G. Knepley }
3856c270751SPatrick Farrell 
3866c270751SPatrick Farrell PetscErrorCode SNESPatchSetDiscretisationInfo(SNES snes, PetscInt nsubspaces, DM *dms, PetscInt *bs, PetscInt *nodesPerCell, const PetscInt **cellNodeMap,
3876c270751SPatrick Farrell                                             const PetscInt *subspaceOffsets, PetscInt numGhostBcs, const PetscInt *ghostBcNodes, PetscInt numGlobalBcs, const PetscInt *globalBcNodes)
3886c270751SPatrick Farrell {
3896c270751SPatrick Farrell   SNES_Patch     *patch = (SNES_Patch *) snes->data;
390f08b3ad2SPatrick Farrell   DM             dm;
3916c270751SPatrick Farrell 
3926c270751SPatrick Farrell   PetscFunctionBegin;
393*5f80ce2aSJacob Faibussowitsch   CHKERRQ(SNESGetDM(snes, &dm));
3942c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!dm,PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONGSTATE, "DM not yet set on patch SNES");
395*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PCSetDM(patch->pc, dm));
396*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PCPatchSetDiscretisationInfo(patch->pc, nsubspaces, dms, bs, nodesPerCell, cellNodeMap, subspaceOffsets, numGhostBcs, ghostBcNodes, numGlobalBcs, globalBcNodes));
3976c270751SPatrick Farrell   PetscFunctionReturn(0);
3986c270751SPatrick Farrell }
3996c270751SPatrick Farrell 
4004d04e9f1SPatrick Farrell PetscErrorCode SNESPatchSetComputeOperator(SNES snes, PetscErrorCode (*func)(PC, PetscInt, Vec, Mat, IS, PetscInt, const PetscInt *, const PetscInt *, void *), void *ctx)
4016c270751SPatrick Farrell {
4026c270751SPatrick Farrell   SNES_Patch    *patch = (SNES_Patch *) snes->data;
4036c270751SPatrick Farrell 
4046c270751SPatrick Farrell   PetscFunctionBegin;
405*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PCPatchSetComputeOperator(patch->pc, func, ctx));
4066c270751SPatrick Farrell   PetscFunctionReturn(0);
4076c270751SPatrick Farrell }
4086c270751SPatrick Farrell 
40939fd2e8aSPatrick Farrell PetscErrorCode SNESPatchSetComputeFunction(SNES snes, PetscErrorCode (*func)(PC, PetscInt, Vec, Vec, IS, PetscInt, const PetscInt *, const PetscInt *, void *), void *ctx)
4106c270751SPatrick Farrell {
4116c270751SPatrick Farrell   SNES_Patch    *patch = (SNES_Patch *) snes->data;
4126c270751SPatrick Farrell 
4136c270751SPatrick Farrell   PetscFunctionBegin;
414*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PCPatchSetComputeFunction(patch->pc, func, ctx));
4156c270751SPatrick Farrell   PetscFunctionReturn(0);
4166c270751SPatrick Farrell }
4176c270751SPatrick Farrell 
4186c270751SPatrick Farrell PetscErrorCode SNESPatchSetConstructType(SNES snes, PCPatchConstructType ctype, PetscErrorCode (*func)(PC, PetscInt *, IS **, IS *, void *), void *ctx)
4196c270751SPatrick Farrell {
4206c270751SPatrick Farrell   SNES_Patch    *patch = (SNES_Patch *) snes->data;
4216c270751SPatrick Farrell 
4226c270751SPatrick Farrell   PetscFunctionBegin;
423*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PCPatchSetConstructType(patch->pc, ctype, func, ctx));
4246c270751SPatrick Farrell   PetscFunctionReturn(0);
4256c270751SPatrick Farrell }
4266c270751SPatrick Farrell 
4276c270751SPatrick Farrell PetscErrorCode SNESPatchSetCellNumbering(SNES snes, PetscSection cellNumbering)
4286c270751SPatrick Farrell {
4296c270751SPatrick Farrell   SNES_Patch    *patch = (SNES_Patch *) snes->data;
4306c270751SPatrick Farrell 
4316c270751SPatrick Farrell   PetscFunctionBegin;
432*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PCPatchSetCellNumbering(patch->pc, cellNumbering));
4336c270751SPatrick Farrell   PetscFunctionReturn(0);
4346c270751SPatrick Farrell }
435