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
SNESPatchComputeResidual_Private(SNES snes,Vec x,Vec F,PetscCtx ctx)14*2a8381b2SBarry Smith static PetscErrorCode SNESPatchComputeResidual_Private(SNES snes, Vec x, Vec F, PetscCtx 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;
240904074fSPatrick Farrell /* scatter from x to patch->patchStateWithAll[pt] */
2539fd2e8aSPatrick Farrell pt = pcpatch->currentPatch;
269566063dSJacob Faibussowitsch PetscCall(ISGetSize(pcpatch->dofMappingWithoutToWithAll[pt], &size));
2739fd2e8aSPatrick Farrell
289566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcpatch->dofMappingWithoutToWithAll[pt], &indices));
299566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x, &X));
309566063dSJacob Faibussowitsch PetscCall(VecGetArray(pcpatch->patchStateWithAll, &XWithAll));
3139fd2e8aSPatrick Farrell
32ad540459SPierre Jolivet for (i = 0; i < size; ++i) XWithAll[indices[i]] = X[i];
3339fd2e8aSPatrick Farrell
349566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(pcpatch->patchStateWithAll, &XWithAll));
359566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x, &X));
369566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcpatch->dofMappingWithoutToWithAll[pt], &indices));
3739fd2e8aSPatrick Farrell
389566063dSJacob Faibussowitsch PetscCall(PCPatchComputeFunction_Internal(pc, pcpatch->patchStateWithAll, F, pt));
393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
40561742edSMatthew G. Knepley }
41561742edSMatthew G. Knepley
SNESPatchComputeJacobian_Private(SNES snes,Vec x,Mat J,Mat M,PetscCtx ctx)42*2a8381b2SBarry Smith static PetscErrorCode SNESPatchComputeJacobian_Private(SNES snes, Vec x, Mat J, Mat M, PetscCtx ctx)
43d71ae5a4SJacob Faibussowitsch {
44ab270f91SPatrick Farrell PC pc = (PC)ctx;
45ab270f91SPatrick Farrell PC_PATCH *pcpatch = (PC_PATCH *)pc->data;
4687050cfdSPatrick Farrell PetscInt pt, size, i;
474d04e9f1SPatrick Farrell const PetscInt *indices;
484d04e9f1SPatrick Farrell const PetscScalar *X;
490904074fSPatrick Farrell PetscScalar *XWithAll;
50561742edSMatthew G. Knepley
51561742edSMatthew G. Knepley PetscFunctionBegin;
520904074fSPatrick Farrell /* scatter from x to patch->patchStateWithAll[pt] */
534d04e9f1SPatrick Farrell pt = pcpatch->currentPatch;
549566063dSJacob Faibussowitsch PetscCall(ISGetSize(pcpatch->dofMappingWithoutToWithAll[pt], &size));
554d04e9f1SPatrick Farrell
569566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcpatch->dofMappingWithoutToWithAll[pt], &indices));
579566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x, &X));
589566063dSJacob Faibussowitsch PetscCall(VecGetArray(pcpatch->patchStateWithAll, &XWithAll));
594d04e9f1SPatrick Farrell
60ad540459SPierre Jolivet for (i = 0; i < size; ++i) XWithAll[indices[i]] = X[i];
614d04e9f1SPatrick Farrell
629566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(pcpatch->patchStateWithAll, &XWithAll));
639566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x, &X));
649566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcpatch->dofMappingWithoutToWithAll[pt], &indices));
654d04e9f1SPatrick Farrell
669566063dSJacob Faibussowitsch PetscCall(PCPatchComputeOperator_Internal(pc, pcpatch->patchStateWithAll, M, pcpatch->currentPatch, PETSC_FALSE));
673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
68561742edSMatthew G. Knepley }
69561742edSMatthew G. Knepley
PCSetUp_PATCH_Nonlinear(PC pc)70d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetUp_PATCH_Nonlinear(PC pc)
71d71ae5a4SJacob Faibussowitsch {
72561742edSMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data;
73561742edSMatthew G. Knepley const char *prefix;
749d4fc724SLawrence Mitchell PetscInt i, pStart, dof, maxDof = -1;
75561742edSMatthew G. Knepley
76561742edSMatthew G. Knepley PetscFunctionBegin;
77561742edSMatthew G. Knepley if (!pc->setupcalled) {
789566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(patch->npatch, &patch->solver));
799566063dSJacob Faibussowitsch PetscCall(PCGetOptionsPrefix(pc, &prefix));
809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(patch->gtolCounts, &pStart, NULL));
81561742edSMatthew G. Knepley for (i = 0; i < patch->npatch; ++i) {
82561742edSMatthew G. Knepley SNES snes;
83561742edSMatthew G. Knepley
849566063dSJacob Faibussowitsch PetscCall(SNESCreate(PETSC_COMM_SELF, &snes));
859566063dSJacob Faibussowitsch PetscCall(SNESSetOptionsPrefix(snes, prefix));
869566063dSJacob Faibussowitsch PetscCall(SNESAppendOptionsPrefix(snes, "sub_"));
879566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes, (PetscObject)pc, 2));
88561742edSMatthew G. Knepley patch->solver[i] = (PetscObject)snes;
8939fd2e8aSPatrick Farrell
909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->gtolCountsWithAll, i + pStart, &dof));
919d4fc724SLawrence Mitchell maxDof = PetscMax(maxDof, dof);
921202d238SPatrick Farrell }
939566063dSJacob Faibussowitsch PetscCall(VecDuplicate(patch->localUpdate, &patch->localState));
949566063dSJacob Faibussowitsch PetscCall(VecDuplicate(patch->patchRHS, &patch->patchResidual));
959566063dSJacob Faibussowitsch PetscCall(VecDuplicate(patch->patchUpdate, &patch->patchState));
969d4fc724SLawrence Mitchell
979566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF, maxDof, &patch->patchStateWithAll));
989566063dSJacob Faibussowitsch PetscCall(VecSetUp(patch->patchStateWithAll));
99561742edSMatthew G. Knepley }
100561742edSMatthew G. Knepley for (i = 0; i < patch->npatch; ++i) {
101561742edSMatthew G. Knepley SNES snes = (SNES)patch->solver[i];
102561742edSMatthew G. Knepley
1039566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes, patch->patchResidual, SNESPatchComputeResidual_Private, pc));
1049566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, patch->mat[i], patch->mat[i], SNESPatchComputeJacobian_Private, pc));
105561742edSMatthew G. Knepley }
1069371c9d4SSatish Balay if (!pc->setupcalled && patch->optionsSet)
1079371c9d4SSatish Balay for (i = 0; i < patch->npatch; ++i) PetscCall(SNESSetFromOptions((SNES)patch->solver[i]));
1083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
109561742edSMatthew G. Knepley }
110561742edSMatthew G. Knepley
PCApply_PATCH_Nonlinear(PC pc,PetscInt i,Vec patchRHS,Vec patchUpdate)111d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApply_PATCH_Nonlinear(PC pc, PetscInt i, Vec patchRHS, Vec patchUpdate)
112d71ae5a4SJacob Faibussowitsch {
113561742edSMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data;
114917d05d1SLawrence Mitchell PetscInt pStart, n;
115561742edSMatthew G. Knepley
116561742edSMatthew G. Knepley PetscFunctionBegin;
117561742edSMatthew G. Knepley patch->currentPatch = i;
1189566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_Patch_Solve, pc, 0, 0, 0));
1191202d238SPatrick Farrell
1201202d238SPatrick Farrell /* Scatter the overlapped global state to our patch state vector */
1219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(patch->gtolCounts, &pStart, NULL));
1229566063dSJacob Faibussowitsch PetscCall(PCPatch_ScatterLocal_Private(pc, i + pStart, patch->localState, patch->patchState, INSERT_VALUES, SCATTER_FORWARD, SCATTER_INTERIOR));
1239566063dSJacob Faibussowitsch PetscCall(PCPatch_ScatterLocal_Private(pc, i + pStart, patch->localState, patch->patchStateWithAll, INSERT_VALUES, SCATTER_FORWARD, SCATTER_WITHALL));
1241202d238SPatrick Farrell
1259566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(patch->mat[i], NULL, &n));
126917d05d1SLawrence Mitchell patch->patchState->map->n = n;
127917d05d1SLawrence Mitchell patch->patchState->map->N = n;
128917d05d1SLawrence Mitchell patchUpdate->map->n = n;
129917d05d1SLawrence Mitchell patchUpdate->map->N = n;
130917d05d1SLawrence Mitchell patchRHS->map->n = n;
131917d05d1SLawrence Mitchell patchRHS->map->N = n;
1321202d238SPatrick Farrell /* Set initial guess to be current state*/
1339566063dSJacob Faibussowitsch PetscCall(VecCopy(patch->patchState, patchUpdate));
1341202d238SPatrick Farrell /* Solve for new state */
1359566063dSJacob Faibussowitsch PetscCall(SNESSolve((SNES)patch->solver[i], patchRHS, patchUpdate));
1361202d238SPatrick Farrell /* To compute update, subtract off previous state */
1379566063dSJacob Faibussowitsch PetscCall(VecAXPY(patchUpdate, -1.0, patch->patchState));
1381202d238SPatrick Farrell
1399566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_Patch_Solve, pc, 0, 0, 0));
1403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
141561742edSMatthew G. Knepley }
142561742edSMatthew G. Knepley
PCReset_PATCH_Nonlinear(PC pc)143d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCReset_PATCH_Nonlinear(PC pc)
144d71ae5a4SJacob Faibussowitsch {
145561742edSMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data;
146561742edSMatthew G. Knepley PetscInt i;
147561742edSMatthew G. Knepley
148561742edSMatthew G. Knepley PetscFunctionBegin;
149561742edSMatthew G. Knepley if (patch->solver) {
1509566063dSJacob Faibussowitsch for (i = 0; i < patch->npatch; ++i) PetscCall(SNESReset((SNES)patch->solver[i]));
151561742edSMatthew G. Knepley }
1521202d238SPatrick Farrell
1539566063dSJacob Faibussowitsch PetscCall(VecDestroy(&patch->patchResidual));
1549566063dSJacob Faibussowitsch PetscCall(VecDestroy(&patch->patchState));
1559566063dSJacob Faibussowitsch PetscCall(VecDestroy(&patch->patchStateWithAll));
15639fd2e8aSPatrick Farrell
1579566063dSJacob Faibussowitsch PetscCall(VecDestroy(&patch->localState));
1583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
159561742edSMatthew G. Knepley }
160561742edSMatthew G. Knepley
PCDestroy_PATCH_Nonlinear(PC pc)161d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCDestroy_PATCH_Nonlinear(PC pc)
162d71ae5a4SJacob Faibussowitsch {
163561742edSMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data;
164561742edSMatthew G. Knepley PetscInt i;
165561742edSMatthew G. Knepley
166561742edSMatthew G. Knepley PetscFunctionBegin;
167561742edSMatthew G. Knepley if (patch->solver) {
1689566063dSJacob Faibussowitsch for (i = 0; i < patch->npatch; ++i) PetscCall(SNESDestroy((SNES *)&patch->solver[i]));
1699566063dSJacob Faibussowitsch PetscCall(PetscFree(patch->solver));
170561742edSMatthew G. Knepley }
1713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
172561742edSMatthew G. Knepley }
173561742edSMatthew G. Knepley
PCUpdateMultiplicative_PATCH_Nonlinear(PC pc,PetscInt i,PetscInt pStart)174d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCUpdateMultiplicative_PATCH_Nonlinear(PC pc, PetscInt i, PetscInt pStart)
175d71ae5a4SJacob Faibussowitsch {
1766c9c532dSPatrick Farrell PC_PATCH *patch = (PC_PATCH *)pc->data;
1776c9c532dSPatrick Farrell
1784d04e9f1SPatrick Farrell PetscFunctionBegin;
1799566063dSJacob Faibussowitsch PetscCall(PCPatch_ScatterLocal_Private(pc, i + pStart, patch->patchUpdate, patch->localState, ADD_VALUES, SCATTER_REVERSE, SCATTER_INTERIOR));
1803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1816c9c532dSPatrick Farrell }
1826c9c532dSPatrick Farrell
SNESSetUp_Patch(SNES snes)183d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetUp_Patch(SNES snes)
184d71ae5a4SJacob Faibussowitsch {
185561742edSMatthew G. Knepley SNES_Patch *patch = (SNES_Patch *)snes->data;
186561742edSMatthew G. Knepley DM dm;
187561742edSMatthew G. Knepley Mat dummy;
188561742edSMatthew G. Knepley Vec F;
189561742edSMatthew G. Knepley PetscInt n, N;
190561742edSMatthew G. Knepley
191561742edSMatthew G. Knepley PetscFunctionBegin;
1929566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm));
1939566063dSJacob Faibussowitsch PetscCall(PCSetDM(patch->pc, dm));
1949566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &F, NULL, NULL));
1959566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(F, &n));
1969566063dSJacob Faibussowitsch PetscCall(VecGetSize(F, &N));
1979566063dSJacob Faibussowitsch PetscCall(MatCreateShell(PetscObjectComm((PetscObject)snes), n, n, N, N, (void *)snes, &dummy));
1989566063dSJacob Faibussowitsch PetscCall(PCSetOperators(patch->pc, dummy, dummy));
1999566063dSJacob Faibussowitsch PetscCall(MatDestroy(&dummy));
2009566063dSJacob Faibussowitsch PetscCall(PCSetUp(patch->pc));
201561742edSMatthew G. Knepley /* allocate workspace */
2023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
203561742edSMatthew G. Knepley }
204561742edSMatthew G. Knepley
SNESReset_Patch(SNES snes)205d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESReset_Patch(SNES snes)
206d71ae5a4SJacob Faibussowitsch {
207561742edSMatthew G. Knepley SNES_Patch *patch = (SNES_Patch *)snes->data;
208561742edSMatthew G. Knepley
209561742edSMatthew G. Knepley PetscFunctionBegin;
2109566063dSJacob Faibussowitsch PetscCall(PCReset(patch->pc));
2113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
212561742edSMatthew G. Knepley }
213561742edSMatthew G. Knepley
SNESDestroy_Patch(SNES snes)214d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESDestroy_Patch(SNES snes)
215d71ae5a4SJacob Faibussowitsch {
216561742edSMatthew G. Knepley SNES_Patch *patch = (SNES_Patch *)snes->data;
217561742edSMatthew G. Knepley
218561742edSMatthew G. Knepley PetscFunctionBegin;
2199566063dSJacob Faibussowitsch PetscCall(SNESReset_Patch(snes));
2209566063dSJacob Faibussowitsch PetscCall(PCDestroy(&patch->pc));
2219566063dSJacob Faibussowitsch PetscCall(PetscFree(snes->data));
2223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
223561742edSMatthew G. Knepley }
224561742edSMatthew G. Knepley
SNESSetFromOptions_Patch(SNES snes,PetscOptionItems PetscOptionsObject)225ce78bad3SBarry Smith static PetscErrorCode SNESSetFromOptions_Patch(SNES snes, PetscOptionItems PetscOptionsObject)
226d71ae5a4SJacob Faibussowitsch {
227561742edSMatthew G. Knepley SNES_Patch *patch = (SNES_Patch *)snes->data;
2284aa795a7SPatrick Farrell const char *prefix;
229561742edSMatthew G. Knepley
230561742edSMatthew G. Knepley PetscFunctionBegin;
2319566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)snes, &prefix));
2329566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)patch->pc, prefix));
2339566063dSJacob Faibussowitsch PetscCall(PCSetFromOptions(patch->pc));
2343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
235561742edSMatthew G. Knepley }
236561742edSMatthew G. Knepley
SNESView_Patch(SNES snes,PetscViewer viewer)237d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESView_Patch(SNES snes, PetscViewer viewer)
238d71ae5a4SJacob Faibussowitsch {
239561742edSMatthew G. Knepley SNES_Patch *patch = (SNES_Patch *)snes->data;
2409f196a02SMartin Diehl PetscBool isascii;
241561742edSMatthew G. Knepley
242561742edSMatthew G. Knepley PetscFunctionBegin;
2439f196a02SMartin Diehl PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
2449f196a02SMartin Diehl if (isascii) PetscCall(PetscViewerASCIIPrintf(viewer, "SNESPATCH\n"));
2459566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer));
2469566063dSJacob Faibussowitsch PetscCall(PCView(patch->pc, viewer));
2479566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer));
2483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
249561742edSMatthew G. Knepley }
250561742edSMatthew G. Knepley
SNESSolve_Patch(SNES snes)251d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSolve_Patch(SNES snes)
252d71ae5a4SJacob Faibussowitsch {
253ab270f91SPatrick Farrell SNES_Patch *patch = (SNES_Patch *)snes->data;
2541202d238SPatrick Farrell PC_PATCH *pcpatch = (PC_PATCH *)patch->pc->data;
255636c62a6SPatrick Farrell SNESLineSearch ls;
256636c62a6SPatrick Farrell Vec rhs, update, state, residual;
2571202d238SPatrick Farrell const PetscScalar *globalState = NULL;
2581202d238SPatrick Farrell PetscScalar *localState = NULL;
259636c62a6SPatrick Farrell PetscInt its = 0;
260636c62a6SPatrick Farrell PetscReal xnorm = 0.0, ynorm = 0.0, fnorm = 0.0;
2614aa795a7SPatrick Farrell
262561742edSMatthew G. Knepley PetscFunctionBegin;
2639566063dSJacob Faibussowitsch PetscCall(SNESGetSolution(snes, &state));
2649566063dSJacob Faibussowitsch PetscCall(SNESGetSolutionUpdate(snes, &update));
2659566063dSJacob Faibussowitsch PetscCall(SNESGetRhs(snes, &rhs));
2661202d238SPatrick Farrell
2679566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &residual, NULL, NULL));
2689566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &ls));
269636c62a6SPatrick Farrell
2709566063dSJacob Faibussowitsch PetscCall(SNESSetConvergedReason(snes, SNES_CONVERGED_ITERATING));
2719566063dSJacob Faibussowitsch PetscCall(VecSet(update, 0.0));
2729566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, state, residual));
273636c62a6SPatrick Farrell
2749566063dSJacob Faibussowitsch PetscCall(VecNorm(state, NORM_2, &xnorm));
2759566063dSJacob Faibussowitsch PetscCall(VecNorm(residual, NORM_2, &fnorm));
27676c63389SBarry Smith SNESCheckFunctionDomainError(snes, 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));
3233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
324561742edSMatthew G. Knepley }
325561742edSMatthew G. Knepley
326561742edSMatthew G. Knepley /*MC
3271d27aa22SBarry Smith SNESPATCH - Solve a nonlinear problem or apply a nonlinear smoother by composing together many nonlinear solvers on (often overlapping) patches {cite}`bruneknepleysmithtu15`
328561742edSMatthew G. Knepley
329561742edSMatthew G. Knepley Level: intermediate
330561742edSMatthew G. Knepley
331420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESFAS`, `SNESCreate()`, `SNESSetType()`, `SNESType`, `SNES`, `PCPATCH`
332561742edSMatthew G. Knepley M*/
SNESCreate_Patch(SNES snes)333d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode SNESCreate_Patch(SNES snes)
334d71ae5a4SJacob Faibussowitsch {
335561742edSMatthew G. Knepley SNES_Patch *patch;
33610534d48SPatrick Farrell PC_PATCH *patchpc;
337d8d34be6SBarry Smith SNESLineSearch linesearch;
338561742edSMatthew G. Knepley
339561742edSMatthew G. Knepley PetscFunctionBegin;
3404dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&patch));
341561742edSMatthew G. Knepley
342561742edSMatthew G. Knepley snes->ops->solve = SNESSolve_Patch;
343561742edSMatthew G. Knepley snes->ops->setup = SNESSetUp_Patch;
344561742edSMatthew G. Knepley snes->ops->reset = SNESReset_Patch;
345561742edSMatthew G. Knepley snes->ops->destroy = SNESDestroy_Patch;
346561742edSMatthew G. Knepley snes->ops->setfromoptions = SNESSetFromOptions_Patch;
347561742edSMatthew G. Knepley snes->ops->view = SNESView_Patch;
348561742edSMatthew G. Knepley
3499566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &linesearch));
35048a46eb9SPierre Jolivet if (!((PetscObject)linesearch)->type_name) PetscCall(SNESLineSearchSetType(linesearch, SNESLINESEARCHBASIC));
351d8d34be6SBarry Smith snes->usesksp = PETSC_FALSE;
352d8d34be6SBarry Smith
353561742edSMatthew G. Knepley snes->alwayscomputesfinalresidual = PETSC_FALSE;
354561742edSMatthew G. Knepley
35577e5a1f9SBarry Smith PetscCall(SNESParametersInitialize(snes));
35677e5a1f9SBarry Smith
357561742edSMatthew G. Knepley snes->data = (void *)patch;
3589566063dSJacob Faibussowitsch PetscCall(PCCreate(PetscObjectComm((PetscObject)snes), &patch->pc));
3599566063dSJacob Faibussowitsch PetscCall(PCSetType(patch->pc, PCPATCH));
360561742edSMatthew G. Knepley
36110534d48SPatrick Farrell patchpc = (PC_PATCH *)patch->pc->data;
36210534d48SPatrick Farrell patchpc->classname = "snes";
363debbdec3SPatrick Farrell patchpc->isNonlinear = PETSC_TRUE;
36410534d48SPatrick Farrell
36510534d48SPatrick Farrell patchpc->setupsolver = PCSetUp_PATCH_Nonlinear;
36610534d48SPatrick Farrell patchpc->applysolver = PCApply_PATCH_Nonlinear;
36710534d48SPatrick Farrell patchpc->resetsolver = PCReset_PATCH_Nonlinear;
36810534d48SPatrick Farrell patchpc->destroysolver = PCDestroy_PATCH_Nonlinear;
3696c9c532dSPatrick Farrell patchpc->updatemultiplicative = PCUpdateMultiplicative_PATCH_Nonlinear;
3703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
371561742edSMatthew G. Knepley }
3726c270751SPatrick Farrell
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)373d71ae5a4SJacob 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)
374d71ae5a4SJacob Faibussowitsch {
3756c270751SPatrick Farrell SNES_Patch *patch = (SNES_Patch *)snes->data;
376f08b3ad2SPatrick Farrell DM dm;
3776c270751SPatrick Farrell
3786c270751SPatrick Farrell PetscFunctionBegin;
3799566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm));
38028b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONGSTATE, "DM not yet set on patch SNES");
3819566063dSJacob Faibussowitsch PetscCall(PCSetDM(patch->pc, dm));
3829566063dSJacob Faibussowitsch PetscCall(PCPatchSetDiscretisationInfo(patch->pc, nsubspaces, dms, bs, nodesPerCell, cellNodeMap, subspaceOffsets, numGhostBcs, ghostBcNodes, numGlobalBcs, globalBcNodes));
3833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
3846c270751SPatrick Farrell }
3856c270751SPatrick Farrell
SNESPatchSetComputeOperator(SNES snes,PetscErrorCode (* func)(PC,PetscInt,Vec,Mat,IS,PetscInt,const PetscInt *,const PetscInt *,void *),PetscCtx ctx)386*2a8381b2SBarry Smith PetscErrorCode SNESPatchSetComputeOperator(SNES snes, PetscErrorCode (*func)(PC, PetscInt, Vec, Mat, IS, PetscInt, const PetscInt *, const PetscInt *, void *), PetscCtx ctx)
387d71ae5a4SJacob Faibussowitsch {
3886c270751SPatrick Farrell SNES_Patch *patch = (SNES_Patch *)snes->data;
3896c270751SPatrick Farrell
3906c270751SPatrick Farrell PetscFunctionBegin;
3919566063dSJacob Faibussowitsch PetscCall(PCPatchSetComputeOperator(patch->pc, func, ctx));
3923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
3936c270751SPatrick Farrell }
3946c270751SPatrick Farrell
SNESPatchSetComputeFunction(SNES snes,PetscErrorCode (* func)(PC,PetscInt,Vec,Vec,IS,PetscInt,const PetscInt *,const PetscInt *,void *),PetscCtx ctx)395*2a8381b2SBarry Smith PetscErrorCode SNESPatchSetComputeFunction(SNES snes, PetscErrorCode (*func)(PC, PetscInt, Vec, Vec, IS, PetscInt, const PetscInt *, const PetscInt *, void *), PetscCtx ctx)
396d71ae5a4SJacob Faibussowitsch {
3976c270751SPatrick Farrell SNES_Patch *patch = (SNES_Patch *)snes->data;
3986c270751SPatrick Farrell
3996c270751SPatrick Farrell PetscFunctionBegin;
4009566063dSJacob Faibussowitsch PetscCall(PCPatchSetComputeFunction(patch->pc, func, ctx));
4013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
4026c270751SPatrick Farrell }
4036c270751SPatrick Farrell
SNESPatchSetConstructType(SNES snes,PCPatchConstructType ctype,PetscErrorCode (* func)(PC,PetscInt *,IS **,IS *,void *),PetscCtx ctx)404*2a8381b2SBarry Smith PetscErrorCode SNESPatchSetConstructType(SNES snes, PCPatchConstructType ctype, PetscErrorCode (*func)(PC, PetscInt *, IS **, IS *, void *), PetscCtx ctx)
405d71ae5a4SJacob Faibussowitsch {
4066c270751SPatrick Farrell SNES_Patch *patch = (SNES_Patch *)snes->data;
4076c270751SPatrick Farrell
4086c270751SPatrick Farrell PetscFunctionBegin;
4099566063dSJacob Faibussowitsch PetscCall(PCPatchSetConstructType(patch->pc, ctype, func, ctx));
4103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
4116c270751SPatrick Farrell }
4126c270751SPatrick Farrell
SNESPatchSetCellNumbering(SNES snes,PetscSection cellNumbering)413d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPatchSetCellNumbering(SNES snes, PetscSection cellNumbering)
414d71ae5a4SJacob Faibussowitsch {
4156c270751SPatrick Farrell SNES_Patch *patch = (SNES_Patch *)snes->data;
4166c270751SPatrick Farrell
4176c270751SPatrick Farrell PetscFunctionBegin;
4189566063dSJacob Faibussowitsch PetscCall(PCPatchSetCellNumbering(patch->pc, cellNumbering));
4193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
4206c270751SPatrick Farrell }
421