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; 275f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetSize(pcpatch->dofMappingWithoutToWithAll[pt], &size)); 2839fd2e8aSPatrick Farrell 295f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(pcpatch->dofMappingWithoutToWithAll[pt], &indices)); 305f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(x, &X)); 315f80ce2aSJacob 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 375f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(pcpatch->patchStateWithAll, &XWithAll)); 385f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(x, &X)); 395f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(pcpatch->dofMappingWithoutToWithAll[pt], &indices)); 4039fd2e8aSPatrick Farrell 415f80ce2aSJacob 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; 575f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetSize(pcpatch->dofMappingWithoutToWithAll[pt], &size)); 584d04e9f1SPatrick Farrell 595f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(pcpatch->dofMappingWithoutToWithAll[pt], &indices)); 605f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(x, &X)); 615f80ce2aSJacob 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 675f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(pcpatch->patchStateWithAll, &XWithAll)); 685f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(x, &X)); 695f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(pcpatch->dofMappingWithoutToWithAll[pt], &indices)); 704d04e9f1SPatrick Farrell 715f80ce2aSJacob 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) { 835f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(patch->npatch, &patch->solver)); 845f80ce2aSJacob Faibussowitsch CHKERRQ(PCGetOptionsPrefix(pc, &prefix)); 855f80ce2aSJacob 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 895f80ce2aSJacob Faibussowitsch CHKERRQ(SNESCreate(PETSC_COMM_SELF, &snes)); 905f80ce2aSJacob Faibussowitsch CHKERRQ(SNESSetOptionsPrefix(snes, prefix)); 915f80ce2aSJacob Faibussowitsch CHKERRQ(SNESAppendOptionsPrefix(snes, "sub_")); 925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectIncrementTabLevel((PetscObject) snes, (PetscObject) pc, 2)); 935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogObjectParent((PetscObject) pc, (PetscObject) snes)); 94561742edSMatthew G. Knepley patch->solver[i] = (PetscObject) snes; 9539fd2e8aSPatrick Farrell 965f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(patch->gtolCountsWithAll, i+pStart, &dof)); 979d4fc724SLawrence Mitchell maxDof = PetscMax(maxDof, dof); 981202d238SPatrick Farrell } 995f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(patch->localUpdate, &patch->localState)); 1005f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(patch->patchRHS, &patch->patchResidual)); 1015f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(patch->patchUpdate, &patch->patchState)); 1029d4fc724SLawrence Mitchell 1035f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreateSeq(PETSC_COMM_SELF, maxDof, &patch->patchStateWithAll)); 1045f80ce2aSJacob 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 1095f80ce2aSJacob Faibussowitsch CHKERRQ(SNESSetFunction(snes, patch->patchResidual, SNESPatchComputeResidual_Private, pc)); 1105f80ce2aSJacob Faibussowitsch CHKERRQ(SNESSetJacobian(snes, patch->mat[i], patch->mat[i], SNESPatchComputeJacobian_Private, pc)); 111561742edSMatthew G. Knepley } 1125f80ce2aSJacob 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; 1235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(PC_Patch_Solve, pc, 0, 0, 0)); 1241202d238SPatrick Farrell 1251202d238SPatrick Farrell /* Scatter the overlapped global state to our patch state vector */ 1265f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(patch->gtolCounts, &pStart, NULL)); 1275f80ce2aSJacob Faibussowitsch CHKERRQ(PCPatch_ScatterLocal_Private(pc, i+pStart, patch->localState, patch->patchState, INSERT_VALUES, SCATTER_FORWARD, SCATTER_INTERIOR)); 1285f80ce2aSJacob Faibussowitsch CHKERRQ(PCPatch_ScatterLocal_Private(pc, i+pStart, patch->localState, patch->patchStateWithAll, INSERT_VALUES, SCATTER_FORWARD, SCATTER_WITHALL)); 1291202d238SPatrick Farrell 1305f80ce2aSJacob 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*/ 1385f80ce2aSJacob Faibussowitsch CHKERRQ(VecCopy(patch->patchState, patchUpdate)); 1391202d238SPatrick Farrell /* Solve for new state */ 1405f80ce2aSJacob Faibussowitsch CHKERRQ(SNESSolve((SNES) patch->solver[i], patchRHS, patchUpdate)); 1411202d238SPatrick Farrell /* To compute update, subtract off previous state */ 1425f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(patchUpdate, -1.0, patch->patchState)); 1431202d238SPatrick Farrell 1445f80ce2aSJacob 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) { 1555f80ce2aSJacob Faibussowitsch for (i = 0; i < patch->npatch; ++i) CHKERRQ(SNESReset((SNES) patch->solver[i])); 156561742edSMatthew G. Knepley } 1571202d238SPatrick Farrell 1585f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&patch->patchResidual)); 1595f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&patch->patchState)); 1605f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&patch->patchStateWithAll)); 16139fd2e8aSPatrick Farrell 1625f80ce2aSJacob 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) { 1735f80ce2aSJacob Faibussowitsch for (i = 0; i < patch->npatch; ++i) CHKERRQ(SNESDestroy((SNES *) &patch->solver[i])); 1745f80ce2aSJacob 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; 1845f80ce2aSJacob 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; 1975f80ce2aSJacob Faibussowitsch CHKERRQ(SNESGetDM(snes, &dm)); 1985f80ce2aSJacob Faibussowitsch CHKERRQ(PCSetDM(patch->pc, dm)); 1995f80ce2aSJacob Faibussowitsch CHKERRQ(SNESGetFunction(snes, &F, NULL, NULL)); 2005f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetLocalSize(F, &n)); 2015f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetSize(F, &N)); 2025f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateShell(PetscObjectComm((PetscObject) snes), n, n, N, N, (void *) snes, &dummy)); 2035f80ce2aSJacob Faibussowitsch CHKERRQ(PCSetOperators(patch->pc, dummy, dummy)); 2045f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&dummy)); 2055f80ce2aSJacob 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; 2155f80ce2aSJacob 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; 2245f80ce2aSJacob Faibussowitsch CHKERRQ(SNESReset_Patch(snes)); 2255f80ce2aSJacob Faibussowitsch CHKERRQ(PCDestroy(&patch->pc)); 2265f80ce2aSJacob 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; 2365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetOptionsPrefix((PetscObject)snes, &prefix)); 2375f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetOptionsPrefix((PetscObject)patch->pc, prefix)); 2385f80ce2aSJacob 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; 2485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii)); 249561742edSMatthew G. Knepley if (iascii) { 2505f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer,"SNESPATCH\n")); 251561742edSMatthew G. Knepley } 2525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPushTab(viewer)); 2535f80ce2aSJacob Faibussowitsch CHKERRQ(PCView(patch->pc, viewer)); 2545f80ce2aSJacob 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; 2705f80ce2aSJacob Faibussowitsch CHKERRQ(SNESGetSolution(snes, &state)); 2715f80ce2aSJacob Faibussowitsch CHKERRQ(SNESGetSolutionUpdate(snes, &update)); 2725f80ce2aSJacob Faibussowitsch CHKERRQ(SNESGetRhs(snes, &rhs)); 2731202d238SPatrick Farrell 2745f80ce2aSJacob Faibussowitsch CHKERRQ(SNESGetFunction(snes, &residual, NULL, NULL)); 2755f80ce2aSJacob Faibussowitsch CHKERRQ(SNESGetLineSearch(snes, &ls)); 276636c62a6SPatrick Farrell 2775f80ce2aSJacob Faibussowitsch CHKERRQ(SNESSetConvergedReason(snes, SNES_CONVERGED_ITERATING)); 2785f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(update, 0.0)); 2795f80ce2aSJacob Faibussowitsch CHKERRQ(SNESComputeFunction(snes, state, residual)); 280636c62a6SPatrick Farrell 2815f80ce2aSJacob Faibussowitsch CHKERRQ(VecNorm(state, NORM_2, &xnorm)); 2825f80ce2aSJacob Faibussowitsch CHKERRQ(VecNorm(residual, NORM_2, &fnorm)); 283636c62a6SPatrick Farrell snes->ttol = fnorm*snes->rtol; 284636c62a6SPatrick Farrell 285636c62a6SPatrick Farrell if (snes->ops->converged) { 2865f80ce2aSJacob Faibussowitsch CHKERRQ((*snes->ops->converged)(snes,its,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP)); 287636c62a6SPatrick Farrell } else { 2885f80ce2aSJacob Faibussowitsch CHKERRQ(SNESConvergedSkip(snes,its,xnorm,ynorm,fnorm,&snes->reason,NULL)); 289636c62a6SPatrick Farrell } 2905f80ce2aSJacob Faibussowitsch CHKERRQ(SNESLogConvergenceHistory(snes, fnorm, 0)); /* should we count lits from the patches? */ 2915f80ce2aSJacob 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 2965f80ce2aSJacob 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. */ 3015f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(state, &globalState)); 3025f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(pcpatch->localState, &localState)); 3035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastBegin(pcpatch->sectionSF, MPIU_SCALAR, globalState, localState,MPI_REPLACE)); 3045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastEnd(pcpatch->sectionSF, MPIU_SCALAR, globalState, localState,MPI_REPLACE)); 3055f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(pcpatch->localState, &localState)); 3065f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(state, &globalState)); 3071202d238SPatrick Farrell 308636c62a6SPatrick Farrell /* The looping over patches happens here */ 3095f80ce2aSJacob 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 */ 3145f80ce2aSJacob Faibussowitsch CHKERRQ(VecScale(update, -1.0)); 3155f80ce2aSJacob Faibussowitsch CHKERRQ(SNESLineSearchApply(ls, state, residual, &fnorm, update)); 316636c62a6SPatrick Farrell 3175f80ce2aSJacob Faibussowitsch CHKERRQ(VecNorm(state, NORM_2, &xnorm)); 3185f80ce2aSJacob Faibussowitsch CHKERRQ(VecNorm(update, NORM_2, &ynorm)); 319636c62a6SPatrick Farrell 320636c62a6SPatrick Farrell if (snes->ops->converged) { 3215f80ce2aSJacob Faibussowitsch CHKERRQ((*snes->ops->converged)(snes,its,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP)); 322636c62a6SPatrick Farrell } else { 3235f80ce2aSJacob Faibussowitsch CHKERRQ(SNESConvergedSkip(snes,its,xnorm,ynorm,fnorm,&snes->reason,NULL)); 324636c62a6SPatrick Farrell } 3255f80ce2aSJacob Faibussowitsch CHKERRQ(SNESLogConvergenceHistory(snes, fnorm, 0)); /* FIXME: should we count lits? */ 3265f80ce2aSJacob Faibussowitsch CHKERRQ(SNESMonitor(snes, its, fnorm)); 3271202d238SPatrick Farrell } 3281202d238SPatrick Farrell 3295f80ce2aSJacob 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; 3525f80ce2aSJacob 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 3615f80ce2aSJacob Faibussowitsch CHKERRQ(SNESGetLineSearch(snes,&linesearch)); 362ec786807SJed Brown if (!((PetscObject)linesearch)->type_name) { 3635f80ce2aSJacob 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; 3705f80ce2aSJacob Faibussowitsch CHKERRQ(PCCreate(PetscObjectComm((PetscObject) snes), &patch->pc)); 3715f80ce2aSJacob 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; 3935f80ce2aSJacob Faibussowitsch CHKERRQ(SNESGetDM(snes, &dm)); 394*28b400f6SJacob Faibussowitsch PetscCheck(dm,PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONGSTATE, "DM not yet set on patch SNES"); 3955f80ce2aSJacob Faibussowitsch CHKERRQ(PCSetDM(patch->pc, dm)); 3965f80ce2aSJacob 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; 4055f80ce2aSJacob 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; 4145f80ce2aSJacob 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; 4235f80ce2aSJacob 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; 4325f80ce2aSJacob Faibussowitsch CHKERRQ(PCPatchSetCellNumbering(patch->pc, cellNumbering)); 4336c270751SPatrick Farrell PetscFunctionReturn(0); 4346c270751SPatrick Farrell } 435