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 339371c9d4SSatish Balay static PetscErrorCode SNESReset_NASM(SNES snes) { 34eaedb033SPeter Brune SNES_NASM *nasm = (SNES_NASM *)snes->data; 35eaedb033SPeter Brune PetscInt i; 366e111a19SKarl Rupp 37eaedb033SPeter Brune PetscFunctionBegin; 38eaedb033SPeter Brune for (i = 0; i < nasm->n; i++) { 399566063dSJacob Faibussowitsch if (nasm->xl) PetscCall(VecDestroy(&nasm->xl[i])); 409566063dSJacob Faibussowitsch if (nasm->x) PetscCall(VecDestroy(&nasm->x[i])); 419566063dSJacob Faibussowitsch if (nasm->y) PetscCall(VecDestroy(&nasm->y[i])); 429566063dSJacob Faibussowitsch if (nasm->b) PetscCall(VecDestroy(&nasm->b[i])); 43eaedb033SPeter Brune 449566063dSJacob Faibussowitsch if (nasm->subsnes) PetscCall(SNESDestroy(&nasm->subsnes[i])); 459566063dSJacob Faibussowitsch if (nasm->oscatter) PetscCall(VecScatterDestroy(&nasm->oscatter[i])); 469566063dSJacob Faibussowitsch if (nasm->oscatter_copy) PetscCall(VecScatterDestroy(&nasm->oscatter_copy[i])); 479566063dSJacob Faibussowitsch if (nasm->iscatter) PetscCall(VecScatterDestroy(&nasm->iscatter[i])); 489566063dSJacob Faibussowitsch if (nasm->gscatter) PetscCall(VecScatterDestroy(&nasm->gscatter[i])); 49eaedb033SPeter Brune } 50111ade9eSPeter Brune 519566063dSJacob Faibussowitsch PetscCall(PetscFree(nasm->x)); 529566063dSJacob Faibussowitsch PetscCall(PetscFree(nasm->xl)); 539566063dSJacob Faibussowitsch PetscCall(PetscFree(nasm->y)); 549566063dSJacob Faibussowitsch PetscCall(PetscFree(nasm->b)); 55111ade9eSPeter Brune 569566063dSJacob Faibussowitsch if (nasm->xinit) PetscCall(VecDestroy(&nasm->xinit)); 57602bec5dSPeter Brune 589566063dSJacob Faibussowitsch PetscCall(PetscFree(nasm->subsnes)); 599566063dSJacob Faibussowitsch PetscCall(PetscFree(nasm->oscatter)); 609566063dSJacob Faibussowitsch PetscCall(PetscFree(nasm->oscatter_copy)); 619566063dSJacob Faibussowitsch PetscCall(PetscFree(nasm->iscatter)); 629566063dSJacob Faibussowitsch PetscCall(PetscFree(nasm->gscatter)); 63b20c023fSPeter Brune 6448a46eb9SPierre Jolivet if (nasm->weight_set) PetscCall(VecDestroy(&nasm->weight)); 65f10b3e88SPatrick Farrell 66b20c023fSPeter Brune nasm->eventrestrictinterp = 0; 67b20c023fSPeter Brune nasm->eventsubsolve = 0; 68eaedb033SPeter Brune PetscFunctionReturn(0); 69eaedb033SPeter Brune } 70eaedb033SPeter Brune 719371c9d4SSatish Balay static PetscErrorCode SNESDestroy_NASM(SNES snes) { 72eaedb033SPeter Brune PetscFunctionBegin; 739566063dSJacob Faibussowitsch PetscCall(SNESReset_NASM(snes)); 742e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMSetType_C", NULL)); 752e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMGetType_C", NULL)); 762e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMSetSubdomains_C", NULL)); 772e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMGetSubdomains_C", NULL)); 782e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMSetDamping_C", NULL)); 792e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMGetDamping_C", NULL)); 802e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMGetSubdomainVecs_C", NULL)); 812e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMSetComputeFinalJacobian_C", NULL)); 829566063dSJacob Faibussowitsch PetscCall(PetscFree(snes->data)); 83eaedb033SPeter Brune PetscFunctionReturn(0); 84eaedb033SPeter Brune } 85eaedb033SPeter Brune 869371c9d4SSatish Balay static PetscErrorCode DMGlobalToLocalSubDomainDirichletHook_Private(DM dm, Vec g, InsertMode mode, Vec l, void *ctx) { 87111ade9eSPeter Brune Vec bcs = (Vec)ctx; 886e111a19SKarl Rupp 89111ade9eSPeter Brune PetscFunctionBegin; 909566063dSJacob Faibussowitsch PetscCall(VecCopy(bcs, l)); 91111ade9eSPeter Brune PetscFunctionReturn(0); 92111ade9eSPeter Brune } 93111ade9eSPeter Brune 949371c9d4SSatish Balay static PetscErrorCode SNESSetUp_NASM(SNES snes) { 95eaedb033SPeter Brune SNES_NASM *nasm = (SNES_NASM *)snes->data; 9676857b2aSPeter Brune DM dm, subdm; 97111ade9eSPeter Brune DM *subdms; 98111ade9eSPeter Brune PetscInt i; 99eaedb033SPeter Brune const char *optionsprefix; 100111ade9eSPeter Brune Vec F; 101ed3c11a9SPeter Brune PetscMPIInt size; 102ed3c11a9SPeter Brune KSP ksp; 103ed3c11a9SPeter Brune PC pc; 104eaedb033SPeter Brune 105eaedb033SPeter Brune PetscFunctionBegin; 106eaedb033SPeter Brune if (!nasm->subsnes) { 1079566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 1080a696f66SPeter Brune if (dm) { 109eaedb033SPeter Brune nasm->usesdm = PETSC_TRUE; 1109566063dSJacob Faibussowitsch PetscCall(DMCreateDomainDecomposition(dm, &nasm->n, NULL, NULL, NULL, &subdms)); 11128b400f6SJacob Faibussowitsch PetscCheck(subdms, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM has no default decomposition defined. Set subsolves manually with SNESNASMSetSubdomains()."); 1129566063dSJacob Faibussowitsch PetscCall(DMCreateDomainDecompositionScatters(dm, nasm->n, subdms, &nasm->iscatter, &nasm->oscatter, &nasm->gscatter)); 1139566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nasm->n, &nasm->oscatter_copy)); 11448a46eb9SPierre Jolivet for (i = 0; i < nasm->n; i++) PetscCall(VecScatterCopy(nasm->oscatter[i], &nasm->oscatter_copy[i])); 115eaedb033SPeter Brune 1169566063dSJacob Faibussowitsch PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 1179566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nasm->n, &nasm->subsnes)); 118111ade9eSPeter Brune for (i = 0; i < nasm->n; i++) { 1199566063dSJacob Faibussowitsch PetscCall(SNESCreate(PETSC_COMM_SELF, &nasm->subsnes[i])); 1209566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)nasm->subsnes[i], (PetscObject)snes, 1)); 1219566063dSJacob Faibussowitsch PetscCall(SNESAppendOptionsPrefix(nasm->subsnes[i], optionsprefix)); 1229566063dSJacob Faibussowitsch PetscCall(SNESAppendOptionsPrefix(nasm->subsnes[i], "sub_")); 1239566063dSJacob Faibussowitsch PetscCall(SNESSetDM(nasm->subsnes[i], subdms[i])); 1249566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)nasm->subsnes[i]), &size)); 125ed3c11a9SPeter Brune if (size == 1) { 1269566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(nasm->subsnes[i], &ksp)); 1279566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksp, &pc)); 1289566063dSJacob Faibussowitsch PetscCall(KSPSetType(ksp, KSPPREONLY)); 1299566063dSJacob Faibussowitsch PetscCall(PCSetType(pc, PCLU)); 130ed3c11a9SPeter Brune } 1319566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(nasm->subsnes[i])); 1329566063dSJacob Faibussowitsch PetscCall(DMDestroy(&subdms[i])); 133111ade9eSPeter Brune } 1349566063dSJacob Faibussowitsch PetscCall(PetscFree(subdms)); 135ce94432eSBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONGSTATE, "Cannot construct local problems automatically without a DM!"); 136ce94432eSBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONGSTATE, "Must set subproblems manually if there is no DM!"); 137111ade9eSPeter Brune /* allocate the global vectors */ 13848a46eb9SPierre Jolivet if (!nasm->x) PetscCall(PetscCalloc1(nasm->n, &nasm->x)); 13948a46eb9SPierre Jolivet if (!nasm->xl) PetscCall(PetscCalloc1(nasm->n, &nasm->xl)); 14048a46eb9SPierre Jolivet if (!nasm->y) PetscCall(PetscCalloc1(nasm->n, &nasm->y)); 14148a46eb9SPierre Jolivet if (!nasm->b) PetscCall(PetscCalloc1(nasm->n, &nasm->b)); 142111ade9eSPeter Brune 143111ade9eSPeter Brune for (i = 0; i < nasm->n; i++) { 1449566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(nasm->subsnes[i], &F, NULL, NULL)); 1459566063dSJacob Faibussowitsch if (!nasm->x[i]) PetscCall(VecDuplicate(F, &nasm->x[i])); 1469566063dSJacob Faibussowitsch if (!nasm->y[i]) PetscCall(VecDuplicate(F, &nasm->y[i])); 1479566063dSJacob Faibussowitsch if (!nasm->b[i]) PetscCall(VecDuplicate(F, &nasm->b[i])); 14876857b2aSPeter Brune if (!nasm->xl[i]) { 1499566063dSJacob Faibussowitsch PetscCall(SNESGetDM(nasm->subsnes[i], &subdm)); 1509566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(subdm, &nasm->xl[i])); 1519566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalHookAdd(subdm, DMGlobalToLocalSubDomainDirichletHook_Private, NULL, nasm->xl[i])); 152111ade9eSPeter Brune } 15361ba4676SBarry Smith } 154602bec5dSPeter Brune if (nasm->finaljacobian) { 1559566063dSJacob Faibussowitsch PetscCall(SNESSetUpMatrices(snes)); 15648a46eb9SPierre Jolivet if (nasm->fjtype == 2) PetscCall(VecDuplicate(snes->vec_sol, &nasm->xinit)); 15748a46eb9SPierre Jolivet for (i = 0; i < nasm->n; i++) PetscCall(SNESSetUpMatrices(nasm->subsnes[i])); 158602bec5dSPeter Brune } 159eaedb033SPeter Brune PetscFunctionReturn(0); 160eaedb033SPeter Brune } 161eaedb033SPeter Brune 1629371c9d4SSatish Balay static PetscErrorCode SNESSetFromOptions_NASM(SNES snes, PetscOptionItems *PetscOptionsObject) { 163111ade9eSPeter Brune PCASMType asmtype; 16483dc3634SPierre Jolivet PetscBool flg, monflg; 165111ade9eSPeter Brune SNES_NASM *nasm = (SNES_NASM *)snes->data; 1666e111a19SKarl Rupp 167eaedb033SPeter Brune PetscFunctionBegin; 168d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "Nonlinear Additive Schwarz options"); 1699566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-snes_nasm_type", "Type of restriction/extension", "", SNESNASMTypes, (PetscEnum)nasm->type, (PetscEnum *)&asmtype, &flg)); 1709566063dSJacob Faibussowitsch if (flg) PetscCall(SNESNASMSetType(snes, asmtype)); 171b20c023fSPeter Brune flg = PETSC_FALSE; 172b20c023fSPeter Brune monflg = PETSC_TRUE; 1739566063dSJacob 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)); 1749566063dSJacob Faibussowitsch if (flg) PetscCall(SNESNASMSetDamping(snes, nasm->damping)); 1759566063dSJacob Faibussowitsch PetscCall(PetscOptionsDeprecated("-snes_nasm_sub_view", NULL, "3.15", "Use -snes_view ::ascii_info_detail")); 1769566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_nasm_finaljacobian", "Compute the global jacobian of the final iterate (for ASPIN)", "", nasm->finaljacobian, &nasm->finaljacobian, NULL)); 1779566063dSJacob Faibussowitsch PetscCall(PetscOptionsEList("-snes_nasm_finaljacobian_type", "The type of the final jacobian computed.", "", SNESNASMFJTypes, 3, SNESNASMFJTypes[0], &nasm->fjtype, NULL)); 1789566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_nasm_log", "Log times for subSNES solves and restriction", "", monflg, &monflg, &flg)); 179b20c023fSPeter Brune if (flg) { 1809566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("SNESNASMSubSolve", ((PetscObject)snes)->classid, &nasm->eventsubsolve)); 1819566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("SNESNASMRestrict", ((PetscObject)snes)->classid, &nasm->eventrestrictinterp)); 182b20c023fSPeter Brune } 183d0609cedSBarry Smith PetscOptionsHeadEnd(); 184eaedb033SPeter Brune PetscFunctionReturn(0); 185eaedb033SPeter Brune } 186eaedb033SPeter Brune 1879371c9d4SSatish Balay static PetscErrorCode SNESView_NASM(SNES snes, PetscViewer viewer) { 188b20c023fSPeter Brune SNES_NASM *nasm = (SNES_NASM *)snes->data; 189a4f17876SPeter Brune PetscMPIInt rank, size; 190dd2fa690SBarry Smith PetscInt i, N, bsz; 191b20c023fSPeter Brune PetscBool iascii, isstring; 192b20c023fSPeter Brune PetscViewer sviewer; 193ce94432eSBarry Smith MPI_Comm comm; 19483dc3634SPierre Jolivet PetscViewerFormat format; 19583dc3634SPierre Jolivet const char *prefix; 196b20c023fSPeter Brune 197b20c023fSPeter Brune PetscFunctionBegin; 1989566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 1999566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 2009566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 2019566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 2029566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 2031c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&nasm->n, &N, 1, MPIU_INT, MPI_SUM, comm)); 204b20c023fSPeter Brune if (iascii) { 20563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " total subdomain blocks = %" PetscInt_FMT "\n", N)); 2069566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 20783dc3634SPierre Jolivet if (format != PETSC_VIEWER_ASCII_INFO_DETAIL) { 208a4f17876SPeter Brune if (nasm->subsnes) { 2099566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Local solver information for first block on rank 0:\n")); 2109566063dSJacob Faibussowitsch PetscCall(SNESGetOptionsPrefix(snes, &prefix)); 2119566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use -%ssnes_view ::ascii_info_detail to display information for all blocks\n", prefix ? prefix : "")); 2129566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 2139566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(viewer, PETSC_COMM_SELF, &sviewer)); 214dd400576SPatrick Sanan if (rank == 0) { 2159566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 2169566063dSJacob Faibussowitsch PetscCall(SNESView(nasm->subsnes[0], sviewer)); 2179566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 218a4f17876SPeter Brune } 2199566063dSJacob Faibussowitsch PetscCall(PetscViewerRestoreSubViewer(viewer, PETSC_COMM_SELF, &sviewer)); 2209566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 221a4f17876SPeter Brune } 222a4f17876SPeter Brune } else { 223a4f17876SPeter Brune /* print the solver on each block */ 2249566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 22563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " [%d] number of local blocks = %" PetscInt_FMT "\n", (int)rank, nasm->n)); 2269566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 2279566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 2289566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Local solver information for each block is in the following SNES objects:\n")); 2299566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 2309566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "- - - - - - - - - - - - - - - - - -\n")); 2319566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(viewer, PETSC_COMM_SELF, &sviewer)); 232a4f17876SPeter Brune for (i = 0; i < nasm->n; i++) { 2339566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(nasm->x[i], &bsz)); 23463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(sviewer, "[%d] local block number %" PetscInt_FMT ", size = %" PetscInt_FMT "\n", (int)rank, i, bsz)); 2359566063dSJacob Faibussowitsch PetscCall(SNESView(nasm->subsnes[i], sviewer)); 2369566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(sviewer, "- - - - - - - - - - - - - - - - - -\n")); 237b20c023fSPeter Brune } 2389566063dSJacob Faibussowitsch PetscCall(PetscViewerRestoreSubViewer(viewer, PETSC_COMM_SELF, &sviewer)); 2399566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 2409566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 241a4f17876SPeter Brune } 242b20c023fSPeter Brune } else if (isstring) { 24363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerStringSPrintf(viewer, " blocks=%" PetscInt_FMT ",type=%s", N, SNESNASMTypes[nasm->type])); 2449566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(viewer, PETSC_COMM_SELF, &sviewer)); 2459566063dSJacob Faibussowitsch if (nasm->subsnes && rank == 0) PetscCall(SNESView(nasm->subsnes[0], sviewer)); 2469566063dSJacob Faibussowitsch PetscCall(PetscViewerRestoreSubViewer(viewer, PETSC_COMM_SELF, &sviewer)); 247b20c023fSPeter Brune } 248eaedb033SPeter Brune PetscFunctionReturn(0); 249eaedb033SPeter Brune } 250eaedb033SPeter Brune 251e0331734SPeter Brune /*@ 252f6dfbefdSBarry Smith SNESNASMSetType - Set the type of subdomain update used for the nonlinear additive Schwarz solver 253e0331734SPeter Brune 254f6dfbefdSBarry Smith Logically Collective on snes 255e0331734SPeter Brune 256e0331734SPeter Brune Input Parameters: 257f6dfbefdSBarry Smith + snes - the `SNES` context 258f6dfbefdSBarry Smith - type - the type of update, `PC_ASM_BASIC` or `PC_ASM_RESTRICT` 259e0331734SPeter Brune 260e0331734SPeter Brune Level: intermediate 261e0331734SPeter Brune 262f6dfbefdSBarry Smith .seealso: `SNESNASM`, `SNESNASMGetType()`, `PCASMSetType()`, `PC_ASM_BASIC`, `PC_ASM_RESTRICT`, `PCASMType` 263e0331734SPeter Brune @*/ 2649371c9d4SSatish Balay PetscErrorCode SNESNASMSetType(SNES snes, PCASMType type) { 265e0331734SPeter Brune PetscErrorCode (*f)(SNES, PCASMType); 266e0331734SPeter Brune 267e0331734SPeter Brune PetscFunctionBegin; 2689566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)snes, "SNESNASMSetType_C", &f)); 2699566063dSJacob Faibussowitsch if (f) PetscCall((f)(snes, type)); 270e0331734SPeter Brune PetscFunctionReturn(0); 271e0331734SPeter Brune } 272e0331734SPeter Brune 2739371c9d4SSatish Balay static PetscErrorCode SNESNASMSetType_NASM(SNES snes, PCASMType type) { 274e0331734SPeter Brune SNES_NASM *nasm = (SNES_NASM *)snes->data; 275e0331734SPeter Brune 276e0331734SPeter Brune PetscFunctionBegin; 2770b121fc5SBarry Smith PetscCheck(type == PC_ASM_BASIC || type == PC_ASM_RESTRICT, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "SNESNASM only supports basic and restrict types"); 278e0331734SPeter Brune nasm->type = type; 279e0331734SPeter Brune PetscFunctionReturn(0); 280e0331734SPeter Brune } 281e0331734SPeter Brune 282e0331734SPeter Brune /*@ 283f6dfbefdSBarry Smith SNESNASMGetType - Get the type of subdomain update used for the nonlinear additive Schwarz solver 284e0331734SPeter Brune 285f6dfbefdSBarry Smith Logically Collective on snes 286e0331734SPeter Brune 287e0331734SPeter Brune Input Parameters: 288f6dfbefdSBarry Smith . snes - the `SNES` context 289e0331734SPeter Brune 290e0331734SPeter Brune Output Parameters: 291e0331734SPeter Brune . type - the type of update 292e0331734SPeter Brune 293e0331734SPeter Brune Level: intermediate 294e0331734SPeter Brune 295f6dfbefdSBarry Smith .seealso: `SNESNASM`, `SNESNASMSetType()`, `PCASMGetType()`, `PC_ASM_BASIC`, `PC_ASM_RESTRICT`, `PCASMType` 296e0331734SPeter Brune @*/ 2979371c9d4SSatish Balay PetscErrorCode SNESNASMGetType(SNES snes, PCASMType *type) { 298e0331734SPeter Brune PetscFunctionBegin; 299cac4c232SBarry Smith PetscUseMethod(snes, "SNESNASMGetType_C", (SNES, PCASMType *), (snes, type)); 300e0331734SPeter Brune PetscFunctionReturn(0); 301e0331734SPeter Brune } 302e0331734SPeter Brune 3039371c9d4SSatish Balay static PetscErrorCode SNESNASMGetType_NASM(SNES snes, PCASMType *type) { 304e0331734SPeter Brune SNES_NASM *nasm = (SNES_NASM *)snes->data; 305e0331734SPeter Brune 306e0331734SPeter Brune PetscFunctionBegin; 307e0331734SPeter Brune *type = nasm->type; 308e0331734SPeter Brune PetscFunctionReturn(0); 309e0331734SPeter Brune } 310e0331734SPeter Brune 31176857b2aSPeter Brune /*@ 312f6dfbefdSBarry Smith SNESNASMSetSubdomains - Manually Set the context required to restrict and solve subdomain problems in the nonlinear additive Schwarz solver 31376857b2aSPeter Brune 314f6dfbefdSBarry Smith Logically Collective 31576857b2aSPeter Brune 31676857b2aSPeter Brune Input Parameters: 317f6dfbefdSBarry Smith + snes - the SNES context 31876857b2aSPeter Brune . n - the number of local subdomains 31976857b2aSPeter Brune . subsnes - solvers defined on the local subdomains 32076857b2aSPeter Brune . iscatter - scatters into the nonoverlapping portions of the local subdomains 32176857b2aSPeter Brune . oscatter - scatters into the overlapping portions of the local subdomains 32276857b2aSPeter Brune - gscatter - scatters into the (ghosted) local vector of the local subdomain 32376857b2aSPeter Brune 32476857b2aSPeter Brune Level: intermediate 32576857b2aSPeter Brune 326db781477SPatrick Sanan .seealso: `SNESNASM`, `SNESNASMGetSubdomains()` 32776857b2aSPeter Brune @*/ 3289371c9d4SSatish Balay PetscErrorCode SNESNASMSetSubdomains(SNES snes, PetscInt n, SNES subsnes[], VecScatter iscatter[], VecScatter oscatter[], VecScatter gscatter[]) { 329111ade9eSPeter Brune PetscErrorCode (*f)(SNES, PetscInt, SNES *, VecScatter *, VecScatter *, VecScatter *); 3306e111a19SKarl Rupp 331eaedb033SPeter Brune PetscFunctionBegin; 3329566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)snes, "SNESNASMSetSubdomains_C", &f)); 3339566063dSJacob Faibussowitsch if (f) PetscCall((f)(snes, n, subsnes, iscatter, oscatter, gscatter)); 334eaedb033SPeter Brune PetscFunctionReturn(0); 335eaedb033SPeter Brune } 336eaedb033SPeter Brune 3379371c9d4SSatish Balay static PetscErrorCode SNESNASMSetSubdomains_NASM(SNES snes, PetscInt n, SNES subsnes[], VecScatter iscatter[], VecScatter oscatter[], VecScatter gscatter[]) { 338eaedb033SPeter Brune PetscInt i; 339eaedb033SPeter Brune SNES_NASM *nasm = (SNES_NASM *)snes->data; 3406e111a19SKarl Rupp 341eaedb033SPeter Brune PetscFunctionBegin; 34228b400f6SJacob Faibussowitsch PetscCheck(!snes->setupcalled, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONGSTATE, "SNESNASMSetSubdomains() should be called before calling SNESSetUp()."); 343eaedb033SPeter Brune 344111ade9eSPeter Brune /* tear down the previously set things */ 3459566063dSJacob Faibussowitsch PetscCall(SNESReset(snes)); 346111ade9eSPeter Brune 347eaedb033SPeter Brune nasm->n = n; 348111ade9eSPeter Brune if (oscatter) { 3499566063dSJacob Faibussowitsch for (i = 0; i < n; i++) PetscCall(PetscObjectReference((PetscObject)oscatter[i])); 350eaedb033SPeter Brune } 351111ade9eSPeter Brune if (iscatter) { 3529566063dSJacob Faibussowitsch for (i = 0; i < n; i++) PetscCall(PetscObjectReference((PetscObject)iscatter[i])); 353eaedb033SPeter Brune } 354111ade9eSPeter Brune if (gscatter) { 3559566063dSJacob Faibussowitsch for (i = 0; i < n; i++) PetscCall(PetscObjectReference((PetscObject)gscatter[i])); 356111ade9eSPeter Brune } 357111ade9eSPeter Brune if (oscatter) { 3589566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &nasm->oscatter)); 3599566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &nasm->oscatter_copy)); 360eaedb033SPeter Brune for (i = 0; i < n; i++) { 361111ade9eSPeter Brune nasm->oscatter[i] = oscatter[i]; 3629566063dSJacob Faibussowitsch PetscCall(VecScatterCopy(oscatter[i], &nasm->oscatter_copy[i])); 363eaedb033SPeter Brune } 364111ade9eSPeter Brune } 365111ade9eSPeter Brune if (iscatter) { 3669566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &nasm->iscatter)); 367ad540459SPierre Jolivet for (i = 0; i < n; i++) nasm->iscatter[i] = iscatter[i]; 368eaedb033SPeter Brune } 369111ade9eSPeter Brune if (gscatter) { 3709566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &nasm->gscatter)); 371ad540459SPierre Jolivet for (i = 0; i < n; i++) nasm->gscatter[i] = gscatter[i]; 372eaedb033SPeter Brune } 373111ade9eSPeter Brune 374eaedb033SPeter Brune if (subsnes) { 3759566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &nasm->subsnes)); 376ad540459SPierre Jolivet for (i = 0; i < n; i++) nasm->subsnes[i] = subsnes[i]; 377eaedb033SPeter Brune } 378eaedb033SPeter Brune PetscFunctionReturn(0); 379eaedb033SPeter Brune } 380eaedb033SPeter Brune 38176857b2aSPeter Brune /*@ 382f6dfbefdSBarry Smith SNESNASMGetSubdomains - Get the local subdomain contexts for the nonlinear additive Schwarz solver 38376857b2aSPeter Brune 384f6dfbefdSBarry Smith Not Collective but some of the objects returned will be parallel 38576857b2aSPeter Brune 386f899ff85SJose E. Roman Input Parameter: 387f6dfbefdSBarry Smith . snes - the `SNES` context 38876857b2aSPeter Brune 38976857b2aSPeter Brune Output Parameters: 39076857b2aSPeter Brune + n - the number of local subdomains 39176857b2aSPeter Brune . subsnes - solvers defined on the local subdomains 39276857b2aSPeter Brune . iscatter - scatters into the nonoverlapping portions of the local subdomains 39376857b2aSPeter Brune . oscatter - scatters into the overlapping portions of the local subdomains 39476857b2aSPeter Brune - gscatter - scatters into the (ghosted) local vector of the local subdomain 39576857b2aSPeter Brune 39676857b2aSPeter Brune Level: intermediate 39776857b2aSPeter Brune 398db781477SPatrick Sanan .seealso: `SNESNASM`, `SNESNASMSetSubdomains()` 39976857b2aSPeter Brune @*/ 4009371c9d4SSatish Balay PetscErrorCode SNESNASMGetSubdomains(SNES snes, PetscInt *n, SNES *subsnes[], VecScatter *iscatter[], VecScatter *oscatter[], VecScatter *gscatter[]) { 40176857b2aSPeter Brune PetscErrorCode (*f)(SNES, PetscInt *, SNES **, VecScatter **, VecScatter **, VecScatter **); 40276857b2aSPeter Brune 40376857b2aSPeter Brune PetscFunctionBegin; 4049566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)snes, "SNESNASMGetSubdomains_C", &f)); 4059566063dSJacob Faibussowitsch if (f) PetscCall((f)(snes, n, subsnes, iscatter, oscatter, gscatter)); 40676857b2aSPeter Brune PetscFunctionReturn(0); 40776857b2aSPeter Brune } 40876857b2aSPeter Brune 4099371c9d4SSatish Balay static PetscErrorCode SNESNASMGetSubdomains_NASM(SNES snes, PetscInt *n, SNES *subsnes[], VecScatter *iscatter[], VecScatter *oscatter[], VecScatter *gscatter[]) { 41076857b2aSPeter Brune SNES_NASM *nasm = (SNES_NASM *)snes->data; 41176857b2aSPeter Brune 41276857b2aSPeter Brune PetscFunctionBegin; 41376857b2aSPeter Brune if (n) *n = nasm->n; 41476857b2aSPeter Brune if (oscatter) *oscatter = nasm->oscatter; 41576857b2aSPeter Brune if (iscatter) *iscatter = nasm->iscatter; 41676857b2aSPeter Brune if (gscatter) *gscatter = nasm->gscatter; 41783dc3634SPierre Jolivet if (subsnes) *subsnes = nasm->subsnes; 41876857b2aSPeter Brune PetscFunctionReturn(0); 41976857b2aSPeter Brune } 42076857b2aSPeter Brune 42176857b2aSPeter Brune /*@ 422f6dfbefdSBarry Smith SNESNASMGetSubdomainVecs - Get the processor-local subdomain vectors for the nonlinear additive Schwarz solver 42376857b2aSPeter Brune 42476857b2aSPeter Brune Not Collective 42576857b2aSPeter Brune 426f899ff85SJose E. Roman Input Parameter: 427f6dfbefdSBarry Smith . snes - the `SNES` context 42876857b2aSPeter Brune 42976857b2aSPeter Brune Output Parameters: 43076857b2aSPeter Brune + n - the number of local subdomains 43176857b2aSPeter Brune . x - The subdomain solution vector 43276857b2aSPeter Brune . y - The subdomain step vector 43376857b2aSPeter Brune . b - The subdomain RHS vector 43476857b2aSPeter Brune - xl - The subdomain local vectors (ghosted) 43576857b2aSPeter Brune 43676857b2aSPeter Brune Level: developer 43776857b2aSPeter Brune 438db781477SPatrick Sanan .seealso: `SNESNASM`, `SNESNASMGetSubdomains()` 43976857b2aSPeter Brune @*/ 4409371c9d4SSatish Balay PetscErrorCode SNESNASMGetSubdomainVecs(SNES snes, PetscInt *n, Vec **x, Vec **y, Vec **b, Vec **xl) { 44176857b2aSPeter Brune PetscErrorCode (*f)(SNES, PetscInt *, Vec **, Vec **, Vec **, Vec **); 44276857b2aSPeter Brune 44376857b2aSPeter Brune PetscFunctionBegin; 4449566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)snes, "SNESNASMGetSubdomainVecs_C", &f)); 4459566063dSJacob Faibussowitsch if (f) PetscCall((f)(snes, n, x, y, b, xl)); 44676857b2aSPeter Brune PetscFunctionReturn(0); 44776857b2aSPeter Brune } 44876857b2aSPeter Brune 4499371c9d4SSatish Balay static PetscErrorCode SNESNASMGetSubdomainVecs_NASM(SNES snes, PetscInt *n, Vec **x, Vec **y, Vec **b, Vec **xl) { 45076857b2aSPeter Brune SNES_NASM *nasm = (SNES_NASM *)snes->data; 45176857b2aSPeter Brune 45276857b2aSPeter Brune PetscFunctionBegin; 45376857b2aSPeter Brune if (n) *n = nasm->n; 45476857b2aSPeter Brune if (x) *x = nasm->x; 45576857b2aSPeter Brune if (y) *y = nasm->y; 45676857b2aSPeter Brune if (b) *b = nasm->b; 45776857b2aSPeter Brune if (xl) *xl = nasm->xl; 45876857b2aSPeter Brune PetscFunctionReturn(0); 45976857b2aSPeter Brune } 46076857b2aSPeter Brune 461d728fb7dSPeter Brune /*@ 462f6dfbefdSBarry Smith SNESNASMSetComputeFinalJacobian - Schedules the computation of the global and subdomain Jacobians upon convergence for the 463f6dfbefdSBarry Smith nonlinear additive Schwarz solver 464d728fb7dSPeter Brune 465f6dfbefdSBarry Smith Collective on snes 466d728fb7dSPeter Brune 467d728fb7dSPeter Brune Input Parameters: 468f6dfbefdSBarry Smith + snes - the SNES context 469f6dfbefdSBarry Smith - flg - `PETSC_TRUE` to compute the Jacobians 470d728fb7dSPeter Brune 471d728fb7dSPeter Brune Level: developer 472d728fb7dSPeter Brune 47395452b02SPatrick Sanan Notes: 474f6dfbefdSBarry Smith This is used almost exclusively in the implementation of `SNESASPIN`, where the converged subdomain and global Jacobian 475d728fb7dSPeter Brune is needed at each linear iteration. 476d728fb7dSPeter Brune 477db781477SPatrick Sanan .seealso: `SNESNASM`, `SNESNASMGetSubdomains()` 478d728fb7dSPeter Brune @*/ 4799371c9d4SSatish Balay PetscErrorCode SNESNASMSetComputeFinalJacobian(SNES snes, PetscBool flg) { 480d728fb7dSPeter Brune PetscErrorCode (*f)(SNES, PetscBool); 481d728fb7dSPeter Brune 482d728fb7dSPeter Brune PetscFunctionBegin; 4839566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)snes, "SNESNASMSetComputeFinalJacobian_C", &f)); 4849566063dSJacob Faibussowitsch if (f) PetscCall((f)(snes, flg)); 485d728fb7dSPeter Brune PetscFunctionReturn(0); 486d728fb7dSPeter Brune } 487d728fb7dSPeter Brune 4889371c9d4SSatish Balay static PetscErrorCode SNESNASMSetComputeFinalJacobian_NASM(SNES snes, PetscBool flg) { 489d728fb7dSPeter Brune SNES_NASM *nasm = (SNES_NASM *)snes->data; 490d728fb7dSPeter Brune 491d728fb7dSPeter Brune PetscFunctionBegin; 492d728fb7dSPeter Brune nasm->finaljacobian = flg; 493d728fb7dSPeter Brune PetscFunctionReturn(0); 494d728fb7dSPeter Brune } 49576857b2aSPeter Brune 496610116beSPeter Brune /*@ 497f6dfbefdSBarry Smith SNESNASMSetDamping - Sets the update damping for `SNESNASM` the nonlinear additive Schwarz solver 498610116beSPeter Brune 499f6dfbefdSBarry Smith Logically collective on snes 500610116beSPeter Brune 501610116beSPeter Brune Input Parameters: 502f6dfbefdSBarry Smith + snes - the `SNES` context 503610116beSPeter Brune - dmp - damping 504610116beSPeter Brune 505610116beSPeter Brune Level: intermediate 506610116beSPeter Brune 50795452b02SPatrick Sanan Notes: 50895452b02SPatrick Sanan The new solution is obtained as old solution plus dmp times (sum of the solutions on the subdomains) 5095dfa0f3bSBarry Smith 510db781477SPatrick Sanan .seealso: `SNESNASM`, `SNESNASMGetDamping()` 511610116beSPeter Brune @*/ 5129371c9d4SSatish Balay PetscErrorCode SNESNASMSetDamping(SNES snes, PetscReal dmp) { 513610116beSPeter Brune PetscErrorCode (*f)(SNES, PetscReal); 514610116beSPeter Brune 515610116beSPeter Brune PetscFunctionBegin; 5169566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)snes, "SNESNASMSetDamping_C", (void (**)(void)) & f)); 5179566063dSJacob Faibussowitsch if (f) PetscCall((f)(snes, dmp)); 518610116beSPeter Brune PetscFunctionReturn(0); 519610116beSPeter Brune } 520610116beSPeter Brune 5219371c9d4SSatish Balay static PetscErrorCode SNESNASMSetDamping_NASM(SNES snes, PetscReal dmp) { 522610116beSPeter Brune SNES_NASM *nasm = (SNES_NASM *)snes->data; 523610116beSPeter Brune 524610116beSPeter Brune PetscFunctionBegin; 525610116beSPeter Brune nasm->damping = dmp; 526610116beSPeter Brune PetscFunctionReturn(0); 527610116beSPeter Brune } 528610116beSPeter Brune 529610116beSPeter Brune /*@ 530f6dfbefdSBarry Smith SNESNASMGetDamping - Gets the update damping for `SNESNASM` the nonlinear additive Schwarz solver 531610116beSPeter Brune 532610116beSPeter Brune Not Collective 533610116beSPeter Brune 534f6dfbefdSBarry Smith Input Parameter: 535f6dfbefdSBarry Smith . snes - the SNES context 536f6dfbefdSBarry Smith 537f6dfbefdSBarry Smith Output Parameter: 538f6dfbefdSBarry Smith . dmp - damping 539610116beSPeter Brune 540610116beSPeter Brune Level: intermediate 541610116beSPeter Brune 542db781477SPatrick Sanan .seealso: `SNESNASM`, `SNESNASMSetDamping()` 543610116beSPeter Brune @*/ 5449371c9d4SSatish Balay PetscErrorCode SNESNASMGetDamping(SNES snes, PetscReal *dmp) { 545610116beSPeter Brune PetscFunctionBegin; 546cac4c232SBarry Smith PetscUseMethod(snes, "SNESNASMGetDamping_C", (SNES, PetscReal *), (snes, dmp)); 547610116beSPeter Brune PetscFunctionReturn(0); 548610116beSPeter Brune } 549610116beSPeter Brune 5509371c9d4SSatish Balay static PetscErrorCode SNESNASMGetDamping_NASM(SNES snes, PetscReal *dmp) { 551610116beSPeter Brune SNES_NASM *nasm = (SNES_NASM *)snes->data; 552610116beSPeter Brune 553610116beSPeter Brune PetscFunctionBegin; 554610116beSPeter Brune *dmp = nasm->damping; 555610116beSPeter Brune PetscFunctionReturn(0); 556610116beSPeter Brune } 557610116beSPeter Brune 55814eb1c5cSMatthew G. Knepley /* 55914eb1c5cSMatthew G. Knepley Input Parameters: 56014eb1c5cSMatthew G. Knepley + snes - The solver 56114eb1c5cSMatthew G. Knepley . B - The RHS vector 56214eb1c5cSMatthew G. Knepley - X - The initial guess 56314eb1c5cSMatthew G. Knepley 56414eb1c5cSMatthew G. Knepley Output Parameters: 56514eb1c5cSMatthew G. Knepley . Y - The solution update 56614eb1c5cSMatthew G. Knepley 56714eb1c5cSMatthew G. Knepley TODO: All scatters should be packed into one 56814eb1c5cSMatthew G. Knepley */ 5699371c9d4SSatish Balay PetscErrorCode SNESNASMSolveLocal_Private(SNES snes, Vec B, Vec Y, Vec X) { 570eaedb033SPeter Brune SNES_NASM *nasm = (SNES_NASM *)snes->data; 571258e1594SPeter Brune SNES subsnes; 572eaedb033SPeter Brune PetscInt i; 573610116beSPeter Brune PetscReal dmp; 574f10b3e88SPatrick Farrell Vec Xl, Bl, Yl, Xlloc; 575f10b3e88SPatrick Farrell VecScatter iscat, oscat, gscat, oscat_copy; 576111ade9eSPeter Brune DM dm, subdm; 577e0331734SPeter Brune PCASMType type; 5780adebc6cSBarry Smith 579eaedb033SPeter Brune PetscFunctionBegin; 5809566063dSJacob Faibussowitsch PetscCall(SNESNASMGetType(snes, &type)); 5819566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 5829566063dSJacob Faibussowitsch PetscCall(VecSet(Y, 0)); 5839566063dSJacob Faibussowitsch if (nasm->eventrestrictinterp) PetscCall(PetscLogEventBegin(nasm->eventrestrictinterp, snes, 0, 0, 0)); 584eaedb033SPeter Brune for (i = 0; i < nasm->n; i++) { 585f10b3e88SPatrick Farrell /* scatter the solution to the global solution and the local solution */ 586f10b3e88SPatrick Farrell Xl = nasm->x[i]; 58770c78f05SPeter Brune Xlloc = nasm->xl[i]; 58870c78f05SPeter Brune oscat = nasm->oscatter[i]; 589f10b3e88SPatrick Farrell oscat_copy = nasm->oscatter_copy[i]; 590f10b3e88SPatrick Farrell gscat = nasm->gscatter[i]; 5919566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(oscat, X, Xl, INSERT_VALUES, SCATTER_FORWARD)); 5929566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(gscat, X, Xlloc, INSERT_VALUES, SCATTER_FORWARD)); 59370c78f05SPeter Brune if (B) { 59470c78f05SPeter Brune /* scatter the RHS to the local RHS */ 59570c78f05SPeter Brune Bl = nasm->b[i]; 5969566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(oscat_copy, B, Bl, INSERT_VALUES, SCATTER_FORWARD)); 59770c78f05SPeter Brune } 59870c78f05SPeter Brune } 5999566063dSJacob Faibussowitsch if (nasm->eventrestrictinterp) PetscCall(PetscLogEventEnd(nasm->eventrestrictinterp, snes, 0, 0, 0)); 600b20c023fSPeter Brune 6019566063dSJacob Faibussowitsch if (nasm->eventsubsolve) PetscCall(PetscLogEventBegin(nasm->eventsubsolve, snes, 0, 0, 0)); 60270c78f05SPeter Brune for (i = 0; i < nasm->n; i++) { 60370c78f05SPeter Brune Xl = nasm->x[i]; 60470c78f05SPeter Brune Xlloc = nasm->xl[i]; 60570c78f05SPeter Brune Yl = nasm->y[i]; 606258e1594SPeter Brune subsnes = nasm->subsnes[i]; 6079566063dSJacob Faibussowitsch PetscCall(SNESGetDM(subsnes, &subdm)); 608111ade9eSPeter Brune iscat = nasm->iscatter[i]; 609111ade9eSPeter Brune oscat = nasm->oscatter[i]; 610f10b3e88SPatrick Farrell oscat_copy = nasm->oscatter_copy[i]; 611111ade9eSPeter Brune gscat = nasm->gscatter[i]; 6129566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(oscat, X, Xl, INSERT_VALUES, SCATTER_FORWARD)); 6139566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(gscat, X, Xlloc, INSERT_VALUES, SCATTER_FORWARD)); 61424b7f281SPeter Brune if (B) { 61524b7f281SPeter Brune Bl = nasm->b[i]; 6169566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(oscat_copy, B, Bl, INSERT_VALUES, SCATTER_FORWARD)); 617ed3c11a9SPeter Brune } else Bl = NULL; 618f10b3e88SPatrick Farrell 6199566063dSJacob Faibussowitsch PetscCall(DMSubDomainRestrict(dm, oscat, gscat, subdm)); 6209566063dSJacob Faibussowitsch PetscCall(VecCopy(Xl, Yl)); 6219566063dSJacob Faibussowitsch PetscCall(SNESSolve(subsnes, Bl, Xl)); 6229566063dSJacob Faibussowitsch PetscCall(VecAYPX(Yl, -1.0, Xl)); 6239566063dSJacob Faibussowitsch PetscCall(VecScale(Yl, nasm->damping)); 624e0331734SPeter Brune if (type == PC_ASM_BASIC) { 6259566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(oscat, Yl, Y, ADD_VALUES, SCATTER_REVERSE)); 6269566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(oscat, Yl, Y, ADD_VALUES, SCATTER_REVERSE)); 627e0331734SPeter Brune } else if (type == PC_ASM_RESTRICT) { 6289566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(iscat, Yl, Y, ADD_VALUES, SCATTER_REVERSE)); 6299566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(iscat, Yl, Y, ADD_VALUES, SCATTER_REVERSE)); 630ce94432eSBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONGSTATE, "Only basic and restrict types are supported for SNESNASM"); 631eaedb033SPeter Brune } 6329566063dSJacob Faibussowitsch if (nasm->eventsubsolve) PetscCall(PetscLogEventEnd(nasm->eventsubsolve, snes, 0, 0, 0)); 6339566063dSJacob Faibussowitsch if (nasm->eventrestrictinterp) PetscCall(PetscLogEventBegin(nasm->eventrestrictinterp, snes, 0, 0, 0)); 6341baa6e33SBarry Smith if (nasm->weight_set) PetscCall(VecPointwiseMult(Y, Y, nasm->weight)); 6359566063dSJacob Faibussowitsch if (nasm->eventrestrictinterp) PetscCall(PetscLogEventEnd(nasm->eventrestrictinterp, snes, 0, 0, 0)); 6369566063dSJacob Faibussowitsch PetscCall(SNESNASMGetDamping(snes, &dmp)); 6379566063dSJacob Faibussowitsch PetscCall(VecAXPY(X, dmp, Y)); 638eaedb033SPeter Brune PetscFunctionReturn(0); 639eaedb033SPeter Brune } 640eaedb033SPeter Brune 6419371c9d4SSatish Balay static PetscErrorCode SNESNASMComputeFinalJacobian_Private(SNES snes, Vec Xfinal) { 642602bec5dSPeter Brune Vec X = Xfinal; 643d728fb7dSPeter Brune SNES_NASM *nasm = (SNES_NASM *)snes->data; 644d728fb7dSPeter Brune SNES subsnes; 645ca44f815SPeter Brune PetscInt i, lag = 1; 646e59f0a30SPeter Brune Vec Xlloc, Xl, Fl, F; 647d728fb7dSPeter Brune VecScatter oscat, gscat; 648d728fb7dSPeter Brune DM dm, subdm; 649d1e9a80fSBarry Smith 650d728fb7dSPeter Brune PetscFunctionBegin; 651602bec5dSPeter Brune if (nasm->fjtype == 2) X = nasm->xinit; 652e59f0a30SPeter Brune F = snes->vec_func; 6539566063dSJacob Faibussowitsch if (snes->normschedule == SNES_NORM_NONE) PetscCall(SNESComputeFunction(snes, X, F)); 6549566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobian(snes, X, snes->jacobian, snes->jacobian_pre)); 6559566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 6569566063dSJacob Faibussowitsch if (nasm->eventrestrictinterp) PetscCall(PetscLogEventBegin(nasm->eventrestrictinterp, snes, 0, 0, 0)); 657602bec5dSPeter Brune if (nasm->fjtype != 1) { 658d728fb7dSPeter Brune for (i = 0; i < nasm->n; i++) { 659d728fb7dSPeter Brune Xlloc = nasm->xl[i]; 660d728fb7dSPeter Brune gscat = nasm->gscatter[i]; 6619566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(gscat, X, Xlloc, INSERT_VALUES, SCATTER_FORWARD)); 662602bec5dSPeter Brune } 663d728fb7dSPeter Brune } 6649566063dSJacob Faibussowitsch if (nasm->eventrestrictinterp) PetscCall(PetscLogEventEnd(nasm->eventrestrictinterp, snes, 0, 0, 0)); 665d728fb7dSPeter Brune for (i = 0; i < nasm->n; i++) { 666e59f0a30SPeter Brune Fl = nasm->subsnes[i]->vec_func; 667d728fb7dSPeter Brune Xl = nasm->x[i]; 668d728fb7dSPeter Brune Xlloc = nasm->xl[i]; 669d728fb7dSPeter Brune subsnes = nasm->subsnes[i]; 670d728fb7dSPeter Brune oscat = nasm->oscatter[i]; 671d728fb7dSPeter Brune gscat = nasm->gscatter[i]; 6729566063dSJacob Faibussowitsch if (nasm->fjtype != 1) PetscCall(VecScatterEnd(gscat, X, Xlloc, INSERT_VALUES, SCATTER_FORWARD)); 6739566063dSJacob Faibussowitsch PetscCall(SNESGetDM(subsnes, &subdm)); 6749566063dSJacob Faibussowitsch PetscCall(DMSubDomainRestrict(dm, oscat, gscat, subdm)); 675602bec5dSPeter Brune if (nasm->fjtype != 1) { 6769566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(subdm, Xlloc, INSERT_VALUES, Xl)); 6779566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(subdm, Xlloc, INSERT_VALUES, Xl)); 678602bec5dSPeter Brune } 679ca44f815SPeter Brune if (subsnes->lagjacobian == -1) subsnes->lagjacobian = -2; 680ca44f815SPeter Brune else if (subsnes->lagjacobian > 1) lag = subsnes->lagjacobian; 6819566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(subsnes, Xl, Fl)); 6829566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobian(subsnes, Xl, subsnes->jacobian, subsnes->jacobian_pre)); 683ca44f815SPeter Brune if (lag > 1) subsnes->lagjacobian = lag; 684d728fb7dSPeter Brune } 685d728fb7dSPeter Brune PetscFunctionReturn(0); 686d728fb7dSPeter Brune } 687d728fb7dSPeter Brune 6889371c9d4SSatish Balay static PetscErrorCode SNESSolve_NASM(SNES snes) { 689eaedb033SPeter Brune Vec F; 690eaedb033SPeter Brune Vec X; 691eaedb033SPeter Brune Vec B; 692111ade9eSPeter Brune Vec Y; 693eaedb033SPeter Brune PetscInt i; 694ed3c11a9SPeter Brune PetscReal fnorm = 0.0; 695365a6726SPeter Brune SNESNormSchedule normschedule; 696d728fb7dSPeter Brune SNES_NASM *nasm = (SNES_NASM *)snes->data; 697eaedb033SPeter Brune 698eaedb033SPeter Brune PetscFunctionBegin; 699c579b300SPatrick Farrell 7000b121fc5SBarry 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); 701c579b300SPatrick Farrell 7029566063dSJacob Faibussowitsch PetscCall(PetscCitationsRegister(SNESCitation, &SNEScite)); 703eaedb033SPeter Brune X = snes->vec_sol; 704111ade9eSPeter Brune Y = snes->vec_sol_update; 705eaedb033SPeter Brune F = snes->vec_func; 706eaedb033SPeter Brune B = snes->vec_rhs; 707eaedb033SPeter Brune 7089566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes)); 709eaedb033SPeter Brune snes->iter = 0; 710eaedb033SPeter Brune snes->norm = 0.; 7119566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes)); 712eaedb033SPeter Brune snes->reason = SNES_CONVERGED_ITERATING; 7139566063dSJacob Faibussowitsch PetscCall(SNESGetNormSchedule(snes, &normschedule)); 714365a6726SPeter Brune if (normschedule == SNES_NORM_ALWAYS || normschedule == SNES_NORM_INITIAL_ONLY || normschedule == SNES_NORM_INITIAL_FINAL_ONLY) { 715eaedb033SPeter Brune /* compute the initial function and preconditioned update delX */ 716eaedb033SPeter Brune if (!snes->vec_func_init_set) { 7179566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, X, F)); 7181aa26658SKarl Rupp } else snes->vec_func_init_set = PETSC_FALSE; 719eaedb033SPeter Brune 7209566063dSJacob Faibussowitsch PetscCall(VecNorm(F, NORM_2, &fnorm)); /* fnorm <- ||F|| */ 721422a814eSBarry Smith SNESCheckFunctionNorm(snes, fnorm); 7229566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes)); 723eaedb033SPeter Brune snes->iter = 0; 724eaedb033SPeter Brune snes->norm = fnorm; 7259566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes)); 7269566063dSJacob Faibussowitsch PetscCall(SNESLogConvergenceHistory(snes, snes->norm, 0)); 7279566063dSJacob Faibussowitsch PetscCall(SNESMonitor(snes, 0, snes->norm)); 728eaedb033SPeter Brune 729eaedb033SPeter Brune /* test convergence */ 730dbbe0bcdSBarry Smith PetscUseTypeMethod(snes, converged, 0, 0.0, 0.0, fnorm, &snes->reason, snes->cnvP); 731eaedb033SPeter Brune if (snes->reason) PetscFunctionReturn(0); 732eaedb033SPeter Brune } else { 7339566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes)); 7349566063dSJacob Faibussowitsch PetscCall(SNESLogConvergenceHistory(snes, snes->norm, 0)); 7359566063dSJacob Faibussowitsch PetscCall(SNESMonitor(snes, 0, snes->norm)); 736eaedb033SPeter Brune } 737eaedb033SPeter Brune 738eaedb033SPeter Brune /* Call general purpose update function */ 739dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, update, snes->iter); 740602bec5dSPeter Brune /* copy the initial solution over for later */ 7419566063dSJacob Faibussowitsch if (nasm->fjtype == 2) PetscCall(VecCopy(X, nasm->xinit)); 742eaedb033SPeter Brune 743eaedb033SPeter Brune for (i = 0; i < snes->max_its; i++) { 7449566063dSJacob Faibussowitsch PetscCall(SNESNASMSolveLocal_Private(snes, B, Y, X)); 745365a6726SPeter Brune if (normschedule == SNES_NORM_ALWAYS || ((i == snes->max_its - 1) && (normschedule == SNES_NORM_INITIAL_FINAL_ONLY || normschedule == SNES_NORM_FINAL_ONLY))) { 7469566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, X, F)); 7479566063dSJacob Faibussowitsch PetscCall(VecNorm(F, NORM_2, &fnorm)); /* fnorm <- ||F|| */ 748422a814eSBarry Smith SNESCheckFunctionNorm(snes, fnorm); 749eaedb033SPeter Brune } 750eaedb033SPeter Brune /* Monitor convergence */ 7519566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes)); 752eaedb033SPeter Brune snes->iter = i + 1; 753eaedb033SPeter Brune snes->norm = fnorm; 7549566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes)); 7559566063dSJacob Faibussowitsch PetscCall(SNESLogConvergenceHistory(snes, snes->norm, 0)); 7569566063dSJacob Faibussowitsch PetscCall(SNESMonitor(snes, snes->iter, snes->norm)); 757eaedb033SPeter Brune /* Test for convergence */ 758dbbe0bcdSBarry Smith if (normschedule == SNES_NORM_ALWAYS) PetscUseTypeMethod(snes, converged, snes->iter, 0.0, 0.0, fnorm, &snes->reason, snes->cnvP); 759d728fb7dSPeter Brune if (snes->reason) break; 760eaedb033SPeter Brune /* Call general purpose update function */ 761dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, update, snes->iter); 762eaedb033SPeter Brune } 76307b62357SFande Kong if (nasm->finaljacobian) { 7649566063dSJacob Faibussowitsch PetscCall(SNESNASMComputeFinalJacobian_Private(snes, X)); 76507b62357SFande Kong SNESCheckJacobianDomainerror(snes); 76607b62357SFande Kong } 767365a6726SPeter Brune if (normschedule == SNES_NORM_ALWAYS) { 768eaedb033SPeter Brune if (i == snes->max_its) { 76963a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Maximum number of iterations has been reached: %" PetscInt_FMT "\n", snes->max_its)); 770eaedb033SPeter Brune if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 771eaedb033SPeter Brune } 772f6dfbefdSBarry Smith } else if (!snes->reason) snes->reason = SNES_CONVERGED_ITS; /* NASM is meant to be used as a nonlinear preconditioner */ 773eaedb033SPeter Brune PetscFunctionReturn(0); 774eaedb033SPeter Brune } 775eaedb033SPeter Brune 776eaedb033SPeter Brune /*MC 777f6dfbefdSBarry Smith SNESNASM - Nonlinear Additive Schwarz solver 778eaedb033SPeter Brune 779f6dfbefdSBarry Smith Options Database Keys: 78070c78603SPeter Brune + -snes_nasm_log - enable logging events for the communication and solve stages 78170c78603SPeter Brune . -snes_nasm_type <basic,restrict> - type of subdomain update used 7825dfa0f3bSBarry Smith . -snes_asm_damping <dmp> - the new solution is obtained as old solution plus dmp times (sum of the solutions on the subdomains) 78370c78603SPeter Brune . -snes_nasm_finaljacobian - compute the local and global jacobians of the final iterate 784150d49b7SHong Zhang . -snes_nasm_finaljacobian_type <finalinner,finalouter,initial> - pick state the jacobian is calculated at 78570c78603SPeter Brune . -sub_snes_ - options prefix of the subdomain nonlinear solves 78670c78603SPeter Brune . -sub_ksp_ - options prefix of the subdomain Krylov solver 78770c78603SPeter Brune - -sub_pc_ - options prefix of the subdomain preconditioner 78870c78603SPeter Brune 789eaedb033SPeter Brune Level: advanced 790eaedb033SPeter Brune 791f6dfbefdSBarry Smith Note: 792f6dfbefdSBarry Smith This is not often used directly as a solver, it converges too slowly. However it works well as a nonlinear preconditioner for 793f6dfbefdSBarry Smith the `SNESASPIN` solver 794f6dfbefdSBarry Smith 795f6dfbefdSBarry Smith Developer Note: 796f6dfbefdSBarry Smith This is a non-Newton based nonlinear solver that does not directly require a Jacobian; hence the flag snes->usesksp is set to 797f6dfbefdSBarry Smith false and `SNESView()` and -snes_view do not display a `KSP` object. However, if the flag nasm->finaljacobian is set (for example, if 798f6dfbefdSBarry Smith `SNESNASM` is used as a nonlinear preconditioner for `SNESASPIN`) then `SNESSetUpMatrices()` is called to generate the 799f6dfbefdSBarry Smith Jacobian (needed by `SNESASPIN`) 800f6dfbefdSBarry 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 801f6dfbefdSBarry Smith used by `SNESASPIN` they share the same Jacobian matrices because `SNESSetUp()` (called on the outer `SNESASPIN`) causes the inner `SNES` 802f6dfbefdSBarry Smith object (in this case `SNESNASM`) to inherit the outer Jacobian matrices. 803951fe5abSBarry Smith 8044f02bc6aSBarry Smith References: 805606c0280SSatish Balay . * - Peter R. Brune, Matthew G. Knepley, Barry F. Smith, and Xuemin Tu, "Composing Scalable Nonlinear Algebraic Solvers", 8064f02bc6aSBarry Smith SIAM Review, 57(4), 2015 8074f02bc6aSBarry Smith 808db781477SPatrick Sanan .seealso: `SNESCreate()`, `SNES`, `SNESSetType()`, `SNESType`, `SNESNASMSetType()`, `SNESNASMGetType()`, `SNESNASMSetSubdomains()`, `SNESNASMGetSubdomains()`, `SNESNASMGetSubdomainVecs()`, `SNESNASMSetComputeFinalJacobian()`, `SNESNASMSetDamping()`, `SNESNASMGetDamping()` 809eaedb033SPeter Brune M*/ 810eaedb033SPeter Brune 8119371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode SNESCreate_NASM(SNES snes) { 812eaedb033SPeter Brune SNES_NASM *nasm; 813eaedb033SPeter Brune 814eaedb033SPeter Brune PetscFunctionBegin; 815*4dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&nasm)); 816eaedb033SPeter Brune snes->data = (void *)nasm; 817eaedb033SPeter Brune 818eaedb033SPeter Brune nasm->n = PETSC_DECIDE; 8199e5d0892SLisandro Dalcin nasm->subsnes = NULL; 8209e5d0892SLisandro Dalcin nasm->x = NULL; 8219e5d0892SLisandro Dalcin nasm->xl = NULL; 8229e5d0892SLisandro Dalcin nasm->y = NULL; 8239e5d0892SLisandro Dalcin nasm->b = NULL; 8249e5d0892SLisandro Dalcin nasm->oscatter = NULL; 8259e5d0892SLisandro Dalcin nasm->oscatter_copy = NULL; 8269e5d0892SLisandro Dalcin nasm->iscatter = NULL; 8279e5d0892SLisandro Dalcin nasm->gscatter = NULL; 828610116beSPeter Brune nasm->damping = 1.; 829111ade9eSPeter Brune 830111ade9eSPeter Brune nasm->type = PC_ASM_BASIC; 831d728fb7dSPeter Brune nasm->finaljacobian = PETSC_FALSE; 832f10b3e88SPatrick Farrell nasm->weight_set = PETSC_FALSE; 833eaedb033SPeter Brune 834eaedb033SPeter Brune snes->ops->destroy = SNESDestroy_NASM; 835eaedb033SPeter Brune snes->ops->setup = SNESSetUp_NASM; 836eaedb033SPeter Brune snes->ops->setfromoptions = SNESSetFromOptions_NASM; 837eaedb033SPeter Brune snes->ops->view = SNESView_NASM; 838eaedb033SPeter Brune snes->ops->solve = SNESSolve_NASM; 839eaedb033SPeter Brune snes->ops->reset = SNESReset_NASM; 840eaedb033SPeter Brune 841eaedb033SPeter Brune snes->usesksp = PETSC_FALSE; 842efd4aadfSBarry Smith snes->usesnpc = PETSC_FALSE; 843eaedb033SPeter Brune 8444fc747eaSLawrence Mitchell snes->alwayscomputesfinalresidual = PETSC_FALSE; 8454fc747eaSLawrence Mitchell 846602bec5dSPeter Brune nasm->fjtype = 0; 847602bec5dSPeter Brune nasm->xinit = NULL; 8480298fd71SBarry Smith nasm->eventrestrictinterp = 0; 8490298fd71SBarry Smith nasm->eventsubsolve = 0; 850b20c023fSPeter Brune 851eaedb033SPeter Brune if (!snes->tolerancesset) { 852eaedb033SPeter Brune snes->max_its = 10000; 853eaedb033SPeter Brune snes->max_funcs = 10000; 854eaedb033SPeter Brune } 855eaedb033SPeter Brune 8569566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMSetType_C", SNESNASMSetType_NASM)); 8579566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMGetType_C", SNESNASMGetType_NASM)); 8589566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMSetSubdomains_C", SNESNASMSetSubdomains_NASM)); 8599566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMGetSubdomains_C", SNESNASMGetSubdomains_NASM)); 8609566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMSetDamping_C", SNESNASMSetDamping_NASM)); 8619566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMGetDamping_C", SNESNASMGetDamping_NASM)); 8629566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMGetSubdomainVecs_C", SNESNASMGetSubdomainVecs_NASM)); 8639566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMSetComputeFinalJacobian_C", SNESNASMSetComputeFinalJacobian_NASM)); 864eaedb033SPeter Brune PetscFunctionReturn(0); 865eaedb033SPeter Brune } 86699e0435eSBarry Smith 867448b6425SPatrick Farrell /*@ 868448b6425SPatrick Farrell SNESNASMGetSNES - Gets a subsolver 869448b6425SPatrick Farrell 870448b6425SPatrick Farrell Not collective 871448b6425SPatrick Farrell 872448b6425SPatrick Farrell Input Parameters: 873448b6425SPatrick Farrell + snes - the SNES context 874448b6425SPatrick Farrell - i - the number of the subsnes to get 875448b6425SPatrick Farrell 876448b6425SPatrick Farrell Output Parameters: 877448b6425SPatrick Farrell . subsnes - the subsolver context 878448b6425SPatrick Farrell 879448b6425SPatrick Farrell Level: intermediate 880448b6425SPatrick Farrell 881db781477SPatrick Sanan .seealso: `SNESNASM`, `SNESNASMGetNumber()` 882448b6425SPatrick Farrell @*/ 8839371c9d4SSatish Balay PetscErrorCode SNESNASMGetSNES(SNES snes, PetscInt i, SNES *subsnes) { 884448b6425SPatrick Farrell SNES_NASM *nasm = (SNES_NASM *)snes->data; 885448b6425SPatrick Farrell 886448b6425SPatrick Farrell PetscFunctionBegin; 8870b121fc5SBarry Smith PetscCheck(i >= 0 && i < nasm->n, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "No such subsolver"); 888448b6425SPatrick Farrell *subsnes = nasm->subsnes[i]; 889448b6425SPatrick Farrell PetscFunctionReturn(0); 890448b6425SPatrick Farrell } 891448b6425SPatrick Farrell 892448b6425SPatrick Farrell /*@ 893448b6425SPatrick Farrell SNESNASMGetNumber - Gets number of subsolvers 894448b6425SPatrick Farrell 895448b6425SPatrick Farrell Not collective 896448b6425SPatrick Farrell 897448b6425SPatrick Farrell Input Parameters: 898448b6425SPatrick Farrell . snes - the SNES context 899448b6425SPatrick Farrell 900448b6425SPatrick Farrell Output Parameters: 901448b6425SPatrick Farrell . n - the number of subsolvers 902448b6425SPatrick Farrell 903448b6425SPatrick Farrell Level: intermediate 904448b6425SPatrick Farrell 905db781477SPatrick Sanan .seealso: `SNESNASM`, `SNESNASMGetSNES()` 906448b6425SPatrick Farrell @*/ 9079371c9d4SSatish Balay PetscErrorCode SNESNASMGetNumber(SNES snes, PetscInt *n) { 908448b6425SPatrick Farrell SNES_NASM *nasm = (SNES_NASM *)snes->data; 909448b6425SPatrick Farrell 910448b6425SPatrick Farrell PetscFunctionBegin; 911448b6425SPatrick Farrell *n = nasm->n; 912448b6425SPatrick Farrell PetscFunctionReturn(0); 913448b6425SPatrick Farrell } 914448b6425SPatrick Farrell 915f10b3e88SPatrick Farrell /*@ 916f10b3e88SPatrick Farrell SNESNASMSetWeight - Sets weight to use when adding overlapping updates 917f10b3e88SPatrick Farrell 918f10b3e88SPatrick Farrell Collective 919f10b3e88SPatrick Farrell 920f10b3e88SPatrick Farrell Input Parameters: 921f10b3e88SPatrick Farrell + snes - the SNES context 922f10b3e88SPatrick Farrell - weight - the weights to use (typically 1/N for each dof, where N is the number of patches it appears in) 923f10b3e88SPatrick Farrell 924f10b3e88SPatrick Farrell Level: intermediate 925f10b3e88SPatrick Farrell 926db781477SPatrick Sanan .seealso: `SNESNASM` 927f10b3e88SPatrick Farrell @*/ 9289371c9d4SSatish Balay PetscErrorCode SNESNASMSetWeight(SNES snes, Vec weight) { 929f10b3e88SPatrick Farrell SNES_NASM *nasm = (SNES_NASM *)snes->data; 930f10b3e88SPatrick Farrell 931f10b3e88SPatrick Farrell PetscFunctionBegin; 932f10b3e88SPatrick Farrell 9339566063dSJacob Faibussowitsch PetscCall(VecDestroy(&nasm->weight)); 934f10b3e88SPatrick Farrell nasm->weight_set = PETSC_TRUE; 935f10b3e88SPatrick Farrell nasm->weight = weight; 9369566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)nasm->weight)); 937f10b3e88SPatrick Farrell 938f10b3e88SPatrick Farrell PetscFunctionReturn(0); 939f10b3e88SPatrick Farrell } 940