1*561742edSMatthew G. Knepley /* 2*561742edSMatthew G. Knepley Defines a SNES that can consist of a collection of SNESes on patches of the domain 3*561742edSMatthew G. Knepley */ 4*561742edSMatthew G. Knepley #include <petsc/private/snesimpl.h> /*I "petscsnes.h" I*/ 5*561742edSMatthew G. Knepley #include <petsc/private/pcpatchimpl.h> /* We need internal access to PCPatch right now, until that part is moved to Plex */ 6*561742edSMatthew G. Knepley 7*561742edSMatthew G. Knepley typedef struct { 8*561742edSMatthew G. Knepley PC pc; /* The linear patch preconditioner */ 9*561742edSMatthew G. Knepley SNESCompositeType type; 10*561742edSMatthew G. Knepley } SNES_Patch; 11*561742edSMatthew G. Knepley 12*561742edSMatthew G. Knepley static PetscErrorCode SNESPatchComputeResidual_Private(SNES snes, Vec x, Vec F, void *ctx) 13*561742edSMatthew G. Knepley { 14*561742edSMatthew G. Knepley SNES patchsolver = (SNES) ctx; 15*561742edSMatthew G. Knepley SNES_Patch *patch = (SNES_Patch *) patchsolver->data; 16*561742edSMatthew G. Knepley PC_PATCH *pcpatch = (PC_PATCH *) patch->pc->data; 17*561742edSMatthew G. Knepley PetscErrorCode ierr; 18*561742edSMatthew G. Knepley 19*561742edSMatthew G. Knepley PetscFunctionBegin; 20*561742edSMatthew G. Knepley ierr = PCPatchComputeFunction_Internal(patch->pc, x, F, pcpatch->currentPatch);CHKERRQ(ierr); 21*561742edSMatthew G. Knepley PetscFunctionReturn(0); 22*561742edSMatthew G. Knepley } 23*561742edSMatthew G. Knepley 24*561742edSMatthew G. Knepley static PetscErrorCode SNESPatchComputeJacobian_Private(SNES snes, Vec x, Mat J, Mat M, void *ctx) 25*561742edSMatthew G. Knepley { 26*561742edSMatthew G. Knepley SNES patchsolver = (SNES) ctx; 27*561742edSMatthew G. Knepley SNES_Patch *patch = (SNES_Patch *) patchsolver->data; 28*561742edSMatthew G. Knepley PC_PATCH *pcpatch = (PC_PATCH *) patch->pc->data; 29*561742edSMatthew G. Knepley PetscErrorCode ierr; 30*561742edSMatthew G. Knepley 31*561742edSMatthew G. Knepley PetscFunctionBegin; 32*561742edSMatthew G. Knepley ierr = PCPatchComputeOperator_Internal(patch->pc, x, M, pcpatch->currentPatch);CHKERRQ(ierr); 33*561742edSMatthew G. Knepley PetscFunctionReturn(0); 34*561742edSMatthew G. Knepley } 35*561742edSMatthew G. Knepley 36*561742edSMatthew G. Knepley static PetscErrorCode PCSetUp_PATCH_Nonlinear(PC pc) 37*561742edSMatthew G. Knepley { 38*561742edSMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *) pc->data; 39*561742edSMatthew G. Knepley const char *prefix; 40*561742edSMatthew G. Knepley PetscInt i; 41*561742edSMatthew G. Knepley PetscErrorCode ierr; 42*561742edSMatthew G. Knepley 43*561742edSMatthew G. Knepley PetscFunctionBegin; 44*561742edSMatthew G. Knepley if (!pc->setupcalled) { 45*561742edSMatthew G. Knepley ierr = PetscMalloc1(patch->npatch, &patch->solver);CHKERRQ(ierr); 46*561742edSMatthew G. Knepley ierr = PCGetOptionsPrefix(pc, &prefix);CHKERRQ(ierr); 47*561742edSMatthew G. Knepley for (i = 0; i < patch->npatch; ++i) { 48*561742edSMatthew G. Knepley SNES snes; 49*561742edSMatthew G. Knepley KSP subksp; 50*561742edSMatthew G. Knepley 51*561742edSMatthew G. Knepley ierr = SNESCreate(PETSC_COMM_SELF, &snes);CHKERRQ(ierr); 52*561742edSMatthew G. Knepley ierr = SNESSetOptionsPrefix(snes, prefix);CHKERRQ(ierr); 53*561742edSMatthew G. Knepley ierr = SNESAppendOptionsPrefix(snes, "sub_");CHKERRQ(ierr); 54*561742edSMatthew G. Knepley ierr = PetscObjectIncrementTabLevel((PetscObject) snes, (PetscObject) pc, 1);CHKERRQ(ierr); 55*561742edSMatthew G. Knepley ierr = SNESGetKSP(snes, &subksp);CHKERRQ(ierr); 56*561742edSMatthew G. Knepley ierr = PetscObjectIncrementTabLevel((PetscObject) subksp, (PetscObject) pc, 1);CHKERRQ(ierr); 57*561742edSMatthew G. Knepley ierr = PetscLogObjectParent((PetscObject) pc, (PetscObject) snes);CHKERRQ(ierr); 58*561742edSMatthew G. Knepley patch->solver[i] = (PetscObject) snes; 59*561742edSMatthew G. Knepley } 60*561742edSMatthew G. Knepley } 61*561742edSMatthew G. Knepley for (i = 0; i < patch->npatch; ++i) { 62*561742edSMatthew G. Knepley SNES snes = (SNES) patch->solver[i]; 63*561742edSMatthew G. Knepley 64*561742edSMatthew G. Knepley ierr = SNESSetFunction(snes, patch->patchX[i], SNESPatchComputeResidual_Private, snes);CHKERRQ(ierr); 65*561742edSMatthew G. Knepley ierr = SNESSetJacobian(snes, patch->mat[i], patch->mat[i], SNESPatchComputeJacobian_Private, snes);CHKERRQ(ierr); 66*561742edSMatthew G. Knepley } 67*561742edSMatthew G. Knepley if (!pc->setupcalled && patch->optionsSet) for (i = 0; i < patch->npatch; ++i) {ierr = SNESSetFromOptions((SNES) patch->solver[i]);CHKERRQ(ierr);} 68*561742edSMatthew G. Knepley PetscFunctionReturn(0); 69*561742edSMatthew G. Knepley } 70*561742edSMatthew G. Knepley 71*561742edSMatthew G. Knepley static PetscErrorCode PCApply_PATCH_Nonlinear(PC pc, PetscInt i, Vec x, Vec y) 72*561742edSMatthew G. Knepley { 73*561742edSMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *) pc->data; 74*561742edSMatthew G. Knepley PetscErrorCode ierr; 75*561742edSMatthew G. Knepley 76*561742edSMatthew G. Knepley PetscFunctionBegin; 77*561742edSMatthew G. Knepley patch->currentPatch = i; 78*561742edSMatthew G. Knepley ierr = PetscLogEventBegin(PC_Patch_Solve, pc, 0, 0, 0);CHKERRQ(ierr); 79*561742edSMatthew G. Knepley ierr = SNESSolve((SNES) patch->solver[i], x, y);CHKERRQ(ierr); 80*561742edSMatthew G. Knepley ierr = PetscLogEventEnd(PC_Patch_Solve, pc, 0, 0, 0);CHKERRQ(ierr); 81*561742edSMatthew G. Knepley PetscFunctionReturn(0); 82*561742edSMatthew G. Knepley } 83*561742edSMatthew G. Knepley 84*561742edSMatthew G. Knepley static PetscErrorCode PCReset_PATCH_Nonlinear(PC pc) 85*561742edSMatthew G. Knepley { 86*561742edSMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *) pc->data; 87*561742edSMatthew G. Knepley PetscInt i; 88*561742edSMatthew G. Knepley PetscErrorCode ierr; 89*561742edSMatthew G. Knepley 90*561742edSMatthew G. Knepley PetscFunctionBegin; 91*561742edSMatthew G. Knepley if (patch->solver) { 92*561742edSMatthew G. Knepley for (i = 0; i < patch->npatch; ++i) {ierr = SNESReset((SNES) patch->solver[i]);CHKERRQ(ierr);} 93*561742edSMatthew G. Knepley } 94*561742edSMatthew G. Knepley PetscFunctionReturn(0); 95*561742edSMatthew G. Knepley } 96*561742edSMatthew G. Knepley 97*561742edSMatthew G. Knepley static PetscErrorCode PCDestroy_PATCH_Nonlinear(PC pc) 98*561742edSMatthew G. Knepley { 99*561742edSMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *) pc->data; 100*561742edSMatthew G. Knepley PetscInt i; 101*561742edSMatthew G. Knepley PetscErrorCode ierr; 102*561742edSMatthew G. Knepley 103*561742edSMatthew G. Knepley PetscFunctionBegin; 104*561742edSMatthew G. Knepley if (patch->solver) { 105*561742edSMatthew G. Knepley for (i = 0; i < patch->npatch; ++i) {ierr = SNESDestroy((SNES *) &patch->solver[i]);CHKERRQ(ierr);} 106*561742edSMatthew G. Knepley ierr = PetscFree(patch->solver);CHKERRQ(ierr); 107*561742edSMatthew G. Knepley } 108*561742edSMatthew G. Knepley PetscFunctionReturn(0); 109*561742edSMatthew G. Knepley } 110*561742edSMatthew G. Knepley 111*561742edSMatthew G. Knepley static PetscErrorCode SNESSetUp_Patch(SNES snes) 112*561742edSMatthew G. Knepley { 113*561742edSMatthew G. Knepley SNES_Patch *patch = (SNES_Patch *) snes->data; 114*561742edSMatthew G. Knepley DM dm; 115*561742edSMatthew G. Knepley Mat dummy; 116*561742edSMatthew G. Knepley Vec F; 117*561742edSMatthew G. Knepley PetscInt n, N; 118*561742edSMatthew G. Knepley PetscErrorCode ierr; 119*561742edSMatthew G. Knepley 120*561742edSMatthew G. Knepley PetscFunctionBegin; 121*561742edSMatthew G. Knepley ierr = SNESGetDM(snes, &dm);CHKERRQ(ierr); 122*561742edSMatthew G. Knepley ierr = PCSetDM(patch->pc, dm);CHKERRQ(ierr); 123*561742edSMatthew G. Knepley ierr = SNESGetFunction(snes, &F, NULL, NULL);CHKERRQ(ierr); 124*561742edSMatthew G. Knepley ierr = VecGetLocalSize(F, &n);CHKERRQ(ierr); 125*561742edSMatthew G. Knepley ierr = VecGetSize(F, &N);CHKERRQ(ierr); 126*561742edSMatthew G. Knepley ierr = MatCreateShell(PetscObjectComm((PetscObject) snes), n, n, N, N, (void *) snes, &dummy);CHKERRQ(ierr); 127*561742edSMatthew G. Knepley ierr = PCSetOperators(patch->pc, dummy, dummy);CHKERRQ(ierr); 128*561742edSMatthew G. Knepley ierr = MatDestroy(&dummy);CHKERRQ(ierr); 129*561742edSMatthew G. Knepley ierr = PCSetUp(patch->pc);CHKERRQ(ierr); 130*561742edSMatthew G. Knepley /* allocate workspace */ 131*561742edSMatthew G. Knepley PetscFunctionReturn(0); 132*561742edSMatthew G. Knepley } 133*561742edSMatthew G. Knepley 134*561742edSMatthew G. Knepley static PetscErrorCode SNESReset_Patch(SNES snes) 135*561742edSMatthew G. Knepley { 136*561742edSMatthew G. Knepley SNES_Patch *patch = (SNES_Patch *) snes->data; 137*561742edSMatthew G. Knepley PetscErrorCode ierr; 138*561742edSMatthew G. Knepley 139*561742edSMatthew G. Knepley PetscFunctionBegin; 140*561742edSMatthew G. Knepley ierr = PCReset(patch->pc);CHKERRQ(ierr); 141*561742edSMatthew G. Knepley PetscFunctionReturn(0); 142*561742edSMatthew G. Knepley } 143*561742edSMatthew G. Knepley 144*561742edSMatthew G. Knepley static PetscErrorCode SNESDestroy_Patch(SNES snes) 145*561742edSMatthew G. Knepley { 146*561742edSMatthew G. Knepley SNES_Patch *patch = (SNES_Patch *) snes->data; 147*561742edSMatthew G. Knepley PetscErrorCode ierr; 148*561742edSMatthew G. Knepley 149*561742edSMatthew G. Knepley PetscFunctionBegin; 150*561742edSMatthew G. Knepley ierr = SNESReset_Patch(snes);CHKERRQ(ierr); 151*561742edSMatthew G. Knepley ierr = PCDestroy(&patch->pc);CHKERRQ(ierr); 152*561742edSMatthew G. Knepley ierr = PetscFree(snes->data);CHKERRQ(ierr); 153*561742edSMatthew G. Knepley PetscFunctionReturn(0); 154*561742edSMatthew G. Knepley } 155*561742edSMatthew G. Knepley 156*561742edSMatthew G. Knepley static PetscErrorCode SNESSetFromOptions_Patch(PetscOptionItems *PetscOptionsObject, SNES snes) 157*561742edSMatthew G. Knepley { 158*561742edSMatthew G. Knepley SNES_Patch *patch = (SNES_Patch *) snes->data; 159*561742edSMatthew G. Knepley PetscBool flg; 160*561742edSMatthew G. Knepley PetscErrorCode ierr; 161*561742edSMatthew G. Knepley 162*561742edSMatthew G. Knepley PetscFunctionBegin; 163*561742edSMatthew G. Knepley ierr = PetscOptionsHead(PetscOptionsObject, "Patch nonlinear preconditioner options");CHKERRQ(ierr); 164*561742edSMatthew G. Knepley ierr = PetscOptionsEnum("-snes_patch_type", "Type of composition", "SNESPatchSetType", SNESCompositeTypes, (PetscEnum) patch->type, (PetscEnum *) &patch->type, &flg);CHKERRQ(ierr); 165*561742edSMatthew G. Knepley if (flg) {ierr = SNESPatchSetType(snes, patch->type);CHKERRQ(ierr);} 166*561742edSMatthew G. Knepley ierr = PetscOptionsTail();CHKERRQ(ierr); 167*561742edSMatthew G. Knepley 168*561742edSMatthew G. Knepley ierr = PCSetFromOptions(patch->pc);CHKERRQ(ierr); 169*561742edSMatthew G. Knepley PetscFunctionReturn(0); 170*561742edSMatthew G. Knepley } 171*561742edSMatthew G. Knepley 172*561742edSMatthew G. Knepley static PetscErrorCode SNESView_Patch(SNES snes,PetscViewer viewer) 173*561742edSMatthew G. Knepley { 174*561742edSMatthew G. Knepley SNES_Patch *patch = (SNES_Patch *) snes->data; 175*561742edSMatthew G. Knepley PetscBool iascii; 176*561742edSMatthew G. Knepley PetscErrorCode ierr; 177*561742edSMatthew G. Knepley 178*561742edSMatthew G. Knepley PetscFunctionBegin; 179*561742edSMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 180*561742edSMatthew G. Knepley if (iascii) { 181*561742edSMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer," type - %s\n",SNESCompositeTypes[patch->type]);CHKERRQ(ierr); 182*561742edSMatthew G. Knepley } 183*561742edSMatthew G. Knepley ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 184*561742edSMatthew G. Knepley ierr = PCView(patch->pc, viewer);CHKERRQ(ierr); 185*561742edSMatthew G. Knepley ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 186*561742edSMatthew G. Knepley PetscFunctionReturn(0); 187*561742edSMatthew G. Knepley } 188*561742edSMatthew G. Knepley 189*561742edSMatthew G. Knepley static PetscErrorCode SNESSolve_Patch(SNES snes) 190*561742edSMatthew G. Knepley { 191*561742edSMatthew G. Knepley PetscFunctionBegin; 192*561742edSMatthew G. Knepley PetscFunctionReturn(0); 193*561742edSMatthew G. Knepley } 194*561742edSMatthew G. Knepley 195*561742edSMatthew G. Knepley static PetscErrorCode SNESPatchSetType_Patch(SNES snes, SNESCompositeType type) 196*561742edSMatthew G. Knepley { 197*561742edSMatthew G. Knepley SNES_Patch *patch = (SNES_Patch *) snes->data; 198*561742edSMatthew G. Knepley 199*561742edSMatthew G. Knepley PetscFunctionBegin; 200*561742edSMatthew G. Knepley patch->type = type; 201*561742edSMatthew G. Knepley PetscFunctionReturn(0); 202*561742edSMatthew G. Knepley } 203*561742edSMatthew G. Knepley 204*561742edSMatthew G. Knepley /*MC 205*561742edSMatthew G. Knepley SNESPATCH - Build a preconditioner by composing together many nonlinear solvers on patches 206*561742edSMatthew G. Knepley 207*561742edSMatthew G. Knepley Options Database Keys: 208*561742edSMatthew G. Knepley . -snes_patch_type <type: one of additive, multiplicative, symmetric_multiplicative> - Sets composition type 209*561742edSMatthew G. Knepley 210*561742edSMatthew G. Knepley Level: intermediate 211*561742edSMatthew G. Knepley 212*561742edSMatthew G. Knepley Concepts: composing solvers 213*561742edSMatthew G. Knepley 214*561742edSMatthew G. Knepley .seealso: SNESCreate(), SNESSetType(), SNESType (for list of available types), SNES, 215*561742edSMatthew G. Knepley PCPATCH 216*561742edSMatthew G. Knepley 217*561742edSMatthew G. Knepley References: 218*561742edSMatthew G. Knepley . 1. - Peter R. Brune, Matthew G. Knepley, Barry F. Smith, and Xuemin Tu, "Composing Scalable Nonlinear Algebraic Solvers", SIAM Review, 57(4), 2015 219*561742edSMatthew G. Knepley 220*561742edSMatthew G. Knepley M*/ 221*561742edSMatthew G. Knepley PETSC_EXTERN PetscErrorCode SNESCreate_Patch(SNES snes) 222*561742edSMatthew G. Knepley { 223*561742edSMatthew G. Knepley PetscErrorCode ierr; 224*561742edSMatthew G. Knepley SNES_Patch *patch; 225*561742edSMatthew G. Knepley 226*561742edSMatthew G. Knepley PetscFunctionBegin; 227*561742edSMatthew G. Knepley ierr = PetscNewLog(snes, &patch);CHKERRQ(ierr); 228*561742edSMatthew G. Knepley 229*561742edSMatthew G. Knepley snes->ops->solve = SNESSolve_Patch; 230*561742edSMatthew G. Knepley snes->ops->setup = SNESSetUp_Patch; 231*561742edSMatthew G. Knepley snes->ops->reset = SNESReset_Patch; 232*561742edSMatthew G. Knepley snes->ops->destroy = SNESDestroy_Patch; 233*561742edSMatthew G. Knepley snes->ops->setfromoptions = SNESSetFromOptions_Patch; 234*561742edSMatthew G. Knepley snes->ops->view = SNESView_Patch; 235*561742edSMatthew G. Knepley 236*561742edSMatthew G. Knepley snes->alwayscomputesfinalresidual = PETSC_FALSE; 237*561742edSMatthew G. Knepley 238*561742edSMatthew G. Knepley snes->data = (void *) patch; 239*561742edSMatthew G. Knepley patch->type = SNES_COMPOSITE_ADDITIVE; 240*561742edSMatthew G. Knepley ierr = PCCreate(PetscObjectComm((PetscObject) snes), &patch->pc);CHKERRQ(ierr); 241*561742edSMatthew G. Knepley ierr = PCSetType(patch->pc, PCPATCH);CHKERRQ(ierr); 242*561742edSMatthew G. Knepley 243*561742edSMatthew G. Knepley ((PC_PATCH *) patch->pc->data)->setupsolver = PCSetUp_PATCH_Nonlinear; 244*561742edSMatthew G. Knepley ((PC_PATCH *) patch->pc->data)->applysolver = PCApply_PATCH_Nonlinear; 245*561742edSMatthew G. Knepley ((PC_PATCH *) patch->pc->data)->resetsolver = PCReset_PATCH_Nonlinear; 246*561742edSMatthew G. Knepley ((PC_PATCH *) patch->pc->data)->destroysolver = PCDestroy_PATCH_Nonlinear; 247*561742edSMatthew G. Knepley 248*561742edSMatthew G. Knepley ierr = PetscObjectComposeFunction((PetscObject) snes, "SNESPatchSetType_C", SNESPatchSetType_Patch);CHKERRQ(ierr); 249*561742edSMatthew G. Knepley PetscFunctionReturn(0); 250*561742edSMatthew G. Knepley } 251*561742edSMatthew G. Knepley 252*561742edSMatthew G. Knepley /*@ 253*561742edSMatthew G. Knepley SNESPatchSetType - Sets the type of composition. 254*561742edSMatthew G. Knepley 255*561742edSMatthew G. Knepley Logically Collective on SNES 256*561742edSMatthew G. Knepley 257*561742edSMatthew G. Knepley Input Parameter: 258*561742edSMatthew G. Knepley + snes - the preconditioner context 259*561742edSMatthew G. Knepley - type - SNES_COMPOSITE_ADDITIVE (default), SNES_COMPOSITE_MULTIPLICATIVE, etc. 260*561742edSMatthew G. Knepley 261*561742edSMatthew G. Knepley Options Database Key: 262*561742edSMatthew G. Knepley . -snes_composite_type <type: one of additive, multiplicative, etc> - Sets composite preconditioner type 263*561742edSMatthew G. Knepley 264*561742edSMatthew G. Knepley Level: Developer 265*561742edSMatthew G. Knepley 266*561742edSMatthew G. Knepley .keywords: SNES, set, type, composite preconditioner, additive, multiplicative 267*561742edSMatthew G. Knepley @*/ 268*561742edSMatthew G. Knepley PetscErrorCode SNESPatchSetType(SNES snes, SNESCompositeType type) 269*561742edSMatthew G. Knepley { 270*561742edSMatthew G. Knepley PetscErrorCode ierr; 271*561742edSMatthew G. Knepley 272*561742edSMatthew G. Knepley PetscFunctionBegin; 273*561742edSMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 274*561742edSMatthew G. Knepley PetscValidLogicalCollectiveEnum(snes,type, 2); 275*561742edSMatthew G. Knepley ierr = PetscTryMethod(snes, "SNESPatchSetType_C", (SNES,SNESCompositeType), (snes,type));CHKERRQ(ierr); 276*561742edSMatthew G. Knepley PetscFunctionReturn(0); 277*561742edSMatthew G. Knepley } 278