1af0996ceSBarry Smith #include <petsc/private/snesimpl.h> /*I "petscsnes.h" I*/ 2111ade9eSPeter Brune #include <petscdm.h> 3eaedb033SPeter Brune 4eaedb033SPeter Brune typedef struct { 5eaedb033SPeter Brune PetscInt n; /* local subdomains */ 6eaedb033SPeter Brune SNES *subsnes; /* nonlinear solvers for each subdomain */ 7eaedb033SPeter Brune Vec *x; /* solution vectors */ 8111ade9eSPeter Brune Vec *xl; /* solution local vectors */ 9111ade9eSPeter Brune Vec *y; /* step vectors */ 10eaedb033SPeter Brune Vec *b; /* rhs vectors */ 11f10b3e88SPatrick Farrell Vec weight; /* weighting for adding updates on overlaps, in global space */ 12111ade9eSPeter Brune VecScatter *oscatter; /* scatter from global space to the subdomain global space */ 13f10b3e88SPatrick Farrell VecScatter *oscatter_copy; /* copy of the above */ 14111ade9eSPeter Brune VecScatter *iscatter; /* scatter from global space to the nonoverlapping subdomain space */ 15111ade9eSPeter Brune VecScatter *gscatter; /* scatter from global space to the subdomain local space */ 16111ade9eSPeter Brune PCASMType type; /* ASM type */ 17111ade9eSPeter Brune PetscBool usesdm; /* use the DM for setting up the subproblems */ 18d728fb7dSPeter Brune PetscBool finaljacobian; /* compute the jacobian of the converged solution */ 19610116beSPeter Brune PetscReal damping; /* damping parameter for updates from the blocks */ 20f10b3e88SPatrick Farrell PetscBool weight_set; /* use a weight in the overlap updates */ 21b20c023fSPeter Brune 22b20c023fSPeter Brune /* logging events */ 23b20c023fSPeter Brune PetscLogEvent eventrestrictinterp; 24b20c023fSPeter Brune PetscLogEvent eventsubsolve; 25602bec5dSPeter Brune 26602bec5dSPeter Brune PetscInt fjtype; /* type of computed jacobian */ 27602bec5dSPeter Brune Vec xinit; /* initial solution in case the final jacobian type is computed as first */ 28eaedb033SPeter Brune } SNES_NASM; 29eaedb033SPeter Brune 309e5d0892SLisandro Dalcin const char *const SNESNASMTypes[] = {"NONE", "RESTRICT", "INTERPOLATE", "BASIC", "PCASMType", "PC_ASM_", NULL}; 31602bec5dSPeter Brune const char *const SNESNASMFJTypes[] = {"FINALOUTER", "FINALINNER", "INITIAL"}; 32b20c023fSPeter Brune 33d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESReset_NASM(SNES snes) 34d71ae5a4SJacob Faibussowitsch { 35eaedb033SPeter Brune SNES_NASM *nasm = (SNES_NASM *)snes->data; 36eaedb033SPeter Brune PetscInt i; 376e111a19SKarl Rupp 38eaedb033SPeter Brune PetscFunctionBegin; 39eaedb033SPeter Brune for (i = 0; i < nasm->n; i++) { 409566063dSJacob Faibussowitsch if (nasm->xl) PetscCall(VecDestroy(&nasm->xl[i])); 419566063dSJacob Faibussowitsch if (nasm->x) PetscCall(VecDestroy(&nasm->x[i])); 429566063dSJacob Faibussowitsch if (nasm->y) PetscCall(VecDestroy(&nasm->y[i])); 439566063dSJacob Faibussowitsch if (nasm->b) PetscCall(VecDestroy(&nasm->b[i])); 44eaedb033SPeter Brune 459566063dSJacob Faibussowitsch if (nasm->subsnes) PetscCall(SNESDestroy(&nasm->subsnes[i])); 469566063dSJacob Faibussowitsch if (nasm->oscatter) PetscCall(VecScatterDestroy(&nasm->oscatter[i])); 479566063dSJacob Faibussowitsch if (nasm->oscatter_copy) PetscCall(VecScatterDestroy(&nasm->oscatter_copy[i])); 489566063dSJacob Faibussowitsch if (nasm->iscatter) PetscCall(VecScatterDestroy(&nasm->iscatter[i])); 499566063dSJacob Faibussowitsch if (nasm->gscatter) PetscCall(VecScatterDestroy(&nasm->gscatter[i])); 50eaedb033SPeter Brune } 51111ade9eSPeter Brune 529566063dSJacob Faibussowitsch PetscCall(PetscFree(nasm->x)); 539566063dSJacob Faibussowitsch PetscCall(PetscFree(nasm->xl)); 549566063dSJacob Faibussowitsch PetscCall(PetscFree(nasm->y)); 559566063dSJacob Faibussowitsch PetscCall(PetscFree(nasm->b)); 56111ade9eSPeter Brune 579566063dSJacob Faibussowitsch if (nasm->xinit) PetscCall(VecDestroy(&nasm->xinit)); 58602bec5dSPeter Brune 599566063dSJacob Faibussowitsch PetscCall(PetscFree(nasm->subsnes)); 609566063dSJacob Faibussowitsch PetscCall(PetscFree(nasm->oscatter)); 619566063dSJacob Faibussowitsch PetscCall(PetscFree(nasm->oscatter_copy)); 629566063dSJacob Faibussowitsch PetscCall(PetscFree(nasm->iscatter)); 639566063dSJacob Faibussowitsch PetscCall(PetscFree(nasm->gscatter)); 64b20c023fSPeter Brune 6548a46eb9SPierre Jolivet if (nasm->weight_set) PetscCall(VecDestroy(&nasm->weight)); 66f10b3e88SPatrick Farrell 67b20c023fSPeter Brune nasm->eventrestrictinterp = 0; 68b20c023fSPeter Brune nasm->eventsubsolve = 0; 693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 70eaedb033SPeter Brune } 71eaedb033SPeter Brune 72d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESDestroy_NASM(SNES snes) 73d71ae5a4SJacob Faibussowitsch { 74eaedb033SPeter Brune PetscFunctionBegin; 759566063dSJacob Faibussowitsch PetscCall(SNESReset_NASM(snes)); 762e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMSetType_C", NULL)); 772e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMGetType_C", NULL)); 782e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMSetSubdomains_C", NULL)); 792e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMGetSubdomains_C", NULL)); 802e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMSetDamping_C", NULL)); 812e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMGetDamping_C", NULL)); 822e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMGetSubdomainVecs_C", NULL)); 832e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMSetComputeFinalJacobian_C", NULL)); 849566063dSJacob Faibussowitsch PetscCall(PetscFree(snes->data)); 853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 86eaedb033SPeter Brune } 87eaedb033SPeter Brune 88*2a8381b2SBarry Smith static PetscErrorCode DMGlobalToLocalSubDomainDirichletHook_Private(DM dm, Vec g, InsertMode mode, Vec l, PetscCtx ctx) 89d71ae5a4SJacob Faibussowitsch { 90111ade9eSPeter Brune Vec bcs = (Vec)ctx; 916e111a19SKarl Rupp 92111ade9eSPeter Brune PetscFunctionBegin; 939566063dSJacob Faibussowitsch PetscCall(VecCopy(bcs, l)); 943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 95111ade9eSPeter Brune } 96111ade9eSPeter Brune 97d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetUp_NASM(SNES snes) 98d71ae5a4SJacob Faibussowitsch { 99eaedb033SPeter Brune SNES_NASM *nasm = (SNES_NASM *)snes->data; 10076857b2aSPeter Brune DM dm, subdm; 101111ade9eSPeter Brune DM *subdms; 102111ade9eSPeter Brune PetscInt i; 103eaedb033SPeter Brune const char *optionsprefix; 104111ade9eSPeter Brune Vec F; 105eaedb033SPeter Brune 106eaedb033SPeter Brune PetscFunctionBegin; 107eaedb033SPeter Brune if (!nasm->subsnes) { 1089566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 1090a696f66SPeter Brune if (dm) { 110eaedb033SPeter Brune nasm->usesdm = PETSC_TRUE; 1119566063dSJacob Faibussowitsch PetscCall(DMCreateDomainDecomposition(dm, &nasm->n, NULL, NULL, NULL, &subdms)); 11228b400f6SJacob Faibussowitsch PetscCheck(subdms, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM has no default decomposition defined. Set subsolves manually with SNESNASMSetSubdomains()."); 1139566063dSJacob Faibussowitsch PetscCall(DMCreateDomainDecompositionScatters(dm, nasm->n, subdms, &nasm->iscatter, &nasm->oscatter, &nasm->gscatter)); 1149566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nasm->n, &nasm->oscatter_copy)); 11548a46eb9SPierre Jolivet for (i = 0; i < nasm->n; i++) PetscCall(VecScatterCopy(nasm->oscatter[i], &nasm->oscatter_copy[i])); 116eaedb033SPeter Brune 1179566063dSJacob Faibussowitsch PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 1189566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nasm->n, &nasm->subsnes)); 119111ade9eSPeter Brune for (i = 0; i < nasm->n; i++) { 120de54d9edSStefano Zampini PetscCall(SNESCreate(PetscObjectComm((PetscObject)subdms[i]), &nasm->subsnes[i])); 1219566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)nasm->subsnes[i], (PetscObject)snes, 1)); 1229566063dSJacob Faibussowitsch PetscCall(SNESAppendOptionsPrefix(nasm->subsnes[i], optionsprefix)); 1239566063dSJacob Faibussowitsch PetscCall(SNESAppendOptionsPrefix(nasm->subsnes[i], "sub_")); 1249566063dSJacob Faibussowitsch PetscCall(SNESSetDM(nasm->subsnes[i], subdms[i])); 125*2a8381b2SBarry Smith if (snes->ops->ctxcompute) { 126*2a8381b2SBarry Smith PetscCall(SNESSetComputeApplicationContext(nasm->subsnes[i], snes->ops->ctxcompute, snes->ops->ctxdestroy)); 1272891b2c6SStefano Zampini } else { 128*2a8381b2SBarry Smith PetscCtx ctx; 1292891b2c6SStefano Zampini 1302891b2c6SStefano Zampini PetscCall(SNESGetApplicationContext(snes, &ctx)); 1312891b2c6SStefano Zampini PetscCall(SNESSetApplicationContext(nasm->subsnes[i], ctx)); 1322891b2c6SStefano Zampini } 1339566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(nasm->subsnes[i])); 1349566063dSJacob Faibussowitsch PetscCall(DMDestroy(&subdms[i])); 135111ade9eSPeter Brune } 1369566063dSJacob Faibussowitsch PetscCall(PetscFree(subdms)); 137ce94432eSBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONGSTATE, "Cannot construct local problems automatically without a DM!"); 138ce94432eSBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONGSTATE, "Must set subproblems manually if there is no DM!"); 139111ade9eSPeter Brune /* allocate the global vectors */ 14048a46eb9SPierre Jolivet if (!nasm->x) PetscCall(PetscCalloc1(nasm->n, &nasm->x)); 14148a46eb9SPierre Jolivet if (!nasm->xl) PetscCall(PetscCalloc1(nasm->n, &nasm->xl)); 14248a46eb9SPierre Jolivet if (!nasm->y) PetscCall(PetscCalloc1(nasm->n, &nasm->y)); 14348a46eb9SPierre Jolivet if (!nasm->b) PetscCall(PetscCalloc1(nasm->n, &nasm->b)); 144111ade9eSPeter Brune 145111ade9eSPeter Brune for (i = 0; i < nasm->n; i++) { 1469566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(nasm->subsnes[i], &F, NULL, NULL)); 1479566063dSJacob Faibussowitsch if (!nasm->x[i]) PetscCall(VecDuplicate(F, &nasm->x[i])); 1489566063dSJacob Faibussowitsch if (!nasm->y[i]) PetscCall(VecDuplicate(F, &nasm->y[i])); 1499566063dSJacob Faibussowitsch if (!nasm->b[i]) PetscCall(VecDuplicate(F, &nasm->b[i])); 15076857b2aSPeter Brune if (!nasm->xl[i]) { 1519566063dSJacob Faibussowitsch PetscCall(SNESGetDM(nasm->subsnes[i], &subdm)); 1529566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(subdm, &nasm->xl[i])); 1539566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalHookAdd(subdm, DMGlobalToLocalSubDomainDirichletHook_Private, NULL, nasm->xl[i])); 154111ade9eSPeter Brune } 15561ba4676SBarry Smith } 156602bec5dSPeter Brune if (nasm->finaljacobian) { 1579566063dSJacob Faibussowitsch PetscCall(SNESSetUpMatrices(snes)); 15848a46eb9SPierre Jolivet if (nasm->fjtype == 2) PetscCall(VecDuplicate(snes->vec_sol, &nasm->xinit)); 15948a46eb9SPierre Jolivet for (i = 0; i < nasm->n; i++) PetscCall(SNESSetUpMatrices(nasm->subsnes[i])); 160602bec5dSPeter Brune } 1613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 162eaedb033SPeter Brune } 163eaedb033SPeter Brune 164ce78bad3SBarry Smith static PetscErrorCode SNESSetFromOptions_NASM(SNES snes, PetscOptionItems PetscOptionsObject) 165d71ae5a4SJacob Faibussowitsch { 166111ade9eSPeter Brune PCASMType asmtype; 16783dc3634SPierre Jolivet PetscBool flg, monflg; 168111ade9eSPeter Brune SNES_NASM *nasm = (SNES_NASM *)snes->data; 1696e111a19SKarl Rupp 170eaedb033SPeter Brune PetscFunctionBegin; 171d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "Nonlinear Additive Schwarz options"); 1729566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-snes_nasm_type", "Type of restriction/extension", "", SNESNASMTypes, (PetscEnum)nasm->type, (PetscEnum *)&asmtype, &flg)); 1739566063dSJacob Faibussowitsch if (flg) PetscCall(SNESNASMSetType(snes, asmtype)); 174b20c023fSPeter Brune flg = PETSC_FALSE; 175b20c023fSPeter Brune monflg = PETSC_TRUE; 1769566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-snes_nasm_damping", "The new solution is obtained as old solution plus dmp times (sum of the solutions on the subdomains)", "SNESNASMSetDamping", nasm->damping, &nasm->damping, &flg)); 1779566063dSJacob Faibussowitsch if (flg) PetscCall(SNESNASMSetDamping(snes, nasm->damping)); 1789566063dSJacob Faibussowitsch PetscCall(PetscOptionsDeprecated("-snes_nasm_sub_view", NULL, "3.15", "Use -snes_view ::ascii_info_detail")); 1799566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_nasm_finaljacobian", "Compute the global jacobian of the final iterate (for ASPIN)", "", nasm->finaljacobian, &nasm->finaljacobian, NULL)); 1809566063dSJacob Faibussowitsch PetscCall(PetscOptionsEList("-snes_nasm_finaljacobian_type", "The type of the final jacobian computed.", "", SNESNASMFJTypes, 3, SNESNASMFJTypes[0], &nasm->fjtype, NULL)); 1819566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_nasm_log", "Log times for subSNES solves and restriction", "", monflg, &monflg, &flg)); 182b20c023fSPeter Brune if (flg) { 1839566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("SNESNASMSubSolve", ((PetscObject)snes)->classid, &nasm->eventsubsolve)); 1849566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("SNESNASMRestrict", ((PetscObject)snes)->classid, &nasm->eventrestrictinterp)); 185b20c023fSPeter Brune } 186d0609cedSBarry Smith PetscOptionsHeadEnd(); 1873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 188eaedb033SPeter Brune } 189eaedb033SPeter Brune 190d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESView_NASM(SNES snes, PetscViewer viewer) 191d71ae5a4SJacob Faibussowitsch { 192b20c023fSPeter Brune SNES_NASM *nasm = (SNES_NASM *)snes->data; 193a4f17876SPeter Brune PetscMPIInt rank, size; 194dd2fa690SBarry Smith PetscInt i, N, bsz; 1959f196a02SMartin Diehl PetscBool isascii, isstring; 196b20c023fSPeter Brune PetscViewer sviewer; 197ce94432eSBarry Smith MPI_Comm comm; 19883dc3634SPierre Jolivet PetscViewerFormat format; 19983dc3634SPierre Jolivet const char *prefix; 200b20c023fSPeter Brune 201b20c023fSPeter Brune PetscFunctionBegin; 2029566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 2039f196a02SMartin Diehl PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 2049566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 2059566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 2069566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 207462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&nasm->n, &N, 1, MPIU_INT, MPI_SUM, comm)); 2089f196a02SMartin Diehl if (isascii) { 20963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " total subdomain blocks = %" PetscInt_FMT "\n", N)); 2109566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 21183dc3634SPierre Jolivet if (format != PETSC_VIEWER_ASCII_INFO_DETAIL) { 212a4f17876SPeter Brune if (nasm->subsnes) { 2139566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Local solver information for first block on rank 0:\n")); 2149566063dSJacob Faibussowitsch PetscCall(SNESGetOptionsPrefix(snes, &prefix)); 2159566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use -%ssnes_view ::ascii_info_detail to display information for all blocks\n", prefix ? prefix : "")); 2169566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 2179566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(viewer, PETSC_COMM_SELF, &sviewer)); 218dd400576SPatrick Sanan if (rank == 0) { 219b4025f61SBarry Smith PetscCall(PetscViewerASCIIPushTab(sviewer)); 2209566063dSJacob Faibussowitsch PetscCall(SNESView(nasm->subsnes[0], sviewer)); 221b4025f61SBarry Smith PetscCall(PetscViewerASCIIPopTab(sviewer)); 222a4f17876SPeter Brune } 2239566063dSJacob Faibussowitsch PetscCall(PetscViewerRestoreSubViewer(viewer, PETSC_COMM_SELF, &sviewer)); 2249566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 225a4f17876SPeter Brune } 226a4f17876SPeter Brune } else { 227a4f17876SPeter Brune /* print the solver on each block */ 2289566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 229835f2295SStefano Zampini PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " [%d] number of local blocks = %" PetscInt_FMT "\n", rank, nasm->n)); 2309566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 2319566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 2329566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Local solver information for each block is in the following SNES objects:\n")); 2339566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 2349566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "- - - - - - - - - - - - - - - - - -\n")); 2359566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(viewer, PETSC_COMM_SELF, &sviewer)); 236a4f17876SPeter Brune for (i = 0; i < nasm->n; i++) { 2379566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(nasm->x[i], &bsz)); 238835f2295SStefano Zampini PetscCall(PetscViewerASCIIPrintf(sviewer, "[%d] local block number %" PetscInt_FMT ", size = %" PetscInt_FMT "\n", rank, i, bsz)); 2399566063dSJacob Faibussowitsch PetscCall(SNESView(nasm->subsnes[i], sviewer)); 2409566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(sviewer, "- - - - - - - - - - - - - - - - - -\n")); 241b20c023fSPeter Brune } 2429566063dSJacob Faibussowitsch PetscCall(PetscViewerRestoreSubViewer(viewer, PETSC_COMM_SELF, &sviewer)); 2439566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 244a4f17876SPeter Brune } 245b20c023fSPeter Brune } else if (isstring) { 24663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerStringSPrintf(viewer, " blocks=%" PetscInt_FMT ",type=%s", N, SNESNASMTypes[nasm->type])); 2479566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(viewer, PETSC_COMM_SELF, &sviewer)); 2489566063dSJacob Faibussowitsch if (nasm->subsnes && rank == 0) PetscCall(SNESView(nasm->subsnes[0], sviewer)); 2499566063dSJacob Faibussowitsch PetscCall(PetscViewerRestoreSubViewer(viewer, PETSC_COMM_SELF, &sviewer)); 250b20c023fSPeter Brune } 2513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 252eaedb033SPeter Brune } 253eaedb033SPeter Brune 254e0331734SPeter Brune /*@ 255420bcc1bSBarry Smith SNESNASMSetType - Set the type of subdomain update used for the nonlinear additive Schwarz solver `SNESNASM` 256e0331734SPeter Brune 257c3339decSBarry Smith Logically Collective 258e0331734SPeter Brune 259e0331734SPeter Brune Input Parameters: 260f6dfbefdSBarry Smith + snes - the `SNES` context 261f6dfbefdSBarry Smith - type - the type of update, `PC_ASM_BASIC` or `PC_ASM_RESTRICT` 262e0331734SPeter Brune 263420bcc1bSBarry Smith Options Database Key: 264420bcc1bSBarry Smith . -snes_nasm_type <basic,restrict> - type of subdomain update used 265420bcc1bSBarry Smith 266e0331734SPeter Brune Level: intermediate 267e0331734SPeter Brune 268420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNASM`, `SNESNASMGetType()`, `PCASMSetType()`, `PC_ASM_BASIC`, `PC_ASM_RESTRICT`, `PCASMType` 269e0331734SPeter Brune @*/ 270d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESNASMSetType(SNES snes, PCASMType type) 271d71ae5a4SJacob Faibussowitsch { 272e0331734SPeter Brune PetscFunctionBegin; 273835f2295SStefano Zampini PetscTryMethod(snes, "SNESNASMSetType_C", (SNES, PCASMType), (snes, type)); 2743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 275e0331734SPeter Brune } 276e0331734SPeter Brune 277d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESNASMSetType_NASM(SNES snes, PCASMType type) 278d71ae5a4SJacob Faibussowitsch { 279e0331734SPeter Brune SNES_NASM *nasm = (SNES_NASM *)snes->data; 280e0331734SPeter Brune 281e0331734SPeter Brune PetscFunctionBegin; 2820b121fc5SBarry Smith PetscCheck(type == PC_ASM_BASIC || type == PC_ASM_RESTRICT, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "SNESNASM only supports basic and restrict types"); 283e0331734SPeter Brune nasm->type = type; 2843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 285e0331734SPeter Brune } 286e0331734SPeter Brune 287e0331734SPeter Brune /*@ 288420bcc1bSBarry Smith SNESNASMGetType - Get the type of subdomain update used for the nonlinear additive Schwarz solver `SNESNASM` 289e0331734SPeter Brune 290c3339decSBarry Smith Logically Collective 291e0331734SPeter Brune 2922fe279fdSBarry Smith Input Parameter: 293f6dfbefdSBarry Smith . snes - the `SNES` context 294e0331734SPeter Brune 2952fe279fdSBarry Smith Output Parameter: 296e0331734SPeter Brune . type - the type of update 297e0331734SPeter Brune 298e0331734SPeter Brune Level: intermediate 299e0331734SPeter Brune 300420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNASM`, `SNESNASMSetType()`, `PCASMGetType()`, `PC_ASM_BASIC`, `PC_ASM_RESTRICT`, `PCASMType` 301e0331734SPeter Brune @*/ 302d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESNASMGetType(SNES snes, PCASMType *type) 303d71ae5a4SJacob Faibussowitsch { 304e0331734SPeter Brune PetscFunctionBegin; 305cac4c232SBarry Smith PetscUseMethod(snes, "SNESNASMGetType_C", (SNES, PCASMType *), (snes, type)); 3063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 307e0331734SPeter Brune } 308e0331734SPeter Brune 309d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESNASMGetType_NASM(SNES snes, PCASMType *type) 310d71ae5a4SJacob Faibussowitsch { 311e0331734SPeter Brune SNES_NASM *nasm = (SNES_NASM *)snes->data; 312e0331734SPeter Brune 313e0331734SPeter Brune PetscFunctionBegin; 314e0331734SPeter Brune *type = nasm->type; 3153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 316e0331734SPeter Brune } 317e0331734SPeter Brune 31876857b2aSPeter Brune /*@ 319f6dfbefdSBarry Smith SNESNASMSetSubdomains - Manually Set the context required to restrict and solve subdomain problems in the nonlinear additive Schwarz solver 32076857b2aSPeter Brune 321f6dfbefdSBarry Smith Logically Collective 32276857b2aSPeter Brune 32376857b2aSPeter Brune Input Parameters: 324420bcc1bSBarry Smith + snes - the `SNES` context 32576857b2aSPeter Brune . n - the number of local subdomains 32676857b2aSPeter Brune . subsnes - solvers defined on the local subdomains 32776857b2aSPeter Brune . iscatter - scatters into the nonoverlapping portions of the local subdomains 32876857b2aSPeter Brune . oscatter - scatters into the overlapping portions of the local subdomains 32976857b2aSPeter Brune - gscatter - scatters into the (ghosted) local vector of the local subdomain 33076857b2aSPeter Brune 33176857b2aSPeter Brune Level: intermediate 33276857b2aSPeter Brune 333420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNASM`, `SNESNASMGetSubdomains()` 33476857b2aSPeter Brune @*/ 335d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESNASMSetSubdomains(SNES snes, PetscInt n, SNES subsnes[], VecScatter iscatter[], VecScatter oscatter[], VecScatter gscatter[]) 336d71ae5a4SJacob Faibussowitsch { 337111ade9eSPeter Brune PetscErrorCode (*f)(SNES, PetscInt, SNES *, VecScatter *, VecScatter *, VecScatter *); 3386e111a19SKarl Rupp 339eaedb033SPeter Brune PetscFunctionBegin; 3409566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)snes, "SNESNASMSetSubdomains_C", &f)); 3419566063dSJacob Faibussowitsch if (f) PetscCall((f)(snes, n, subsnes, iscatter, oscatter, gscatter)); 3423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 343eaedb033SPeter Brune } 344eaedb033SPeter Brune 345d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESNASMSetSubdomains_NASM(SNES snes, PetscInt n, SNES subsnes[], VecScatter iscatter[], VecScatter oscatter[], VecScatter gscatter[]) 346d71ae5a4SJacob Faibussowitsch { 347eaedb033SPeter Brune PetscInt i; 348eaedb033SPeter Brune SNES_NASM *nasm = (SNES_NASM *)snes->data; 3496e111a19SKarl Rupp 350eaedb033SPeter Brune PetscFunctionBegin; 35128b400f6SJacob Faibussowitsch PetscCheck(!snes->setupcalled, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONGSTATE, "SNESNASMSetSubdomains() should be called before calling SNESSetUp()."); 352eaedb033SPeter Brune 353111ade9eSPeter Brune /* tear down the previously set things */ 3549566063dSJacob Faibussowitsch PetscCall(SNESReset(snes)); 355111ade9eSPeter Brune 356eaedb033SPeter Brune nasm->n = n; 357111ade9eSPeter Brune if (oscatter) { 3589566063dSJacob Faibussowitsch for (i = 0; i < n; i++) PetscCall(PetscObjectReference((PetscObject)oscatter[i])); 359eaedb033SPeter Brune } 360111ade9eSPeter Brune if (iscatter) { 3619566063dSJacob Faibussowitsch for (i = 0; i < n; i++) PetscCall(PetscObjectReference((PetscObject)iscatter[i])); 362eaedb033SPeter Brune } 363111ade9eSPeter Brune if (gscatter) { 3649566063dSJacob Faibussowitsch for (i = 0; i < n; i++) PetscCall(PetscObjectReference((PetscObject)gscatter[i])); 365111ade9eSPeter Brune } 366111ade9eSPeter Brune if (oscatter) { 3679566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &nasm->oscatter)); 3689566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &nasm->oscatter_copy)); 369eaedb033SPeter Brune for (i = 0; i < n; i++) { 370111ade9eSPeter Brune nasm->oscatter[i] = oscatter[i]; 3719566063dSJacob Faibussowitsch PetscCall(VecScatterCopy(oscatter[i], &nasm->oscatter_copy[i])); 372eaedb033SPeter Brune } 373111ade9eSPeter Brune } 374111ade9eSPeter Brune if (iscatter) { 3759566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &nasm->iscatter)); 376ad540459SPierre Jolivet for (i = 0; i < n; i++) nasm->iscatter[i] = iscatter[i]; 377eaedb033SPeter Brune } 378111ade9eSPeter Brune if (gscatter) { 3799566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &nasm->gscatter)); 380ad540459SPierre Jolivet for (i = 0; i < n; i++) nasm->gscatter[i] = gscatter[i]; 381eaedb033SPeter Brune } 382111ade9eSPeter Brune 383eaedb033SPeter Brune if (subsnes) { 3849566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &nasm->subsnes)); 385ad540459SPierre Jolivet for (i = 0; i < n; i++) nasm->subsnes[i] = subsnes[i]; 386eaedb033SPeter Brune } 3873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 388eaedb033SPeter Brune } 389eaedb033SPeter Brune 39076857b2aSPeter Brune /*@ 391f6dfbefdSBarry Smith SNESNASMGetSubdomains - Get the local subdomain contexts for the nonlinear additive Schwarz solver 39276857b2aSPeter Brune 393f6dfbefdSBarry Smith Not Collective but some of the objects returned will be parallel 39476857b2aSPeter Brune 395f899ff85SJose E. Roman Input Parameter: 396f6dfbefdSBarry Smith . snes - the `SNES` context 39776857b2aSPeter Brune 39876857b2aSPeter Brune Output Parameters: 39976857b2aSPeter Brune + n - the number of local subdomains 40076857b2aSPeter Brune . subsnes - solvers defined on the local subdomains 40176857b2aSPeter Brune . iscatter - scatters into the nonoverlapping portions of the local subdomains 40276857b2aSPeter Brune . oscatter - scatters into the overlapping portions of the local subdomains 40376857b2aSPeter Brune - gscatter - scatters into the (ghosted) local vector of the local subdomain 40476857b2aSPeter Brune 40576857b2aSPeter Brune Level: intermediate 40676857b2aSPeter Brune 407420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNASM`, `SNESNASMSetSubdomains()` 40876857b2aSPeter Brune @*/ 409d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESNASMGetSubdomains(SNES snes, PetscInt *n, SNES *subsnes[], VecScatter *iscatter[], VecScatter *oscatter[], VecScatter *gscatter[]) 410d71ae5a4SJacob Faibussowitsch { 41176857b2aSPeter Brune PetscErrorCode (*f)(SNES, PetscInt *, SNES **, VecScatter **, VecScatter **, VecScatter **); 41276857b2aSPeter Brune 41376857b2aSPeter Brune PetscFunctionBegin; 4149566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)snes, "SNESNASMGetSubdomains_C", &f)); 4159566063dSJacob Faibussowitsch if (f) PetscCall((f)(snes, n, subsnes, iscatter, oscatter, gscatter)); 4163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 41776857b2aSPeter Brune } 41876857b2aSPeter Brune 419d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESNASMGetSubdomains_NASM(SNES snes, PetscInt *n, SNES *subsnes[], VecScatter *iscatter[], VecScatter *oscatter[], VecScatter *gscatter[]) 420d71ae5a4SJacob Faibussowitsch { 42176857b2aSPeter Brune SNES_NASM *nasm = (SNES_NASM *)snes->data; 42276857b2aSPeter Brune 42376857b2aSPeter Brune PetscFunctionBegin; 42476857b2aSPeter Brune if (n) *n = nasm->n; 42576857b2aSPeter Brune if (oscatter) *oscatter = nasm->oscatter; 42676857b2aSPeter Brune if (iscatter) *iscatter = nasm->iscatter; 42776857b2aSPeter Brune if (gscatter) *gscatter = nasm->gscatter; 42883dc3634SPierre Jolivet if (subsnes) *subsnes = nasm->subsnes; 4293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 43076857b2aSPeter Brune } 43176857b2aSPeter Brune 43276857b2aSPeter Brune /*@ 433f6dfbefdSBarry Smith SNESNASMGetSubdomainVecs - Get the processor-local subdomain vectors for the nonlinear additive Schwarz solver 43476857b2aSPeter Brune 43576857b2aSPeter Brune Not Collective 43676857b2aSPeter Brune 437f899ff85SJose E. Roman Input Parameter: 438f6dfbefdSBarry Smith . snes - the `SNES` context 43976857b2aSPeter Brune 44076857b2aSPeter Brune Output Parameters: 44176857b2aSPeter Brune + n - the number of local subdomains 44276857b2aSPeter Brune . x - The subdomain solution vector 44376857b2aSPeter Brune . y - The subdomain step vector 44476857b2aSPeter Brune . b - The subdomain RHS vector 44576857b2aSPeter Brune - xl - The subdomain local vectors (ghosted) 44676857b2aSPeter Brune 44776857b2aSPeter Brune Level: developer 44876857b2aSPeter Brune 449420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNASM`, `SNESNASMGetSubdomains()` 45076857b2aSPeter Brune @*/ 451ce78bad3SBarry Smith PetscErrorCode SNESNASMGetSubdomainVecs(SNES snes, PetscInt *n, Vec *x[], Vec *y[], Vec *b[], Vec *xl[]) 452d71ae5a4SJacob Faibussowitsch { 45376857b2aSPeter Brune PetscErrorCode (*f)(SNES, PetscInt *, Vec **, Vec **, Vec **, Vec **); 45476857b2aSPeter Brune 45576857b2aSPeter Brune PetscFunctionBegin; 4569566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)snes, "SNESNASMGetSubdomainVecs_C", &f)); 4579566063dSJacob Faibussowitsch if (f) PetscCall((f)(snes, n, x, y, b, xl)); 4583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 45976857b2aSPeter Brune } 46076857b2aSPeter Brune 461d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESNASMGetSubdomainVecs_NASM(SNES snes, PetscInt *n, Vec **x, Vec **y, Vec **b, Vec **xl) 462d71ae5a4SJacob Faibussowitsch { 46376857b2aSPeter Brune SNES_NASM *nasm = (SNES_NASM *)snes->data; 46476857b2aSPeter Brune 46576857b2aSPeter Brune PetscFunctionBegin; 46676857b2aSPeter Brune if (n) *n = nasm->n; 46776857b2aSPeter Brune if (x) *x = nasm->x; 46876857b2aSPeter Brune if (y) *y = nasm->y; 46976857b2aSPeter Brune if (b) *b = nasm->b; 47076857b2aSPeter Brune if (xl) *xl = nasm->xl; 4713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 47276857b2aSPeter Brune } 47376857b2aSPeter Brune 474d728fb7dSPeter Brune /*@ 475f6dfbefdSBarry Smith SNESNASMSetComputeFinalJacobian - Schedules the computation of the global and subdomain Jacobians upon convergence for the 476f6dfbefdSBarry Smith nonlinear additive Schwarz solver 477d728fb7dSPeter Brune 478c3339decSBarry Smith Collective 479d728fb7dSPeter Brune 480d728fb7dSPeter Brune Input Parameters: 481f6dfbefdSBarry Smith + snes - the SNES context 482f6dfbefdSBarry Smith - flg - `PETSC_TRUE` to compute the Jacobians 483d728fb7dSPeter Brune 484d728fb7dSPeter Brune Level: developer 485d728fb7dSPeter Brune 48695452b02SPatrick Sanan Notes: 487f6dfbefdSBarry Smith This is used almost exclusively in the implementation of `SNESASPIN`, where the converged subdomain and global Jacobian 488d728fb7dSPeter Brune is needed at each linear iteration. 489d728fb7dSPeter Brune 490420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNASM`, `SNESNASMGetSubdomains()` 491d728fb7dSPeter Brune @*/ 492d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESNASMSetComputeFinalJacobian(SNES snes, PetscBool flg) 493d71ae5a4SJacob Faibussowitsch { 494d728fb7dSPeter Brune PetscErrorCode (*f)(SNES, PetscBool); 495d728fb7dSPeter Brune 496d728fb7dSPeter Brune PetscFunctionBegin; 4979566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)snes, "SNESNASMSetComputeFinalJacobian_C", &f)); 4989566063dSJacob Faibussowitsch if (f) PetscCall((f)(snes, flg)); 4993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 500d728fb7dSPeter Brune } 501d728fb7dSPeter Brune 502d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESNASMSetComputeFinalJacobian_NASM(SNES snes, PetscBool flg) 503d71ae5a4SJacob Faibussowitsch { 504d728fb7dSPeter Brune SNES_NASM *nasm = (SNES_NASM *)snes->data; 505d728fb7dSPeter Brune 506d728fb7dSPeter Brune PetscFunctionBegin; 507d728fb7dSPeter Brune nasm->finaljacobian = flg; 5083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 509d728fb7dSPeter Brune } 51076857b2aSPeter Brune 511610116beSPeter Brune /*@ 512f6dfbefdSBarry Smith SNESNASMSetDamping - Sets the update damping for `SNESNASM` the nonlinear additive Schwarz solver 513610116beSPeter Brune 51420f4b53cSBarry Smith Logically Collective 515610116beSPeter Brune 516610116beSPeter Brune Input Parameters: 517f6dfbefdSBarry Smith + snes - the `SNES` context 518610116beSPeter Brune - dmp - damping 519610116beSPeter Brune 520420bcc1bSBarry Smith Options Database Key: 521420bcc1bSBarry Smith . -snes_nasm_damping <dmp> - the new solution is obtained as old solution plus `dmp` times (sum of the solutions on the subdomains) 522420bcc1bSBarry Smith 523610116beSPeter Brune Level: intermediate 524610116beSPeter Brune 525420bcc1bSBarry Smith Note: 52695452b02SPatrick Sanan The new solution is obtained as old solution plus dmp times (sum of the solutions on the subdomains) 5275dfa0f3bSBarry Smith 528420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNASM`, `SNESNASMGetDamping()` 529610116beSPeter Brune @*/ 530d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESNASMSetDamping(SNES snes, PetscReal dmp) 531d71ae5a4SJacob Faibussowitsch { 532610116beSPeter Brune PetscFunctionBegin; 533835f2295SStefano Zampini PetscTryMethod(snes, "SNESNASMSetDamping_C", (SNES, PetscReal), (snes, dmp)); 5343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 535610116beSPeter Brune } 536610116beSPeter Brune 537d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESNASMSetDamping_NASM(SNES snes, PetscReal dmp) 538d71ae5a4SJacob Faibussowitsch { 539610116beSPeter Brune SNES_NASM *nasm = (SNES_NASM *)snes->data; 540610116beSPeter Brune 541610116beSPeter Brune PetscFunctionBegin; 542610116beSPeter Brune nasm->damping = dmp; 5433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 544610116beSPeter Brune } 545610116beSPeter Brune 546610116beSPeter Brune /*@ 547f6dfbefdSBarry Smith SNESNASMGetDamping - Gets the update damping for `SNESNASM` the nonlinear additive Schwarz solver 548610116beSPeter Brune 549610116beSPeter Brune Not Collective 550610116beSPeter Brune 551f6dfbefdSBarry Smith Input Parameter: 552420bcc1bSBarry Smith . snes - the `SNES` context 553f6dfbefdSBarry Smith 554f6dfbefdSBarry Smith Output Parameter: 555f6dfbefdSBarry Smith . dmp - damping 556610116beSPeter Brune 557610116beSPeter Brune Level: intermediate 558610116beSPeter Brune 559420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNASM`, `SNESNASMSetDamping()` 560610116beSPeter Brune @*/ 561d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESNASMGetDamping(SNES snes, PetscReal *dmp) 562d71ae5a4SJacob Faibussowitsch { 563610116beSPeter Brune PetscFunctionBegin; 564cac4c232SBarry Smith PetscUseMethod(snes, "SNESNASMGetDamping_C", (SNES, PetscReal *), (snes, dmp)); 5653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 566610116beSPeter Brune } 567610116beSPeter Brune 568d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESNASMGetDamping_NASM(SNES snes, PetscReal *dmp) 569d71ae5a4SJacob Faibussowitsch { 570610116beSPeter Brune SNES_NASM *nasm = (SNES_NASM *)snes->data; 571610116beSPeter Brune 572610116beSPeter Brune PetscFunctionBegin; 573610116beSPeter Brune *dmp = nasm->damping; 5743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 575610116beSPeter Brune } 576610116beSPeter Brune 57714eb1c5cSMatthew G. Knepley /* 57814eb1c5cSMatthew G. Knepley Input Parameters: 57914eb1c5cSMatthew G. Knepley + snes - The solver 58014eb1c5cSMatthew G. Knepley . B - The RHS vector 58114eb1c5cSMatthew G. Knepley - X - The initial guess 58214eb1c5cSMatthew G. Knepley 5832fe279fdSBarry Smith Output Parameter: 58414eb1c5cSMatthew G. Knepley . Y - The solution update 58514eb1c5cSMatthew G. Knepley 58614eb1c5cSMatthew G. Knepley TODO: All scatters should be packed into one 58714eb1c5cSMatthew G. Knepley */ 58866976f2fSJacob Faibussowitsch static PetscErrorCode SNESNASMSolveLocal_Private(SNES snes, Vec B, Vec Y, Vec X) 589d71ae5a4SJacob Faibussowitsch { 590eaedb033SPeter Brune SNES_NASM *nasm = (SNES_NASM *)snes->data; 591258e1594SPeter Brune SNES subsnes; 592eaedb033SPeter Brune PetscInt i; 593610116beSPeter Brune PetscReal dmp; 594f10b3e88SPatrick Farrell Vec Xl, Bl, Yl, Xlloc; 595f10b3e88SPatrick Farrell VecScatter iscat, oscat, gscat, oscat_copy; 596111ade9eSPeter Brune DM dm, subdm; 597e0331734SPeter Brune PCASMType type; 5980adebc6cSBarry Smith 599eaedb033SPeter Brune PetscFunctionBegin; 6009566063dSJacob Faibussowitsch PetscCall(SNESNASMGetType(snes, &type)); 6019566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 6029566063dSJacob Faibussowitsch PetscCall(VecSet(Y, 0)); 6039566063dSJacob Faibussowitsch if (nasm->eventrestrictinterp) PetscCall(PetscLogEventBegin(nasm->eventrestrictinterp, snes, 0, 0, 0)); 604de54d9edSStefano Zampini for (i = 0; i < nasm->n; i++) { /* scatter the global solution to the overlap solution and the local solution */ 605f10b3e88SPatrick Farrell Xl = nasm->x[i]; 60670c78f05SPeter Brune Xlloc = nasm->xl[i]; 60770c78f05SPeter Brune oscat = nasm->oscatter[i]; 608f10b3e88SPatrick Farrell oscat_copy = nasm->oscatter_copy[i]; 609f10b3e88SPatrick Farrell gscat = nasm->gscatter[i]; 6109566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(oscat, X, Xl, INSERT_VALUES, SCATTER_FORWARD)); 6119566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(gscat, X, Xlloc, INSERT_VALUES, SCATTER_FORWARD)); 612de54d9edSStefano Zampini 61370c78f05SPeter Brune if (B) { 61470c78f05SPeter Brune /* scatter the RHS to the local RHS */ 61570c78f05SPeter Brune Bl = nasm->b[i]; 6169566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(oscat_copy, B, Bl, INSERT_VALUES, SCATTER_FORWARD)); 61770c78f05SPeter Brune } 61870c78f05SPeter Brune } 6199566063dSJacob Faibussowitsch if (nasm->eventrestrictinterp) PetscCall(PetscLogEventEnd(nasm->eventrestrictinterp, snes, 0, 0, 0)); 620b20c023fSPeter Brune 6219566063dSJacob Faibussowitsch if (nasm->eventsubsolve) PetscCall(PetscLogEventBegin(nasm->eventsubsolve, snes, 0, 0, 0)); 62270c78f05SPeter Brune for (i = 0; i < nasm->n; i++) { 623de54d9edSStefano Zampini PetscErrorCode (*bl)(DM, Vec, void *); 624de54d9edSStefano Zampini void *bctx; 625de54d9edSStefano Zampini 62670c78f05SPeter Brune Xl = nasm->x[i]; 62770c78f05SPeter Brune Xlloc = nasm->xl[i]; 62870c78f05SPeter Brune Yl = nasm->y[i]; 629258e1594SPeter Brune subsnes = nasm->subsnes[i]; 6309566063dSJacob Faibussowitsch PetscCall(SNESGetDM(subsnes, &subdm)); 631111ade9eSPeter Brune iscat = nasm->iscatter[i]; 632111ade9eSPeter Brune oscat = nasm->oscatter[i]; 633f10b3e88SPatrick Farrell oscat_copy = nasm->oscatter_copy[i]; 634111ade9eSPeter Brune gscat = nasm->gscatter[i]; 6359566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(oscat, X, Xl, INSERT_VALUES, SCATTER_FORWARD)); 6369566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(gscat, X, Xlloc, INSERT_VALUES, SCATTER_FORWARD)); 63724b7f281SPeter Brune if (B) { 63824b7f281SPeter Brune Bl = nasm->b[i]; 6399566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(oscat_copy, B, Bl, INSERT_VALUES, SCATTER_FORWARD)); 640ed3c11a9SPeter Brune } else Bl = NULL; 641f10b3e88SPatrick Farrell 642de54d9edSStefano Zampini PetscCall(SNESGetDM(subsnes, &subdm)); 643de54d9edSStefano Zampini PetscCall(DMSNESGetBoundaryLocal(subdm, &bl, &bctx)); 644de54d9edSStefano Zampini if (bl) PetscCall((*bl)(subdm, Xlloc, bctx)); 645de54d9edSStefano Zampini 6469566063dSJacob Faibussowitsch PetscCall(DMSubDomainRestrict(dm, oscat, gscat, subdm)); 6479566063dSJacob Faibussowitsch PetscCall(VecCopy(Xl, Yl)); 6489566063dSJacob Faibussowitsch PetscCall(SNESSolve(subsnes, Bl, Xl)); 6499566063dSJacob Faibussowitsch PetscCall(VecAYPX(Yl, -1.0, Xl)); 6509566063dSJacob Faibussowitsch PetscCall(VecScale(Yl, nasm->damping)); 651e0331734SPeter Brune if (type == PC_ASM_BASIC) { 6529566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(oscat, Yl, Y, ADD_VALUES, SCATTER_REVERSE)); 6539566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(oscat, Yl, Y, ADD_VALUES, SCATTER_REVERSE)); 654e0331734SPeter Brune } else if (type == PC_ASM_RESTRICT) { 6559566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(iscat, Yl, Y, ADD_VALUES, SCATTER_REVERSE)); 6569566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(iscat, Yl, Y, ADD_VALUES, SCATTER_REVERSE)); 657ce94432eSBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONGSTATE, "Only basic and restrict types are supported for SNESNASM"); 658eaedb033SPeter Brune } 6599566063dSJacob Faibussowitsch if (nasm->eventsubsolve) PetscCall(PetscLogEventEnd(nasm->eventsubsolve, snes, 0, 0, 0)); 6609566063dSJacob Faibussowitsch if (nasm->eventrestrictinterp) PetscCall(PetscLogEventBegin(nasm->eventrestrictinterp, snes, 0, 0, 0)); 6611baa6e33SBarry Smith if (nasm->weight_set) PetscCall(VecPointwiseMult(Y, Y, nasm->weight)); 6629566063dSJacob Faibussowitsch if (nasm->eventrestrictinterp) PetscCall(PetscLogEventEnd(nasm->eventrestrictinterp, snes, 0, 0, 0)); 6639566063dSJacob Faibussowitsch PetscCall(SNESNASMGetDamping(snes, &dmp)); 6649566063dSJacob Faibussowitsch PetscCall(VecAXPY(X, dmp, Y)); 6653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 666eaedb033SPeter Brune } 667eaedb033SPeter Brune 668d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESNASMComputeFinalJacobian_Private(SNES snes, Vec Xfinal) 669d71ae5a4SJacob Faibussowitsch { 670602bec5dSPeter Brune Vec X = Xfinal; 671d728fb7dSPeter Brune SNES_NASM *nasm = (SNES_NASM *)snes->data; 672d728fb7dSPeter Brune SNES subsnes; 673ca44f815SPeter Brune PetscInt i, lag = 1; 674e59f0a30SPeter Brune Vec Xlloc, Xl, Fl, F; 675d728fb7dSPeter Brune VecScatter oscat, gscat; 676d728fb7dSPeter Brune DM dm, subdm; 677d1e9a80fSBarry Smith 678d728fb7dSPeter Brune PetscFunctionBegin; 679602bec5dSPeter Brune if (nasm->fjtype == 2) X = nasm->xinit; 680e59f0a30SPeter Brune F = snes->vec_func; 6819566063dSJacob Faibussowitsch if (snes->normschedule == SNES_NORM_NONE) PetscCall(SNESComputeFunction(snes, X, F)); 6829566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobian(snes, X, snes->jacobian, snes->jacobian_pre)); 68376c63389SBarry Smith SNESCheckJacobianDomainError(snes); 6849566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 6859566063dSJacob Faibussowitsch if (nasm->eventrestrictinterp) PetscCall(PetscLogEventBegin(nasm->eventrestrictinterp, snes, 0, 0, 0)); 686602bec5dSPeter Brune if (nasm->fjtype != 1) { 687d728fb7dSPeter Brune for (i = 0; i < nasm->n; i++) { 688d728fb7dSPeter Brune Xlloc = nasm->xl[i]; 689d728fb7dSPeter Brune gscat = nasm->gscatter[i]; 6909566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(gscat, X, Xlloc, INSERT_VALUES, SCATTER_FORWARD)); 691602bec5dSPeter Brune } 692d728fb7dSPeter Brune } 6939566063dSJacob Faibussowitsch if (nasm->eventrestrictinterp) PetscCall(PetscLogEventEnd(nasm->eventrestrictinterp, snes, 0, 0, 0)); 694d728fb7dSPeter Brune for (i = 0; i < nasm->n; i++) { 695e59f0a30SPeter Brune Fl = nasm->subsnes[i]->vec_func; 696d728fb7dSPeter Brune Xl = nasm->x[i]; 697d728fb7dSPeter Brune Xlloc = nasm->xl[i]; 698d728fb7dSPeter Brune subsnes = nasm->subsnes[i]; 699d728fb7dSPeter Brune oscat = nasm->oscatter[i]; 700d728fb7dSPeter Brune gscat = nasm->gscatter[i]; 7019566063dSJacob Faibussowitsch if (nasm->fjtype != 1) PetscCall(VecScatterEnd(gscat, X, Xlloc, INSERT_VALUES, SCATTER_FORWARD)); 7029566063dSJacob Faibussowitsch PetscCall(SNESGetDM(subsnes, &subdm)); 7039566063dSJacob Faibussowitsch PetscCall(DMSubDomainRestrict(dm, oscat, gscat, subdm)); 704602bec5dSPeter Brune if (nasm->fjtype != 1) { 7059566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(subdm, Xlloc, INSERT_VALUES, Xl)); 7069566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(subdm, Xlloc, INSERT_VALUES, Xl)); 707602bec5dSPeter Brune } 708ca44f815SPeter Brune if (subsnes->lagjacobian == -1) subsnes->lagjacobian = -2; 709ca44f815SPeter Brune else if (subsnes->lagjacobian > 1) lag = subsnes->lagjacobian; 7109566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(subsnes, Xl, Fl)); 7119566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobian(subsnes, Xl, subsnes->jacobian, subsnes->jacobian_pre)); 712ca44f815SPeter Brune if (lag > 1) subsnes->lagjacobian = lag; 713d728fb7dSPeter Brune } 7143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 715d728fb7dSPeter Brune } 716d728fb7dSPeter Brune 717d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSolve_NASM(SNES snes) 718d71ae5a4SJacob Faibussowitsch { 719eaedb033SPeter Brune Vec F; 720eaedb033SPeter Brune Vec X; 721eaedb033SPeter Brune Vec B; 722111ade9eSPeter Brune Vec Y; 723eaedb033SPeter Brune PetscInt i; 724ed3c11a9SPeter Brune PetscReal fnorm = 0.0; 725365a6726SPeter Brune SNESNormSchedule normschedule; 726d728fb7dSPeter Brune SNES_NASM *nasm = (SNES_NASM *)snes->data; 727eaedb033SPeter Brune 728eaedb033SPeter Brune PetscFunctionBegin; 7290b121fc5SBarry Smith PetscCheck(!snes->xl & !snes->xu && !snes->ops->computevariablebounds, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONGSTATE, "SNES solver %s does not support bounds", ((PetscObject)snes)->type_name); 730c579b300SPatrick Farrell 7319566063dSJacob Faibussowitsch PetscCall(PetscCitationsRegister(SNESCitation, &SNEScite)); 732eaedb033SPeter Brune X = snes->vec_sol; 733111ade9eSPeter Brune Y = snes->vec_sol_update; 734eaedb033SPeter Brune F = snes->vec_func; 735eaedb033SPeter Brune B = snes->vec_rhs; 736eaedb033SPeter Brune 7379566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes)); 738eaedb033SPeter Brune snes->iter = 0; 739eaedb033SPeter Brune snes->norm = 0.; 7409566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes)); 741eaedb033SPeter Brune snes->reason = SNES_CONVERGED_ITERATING; 7429566063dSJacob Faibussowitsch PetscCall(SNESGetNormSchedule(snes, &normschedule)); 743de54d9edSStefano Zampini if (normschedule == SNES_NORM_ALWAYS || normschedule == SNES_NORM_INITIAL_ONLY || normschedule == SNES_NORM_INITIAL_FINAL_ONLY || !snes->max_its) { 744eaedb033SPeter Brune /* compute the initial function and preconditioned update delX */ 745ac530a7eSPierre Jolivet if (!snes->vec_func_init_set) PetscCall(SNESComputeFunction(snes, X, F)); 746ac530a7eSPierre Jolivet else snes->vec_func_init_set = PETSC_FALSE; 747eaedb033SPeter Brune 7489566063dSJacob Faibussowitsch PetscCall(VecNorm(F, NORM_2, &fnorm)); /* fnorm <- ||F|| */ 74976c63389SBarry Smith SNESCheckFunctionDomainError(snes, fnorm); 7509566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes)); 751eaedb033SPeter Brune snes->iter = 0; 752eaedb033SPeter Brune snes->norm = fnorm; 7539566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes)); 7549566063dSJacob Faibussowitsch PetscCall(SNESLogConvergenceHistory(snes, snes->norm, 0)); 755eaedb033SPeter Brune 756eaedb033SPeter Brune /* test convergence */ 7572d157150SStefano Zampini PetscCall(SNESConverged(snes, 0, 0.0, 0.0, fnorm)); 7582d157150SStefano Zampini PetscCall(SNESMonitor(snes, 0, snes->norm)); 7593ba16761SJacob Faibussowitsch if (snes->reason) PetscFunctionReturn(PETSC_SUCCESS); 760eaedb033SPeter Brune } else { 7619566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes)); 7629566063dSJacob Faibussowitsch PetscCall(SNESLogConvergenceHistory(snes, snes->norm, 0)); 7632d157150SStefano Zampini PetscCall(SNESMonitor(snes, snes->iter, snes->norm)); 764eaedb033SPeter Brune } 765eaedb033SPeter Brune 766eaedb033SPeter Brune /* Call general purpose update function */ 767dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, update, snes->iter); 768602bec5dSPeter Brune /* copy the initial solution over for later */ 7699566063dSJacob Faibussowitsch if (nasm->fjtype == 2) PetscCall(VecCopy(X, nasm->xinit)); 770eaedb033SPeter Brune 771eaedb033SPeter Brune for (i = 0; i < snes->max_its; i++) { 7729566063dSJacob Faibussowitsch PetscCall(SNESNASMSolveLocal_Private(snes, B, Y, X)); 773365a6726SPeter Brune if (normschedule == SNES_NORM_ALWAYS || ((i == snes->max_its - 1) && (normschedule == SNES_NORM_INITIAL_FINAL_ONLY || normschedule == SNES_NORM_FINAL_ONLY))) { 7749566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, X, F)); 7759566063dSJacob Faibussowitsch PetscCall(VecNorm(F, NORM_2, &fnorm)); /* fnorm <- ||F|| */ 77676c63389SBarry Smith SNESCheckFunctionDomainError(snes, fnorm); 777eaedb033SPeter Brune } 778eaedb033SPeter Brune /* Monitor convergence */ 7799566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes)); 780eaedb033SPeter Brune snes->iter = i + 1; 781eaedb033SPeter Brune snes->norm = fnorm; 7829566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes)); 7839566063dSJacob Faibussowitsch PetscCall(SNESLogConvergenceHistory(snes, snes->norm, 0)); 784eaedb033SPeter Brune /* Test for convergence */ 7852d157150SStefano Zampini PetscCall(SNESConverged(snes, snes->iter, 0.0, 0.0, fnorm)); 7862d157150SStefano Zampini PetscCall(SNESMonitor(snes, snes->iter, snes->norm)); 787d728fb7dSPeter Brune if (snes->reason) break; 788eaedb033SPeter Brune /* Call general purpose update function */ 789dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, update, snes->iter); 790eaedb033SPeter Brune } 79107b62357SFande Kong if (nasm->finaljacobian) { 7929566063dSJacob Faibussowitsch PetscCall(SNESNASMComputeFinalJacobian_Private(snes, X)); 79376c63389SBarry Smith SNESCheckJacobianDomainError(snes); 79407b62357SFande Kong } 7953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 796eaedb033SPeter Brune } 797eaedb033SPeter Brune 798eaedb033SPeter Brune /*MC 7991d27aa22SBarry Smith SNESNASM - Nonlinear Additive Schwarz solver {cite}`ck02`, {cite}`bruneknepleysmithtu15` 800eaedb033SPeter Brune 801f6dfbefdSBarry Smith Options Database Keys: 80270c78603SPeter Brune + -snes_nasm_log - enable logging events for the communication and solve stages 80370c78603SPeter Brune . -snes_nasm_type <basic,restrict> - type of subdomain update used 804420bcc1bSBarry Smith . -snes_nasm_damping <dmp> - the new solution is obtained as old solution plus dmp times (sum of the solutions on the subdomains) 8051d27aa22SBarry Smith . -snes_nasm_finaljacobian - compute the local and global Jacobians of the final iterate 8061d27aa22SBarry Smith . -snes_nasm_finaljacobian_type <finalinner,finalouter,initial> - pick state the Jacobian is calculated at 80770c78603SPeter Brune . -sub_snes_ - options prefix of the subdomain nonlinear solves 80870c78603SPeter Brune . -sub_ksp_ - options prefix of the subdomain Krylov solver 80970c78603SPeter Brune - -sub_pc_ - options prefix of the subdomain preconditioner 81070c78603SPeter Brune 811eaedb033SPeter Brune Level: advanced 812eaedb033SPeter Brune 813f6dfbefdSBarry Smith Note: 814f6dfbefdSBarry Smith This is not often used directly as a solver, it converges too slowly. However it works well as a nonlinear preconditioner for 815f6dfbefdSBarry Smith the `SNESASPIN` solver 816f6dfbefdSBarry Smith 817f6dfbefdSBarry Smith Developer Note: 818f6dfbefdSBarry Smith This is a non-Newton based nonlinear solver that does not directly require a Jacobian; hence the flag snes->usesksp is set to 819f6dfbefdSBarry Smith false and `SNESView()` and -snes_view do not display a `KSP` object. However, if the flag nasm->finaljacobian is set (for example, if 820f6dfbefdSBarry Smith `SNESNASM` is used as a nonlinear preconditioner for `SNESASPIN`) then `SNESSetUpMatrices()` is called to generate the 821f6dfbefdSBarry Smith Jacobian (needed by `SNESASPIN`) 822f6dfbefdSBarry Smith and this utilizes the inner `KSP` object for storing the matrices, but the `KSP` is never used for solving a linear system. When `SNESNASM` is 823f6dfbefdSBarry Smith used by `SNESASPIN` they share the same Jacobian matrices because `SNESSetUp()` (called on the outer `SNESASPIN`) causes the inner `SNES` 824f6dfbefdSBarry Smith object (in this case `SNESNASM`) to inherit the outer Jacobian matrices. 825951fe5abSBarry Smith 826420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESCreate()`, `SNES`, `SNESSetType()`, `SNESType`, `SNESNASMSetType()`, `SNESNASMGetType()`, `SNESNASMSetSubdomains()`, `SNESNASMGetSubdomains()`, 827420bcc1bSBarry Smith `SNESNASMGetSubdomainVecs()`, `SNESNASMSetComputeFinalJacobian()`, `SNESNASMSetDamping()`, `SNESNASMGetDamping()`, `SNESNASMSetWeight()`, 828420bcc1bSBarry Smith `SNESNASMGetSNES()`, `SNESNASMGetNumber()` 829eaedb033SPeter Brune M*/ 830eaedb033SPeter Brune 831d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode SNESCreate_NASM(SNES snes) 832d71ae5a4SJacob Faibussowitsch { 833eaedb033SPeter Brune SNES_NASM *nasm; 834eaedb033SPeter Brune 835eaedb033SPeter Brune PetscFunctionBegin; 8364dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&nasm)); 837eaedb033SPeter Brune snes->data = (void *)nasm; 838eaedb033SPeter Brune 839eaedb033SPeter Brune nasm->n = PETSC_DECIDE; 8409e5d0892SLisandro Dalcin nasm->subsnes = NULL; 8419e5d0892SLisandro Dalcin nasm->x = NULL; 8429e5d0892SLisandro Dalcin nasm->xl = NULL; 8439e5d0892SLisandro Dalcin nasm->y = NULL; 8449e5d0892SLisandro Dalcin nasm->b = NULL; 8459e5d0892SLisandro Dalcin nasm->oscatter = NULL; 8469e5d0892SLisandro Dalcin nasm->oscatter_copy = NULL; 8479e5d0892SLisandro Dalcin nasm->iscatter = NULL; 8489e5d0892SLisandro Dalcin nasm->gscatter = NULL; 849610116beSPeter Brune nasm->damping = 1.; 850111ade9eSPeter Brune 851111ade9eSPeter Brune nasm->type = PC_ASM_BASIC; 852d728fb7dSPeter Brune nasm->finaljacobian = PETSC_FALSE; 853f10b3e88SPatrick Farrell nasm->weight_set = PETSC_FALSE; 854eaedb033SPeter Brune 855eaedb033SPeter Brune snes->ops->destroy = SNESDestroy_NASM; 856eaedb033SPeter Brune snes->ops->setup = SNESSetUp_NASM; 857eaedb033SPeter Brune snes->ops->setfromoptions = SNESSetFromOptions_NASM; 858eaedb033SPeter Brune snes->ops->view = SNESView_NASM; 859eaedb033SPeter Brune snes->ops->solve = SNESSolve_NASM; 860eaedb033SPeter Brune snes->ops->reset = SNESReset_NASM; 861eaedb033SPeter Brune 862eaedb033SPeter Brune snes->usesksp = PETSC_FALSE; 863efd4aadfSBarry Smith snes->usesnpc = PETSC_FALSE; 864eaedb033SPeter Brune 8654fc747eaSLawrence Mitchell snes->alwayscomputesfinalresidual = PETSC_FALSE; 8664fc747eaSLawrence Mitchell 867602bec5dSPeter Brune nasm->fjtype = 0; 868602bec5dSPeter Brune nasm->xinit = NULL; 8690298fd71SBarry Smith nasm->eventrestrictinterp = 0; 8700298fd71SBarry Smith nasm->eventsubsolve = 0; 871b20c023fSPeter Brune 87277e5a1f9SBarry Smith PetscCall(SNESParametersInitialize(snes)); 87377e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, max_funcs, 10000); 87477e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, max_its, 10000); 875eaedb033SPeter Brune 8769566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMSetType_C", SNESNASMSetType_NASM)); 8779566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMGetType_C", SNESNASMGetType_NASM)); 8789566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMSetSubdomains_C", SNESNASMSetSubdomains_NASM)); 8799566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMGetSubdomains_C", SNESNASMGetSubdomains_NASM)); 8809566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMSetDamping_C", SNESNASMSetDamping_NASM)); 8819566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMGetDamping_C", SNESNASMGetDamping_NASM)); 8829566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMGetSubdomainVecs_C", SNESNASMGetSubdomainVecs_NASM)); 8839566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMSetComputeFinalJacobian_C", SNESNASMSetComputeFinalJacobian_NASM)); 8843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 885eaedb033SPeter Brune } 88699e0435eSBarry Smith 887448b6425SPatrick Farrell /*@ 888448b6425SPatrick Farrell SNESNASMGetSNES - Gets a subsolver 889448b6425SPatrick Farrell 89020f4b53cSBarry Smith Not Collective 891448b6425SPatrick Farrell 892448b6425SPatrick Farrell Input Parameters: 89320f4b53cSBarry Smith + snes - the `SNES` context 894448b6425SPatrick Farrell - i - the number of the subsnes to get 895448b6425SPatrick Farrell 8962fe279fdSBarry Smith Output Parameter: 897448b6425SPatrick Farrell . subsnes - the subsolver context 898448b6425SPatrick Farrell 899448b6425SPatrick Farrell Level: intermediate 900448b6425SPatrick Farrell 901420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESNASM`, `SNESNASMGetNumber()` 902448b6425SPatrick Farrell @*/ 903d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESNASMGetSNES(SNES snes, PetscInt i, SNES *subsnes) 904d71ae5a4SJacob Faibussowitsch { 905448b6425SPatrick Farrell SNES_NASM *nasm = (SNES_NASM *)snes->data; 906448b6425SPatrick Farrell 907448b6425SPatrick Farrell PetscFunctionBegin; 9080b121fc5SBarry Smith PetscCheck(i >= 0 && i < nasm->n, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "No such subsolver"); 909448b6425SPatrick Farrell *subsnes = nasm->subsnes[i]; 9103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 911448b6425SPatrick Farrell } 912448b6425SPatrick Farrell 913448b6425SPatrick Farrell /*@ 914448b6425SPatrick Farrell SNESNASMGetNumber - Gets number of subsolvers 915448b6425SPatrick Farrell 91620f4b53cSBarry Smith Not Collective 917448b6425SPatrick Farrell 9182fe279fdSBarry Smith Input Parameter: 91920f4b53cSBarry Smith . snes - the `SNES` context 920448b6425SPatrick Farrell 9212fe279fdSBarry Smith Output Parameter: 922448b6425SPatrick Farrell . n - the number of subsolvers 923448b6425SPatrick Farrell 924448b6425SPatrick Farrell Level: intermediate 925448b6425SPatrick Farrell 926420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESNASM`, `SNESNASMGetSNES()` 927448b6425SPatrick Farrell @*/ 928d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESNASMGetNumber(SNES snes, PetscInt *n) 929d71ae5a4SJacob Faibussowitsch { 930448b6425SPatrick Farrell SNES_NASM *nasm = (SNES_NASM *)snes->data; 931448b6425SPatrick Farrell 932448b6425SPatrick Farrell PetscFunctionBegin; 933448b6425SPatrick Farrell *n = nasm->n; 9343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 935448b6425SPatrick Farrell } 936448b6425SPatrick Farrell 937f10b3e88SPatrick Farrell /*@ 938f10b3e88SPatrick Farrell SNESNASMSetWeight - Sets weight to use when adding overlapping updates 939f10b3e88SPatrick Farrell 940f10b3e88SPatrick Farrell Collective 941f10b3e88SPatrick Farrell 942f10b3e88SPatrick Farrell Input Parameters: 94320f4b53cSBarry Smith + snes - the `SNES` context 944f10b3e88SPatrick Farrell - weight - the weights to use (typically 1/N for each dof, where N is the number of patches it appears in) 945f10b3e88SPatrick Farrell 946f10b3e88SPatrick Farrell Level: intermediate 947f10b3e88SPatrick Farrell 948420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESNASM` 949f10b3e88SPatrick Farrell @*/ 950d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESNASMSetWeight(SNES snes, Vec weight) 951d71ae5a4SJacob Faibussowitsch { 952f10b3e88SPatrick Farrell SNES_NASM *nasm = (SNES_NASM *)snes->data; 953f10b3e88SPatrick Farrell 954f10b3e88SPatrick Farrell PetscFunctionBegin; 9559566063dSJacob Faibussowitsch PetscCall(VecDestroy(&nasm->weight)); 956f10b3e88SPatrick Farrell nasm->weight_set = PETSC_TRUE; 957f10b3e88SPatrick Farrell nasm->weight = weight; 9589566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)nasm->weight)); 9593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 960f10b3e88SPatrick Farrell } 961