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