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 64*48a46eb9SPierre 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)); 114*48a46eb9SPierre 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 */ 138*48a46eb9SPierre Jolivet if (!nasm->x) PetscCall(PetscCalloc1(nasm->n, &nasm->x)); 139*48a46eb9SPierre Jolivet if (!nasm->xl) PetscCall(PetscCalloc1(nasm->n, &nasm->xl)); 140*48a46eb9SPierre Jolivet if (!nasm->y) PetscCall(PetscCalloc1(nasm->n, &nasm->y)); 141*48a46eb9SPierre 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)); 156*48a46eb9SPierre Jolivet if (nasm->fjtype == 2) PetscCall(VecDuplicate(snes->vec_sol, &nasm->xinit)); 157*48a46eb9SPierre 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 /*@ 252e0331734SPeter Brune SNESNASMSetType - Set the type of subdomain update used 253e0331734SPeter Brune 254e0331734SPeter Brune Logically Collective on SNES 255e0331734SPeter Brune 256e0331734SPeter Brune Input Parameters: 257e0331734SPeter Brune + SNES - the SNES context 258e0331734SPeter Brune - type - the type of update, PC_ASM_BASIC or PC_ASM_RESTRICT 259e0331734SPeter Brune 260e0331734SPeter Brune Level: intermediate 261e0331734SPeter Brune 262db781477SPatrick Sanan .seealso: `SNESNASM`, `SNESNASMGetType()`, `PCASMSetType()` 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 /*@ 283e0331734SPeter Brune SNESNASMGetType - Get the type of subdomain update used 284e0331734SPeter Brune 285e0331734SPeter Brune Logically Collective on SNES 286e0331734SPeter Brune 287e0331734SPeter Brune Input Parameters: 288e0331734SPeter Brune . 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 295db781477SPatrick Sanan .seealso: `SNESNASM`, `SNESNASMSetType()`, `PCASMGetType()` 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 /*@ 31276857b2aSPeter Brune SNESNASMSetSubdomains - Manually Set the context required to restrict and solve subdomain problems. 31376857b2aSPeter Brune 31476857b2aSPeter Brune Not Collective 31576857b2aSPeter Brune 31676857b2aSPeter Brune Input Parameters: 31776857b2aSPeter Brune + 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)); 3679371c9d4SSatish Balay for (i = 0; i < n; i++) { nasm->iscatter[i] = iscatter[i]; } 368eaedb033SPeter Brune } 369111ade9eSPeter Brune if (gscatter) { 3709566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &nasm->gscatter)); 3719371c9d4SSatish Balay 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)); 3769371c9d4SSatish Balay for (i = 0; i < n; i++) { nasm->subsnes[i] = subsnes[i]; } 377eaedb033SPeter Brune } 378eaedb033SPeter Brune PetscFunctionReturn(0); 379eaedb033SPeter Brune } 380eaedb033SPeter Brune 38176857b2aSPeter Brune /*@ 38276857b2aSPeter Brune SNESNASMGetSubdomains - Get the local subdomain context. 38376857b2aSPeter Brune 38476857b2aSPeter Brune Not Collective 38576857b2aSPeter Brune 386f899ff85SJose E. Roman Input Parameter: 38776857b2aSPeter Brune . 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 /*@ 42276857b2aSPeter Brune SNESNASMGetSubdomainVecs - Get the processor-local subdomain vectors 42376857b2aSPeter Brune 42476857b2aSPeter Brune Not Collective 42576857b2aSPeter Brune 426f899ff85SJose E. Roman Input Parameter: 42776857b2aSPeter Brune . 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 /*@ 4628bf45196SRichard Tran Mills SNESNASMSetComputeFinalJacobian - Schedules the computation of the global and subdomain Jacobians upon convergence 463d728fb7dSPeter Brune 464d728fb7dSPeter Brune Collective on SNES 465d728fb7dSPeter Brune 466d728fb7dSPeter Brune Input Parameters: 467d728fb7dSPeter Brune + SNES - the SNES context 4688bf45196SRichard Tran Mills - flg - indication of whether to compute the Jacobians or not 469d728fb7dSPeter Brune 470d728fb7dSPeter Brune Level: developer 471d728fb7dSPeter Brune 47295452b02SPatrick Sanan Notes: 4738bf45196SRichard Tran Mills This is used almost exclusively in the implementation of ASPIN, where the converged subdomain and global Jacobian 474d728fb7dSPeter Brune is needed at each linear iteration. 475d728fb7dSPeter Brune 476db781477SPatrick Sanan .seealso: `SNESNASM`, `SNESNASMGetSubdomains()` 477d728fb7dSPeter Brune @*/ 4789371c9d4SSatish Balay PetscErrorCode SNESNASMSetComputeFinalJacobian(SNES snes, PetscBool flg) { 479d728fb7dSPeter Brune PetscErrorCode (*f)(SNES, PetscBool); 480d728fb7dSPeter Brune 481d728fb7dSPeter Brune PetscFunctionBegin; 4829566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)snes, "SNESNASMSetComputeFinalJacobian_C", &f)); 4839566063dSJacob Faibussowitsch if (f) PetscCall((f)(snes, flg)); 484d728fb7dSPeter Brune PetscFunctionReturn(0); 485d728fb7dSPeter Brune } 486d728fb7dSPeter Brune 4879371c9d4SSatish Balay static PetscErrorCode SNESNASMSetComputeFinalJacobian_NASM(SNES snes, PetscBool flg) { 488d728fb7dSPeter Brune SNES_NASM *nasm = (SNES_NASM *)snes->data; 489d728fb7dSPeter Brune 490d728fb7dSPeter Brune PetscFunctionBegin; 491d728fb7dSPeter Brune nasm->finaljacobian = flg; 492d728fb7dSPeter Brune PetscFunctionReturn(0); 493d728fb7dSPeter Brune } 49476857b2aSPeter Brune 495610116beSPeter Brune /*@ 496610116beSPeter Brune SNESNASMSetDamping - Sets the update damping for NASM 497610116beSPeter Brune 498610116beSPeter Brune Logically collective on SNES 499610116beSPeter Brune 500610116beSPeter Brune Input Parameters: 501610116beSPeter Brune + SNES - the SNES context 502610116beSPeter Brune - dmp - damping 503610116beSPeter Brune 504610116beSPeter Brune Level: intermediate 505610116beSPeter Brune 50695452b02SPatrick Sanan Notes: 50795452b02SPatrick Sanan The new solution is obtained as old solution plus dmp times (sum of the solutions on the subdomains) 5085dfa0f3bSBarry Smith 509db781477SPatrick Sanan .seealso: `SNESNASM`, `SNESNASMGetDamping()` 510610116beSPeter Brune @*/ 5119371c9d4SSatish Balay PetscErrorCode SNESNASMSetDamping(SNES snes, PetscReal dmp) { 512610116beSPeter Brune PetscErrorCode (*f)(SNES, PetscReal); 513610116beSPeter Brune 514610116beSPeter Brune PetscFunctionBegin; 5159566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)snes, "SNESNASMSetDamping_C", (void (**)(void)) & f)); 5169566063dSJacob Faibussowitsch if (f) PetscCall((f)(snes, dmp)); 517610116beSPeter Brune PetscFunctionReturn(0); 518610116beSPeter Brune } 519610116beSPeter Brune 5209371c9d4SSatish Balay static PetscErrorCode SNESNASMSetDamping_NASM(SNES snes, PetscReal dmp) { 521610116beSPeter Brune SNES_NASM *nasm = (SNES_NASM *)snes->data; 522610116beSPeter Brune 523610116beSPeter Brune PetscFunctionBegin; 524610116beSPeter Brune nasm->damping = dmp; 525610116beSPeter Brune PetscFunctionReturn(0); 526610116beSPeter Brune } 527610116beSPeter Brune 528610116beSPeter Brune /*@ 529610116beSPeter Brune SNESNASMGetDamping - Gets the update damping for NASM 530610116beSPeter Brune 531610116beSPeter Brune Not Collective 532610116beSPeter Brune 533610116beSPeter Brune Input Parameters: 534610116beSPeter Brune + SNES - the SNES context 535610116beSPeter Brune - dmp - damping 536610116beSPeter Brune 537610116beSPeter Brune Level: intermediate 538610116beSPeter Brune 539db781477SPatrick Sanan .seealso: `SNESNASM`, `SNESNASMSetDamping()` 540610116beSPeter Brune @*/ 5419371c9d4SSatish Balay PetscErrorCode SNESNASMGetDamping(SNES snes, PetscReal *dmp) { 542610116beSPeter Brune PetscFunctionBegin; 543cac4c232SBarry Smith PetscUseMethod(snes, "SNESNASMGetDamping_C", (SNES, PetscReal *), (snes, dmp)); 544610116beSPeter Brune PetscFunctionReturn(0); 545610116beSPeter Brune } 546610116beSPeter Brune 5479371c9d4SSatish Balay static PetscErrorCode SNESNASMGetDamping_NASM(SNES snes, PetscReal *dmp) { 548610116beSPeter Brune SNES_NASM *nasm = (SNES_NASM *)snes->data; 549610116beSPeter Brune 550610116beSPeter Brune PetscFunctionBegin; 551610116beSPeter Brune *dmp = nasm->damping; 552610116beSPeter Brune PetscFunctionReturn(0); 553610116beSPeter Brune } 554610116beSPeter Brune 55514eb1c5cSMatthew G. Knepley /* 55614eb1c5cSMatthew G. Knepley Input Parameters: 55714eb1c5cSMatthew G. Knepley + snes - The solver 55814eb1c5cSMatthew G. Knepley . B - The RHS vector 55914eb1c5cSMatthew G. Knepley - X - The initial guess 56014eb1c5cSMatthew G. Knepley 56114eb1c5cSMatthew G. Knepley Output Parameters: 56214eb1c5cSMatthew G. Knepley . Y - The solution update 56314eb1c5cSMatthew G. Knepley 56414eb1c5cSMatthew G. Knepley TODO: All scatters should be packed into one 56514eb1c5cSMatthew G. Knepley */ 5669371c9d4SSatish Balay PetscErrorCode SNESNASMSolveLocal_Private(SNES snes, Vec B, Vec Y, Vec X) { 567eaedb033SPeter Brune SNES_NASM *nasm = (SNES_NASM *)snes->data; 568258e1594SPeter Brune SNES subsnes; 569eaedb033SPeter Brune PetscInt i; 570610116beSPeter Brune PetscReal dmp; 571f10b3e88SPatrick Farrell Vec Xl, Bl, Yl, Xlloc; 572f10b3e88SPatrick Farrell VecScatter iscat, oscat, gscat, oscat_copy; 573111ade9eSPeter Brune DM dm, subdm; 574e0331734SPeter Brune PCASMType type; 5750adebc6cSBarry Smith 576eaedb033SPeter Brune PetscFunctionBegin; 5779566063dSJacob Faibussowitsch PetscCall(SNESNASMGetType(snes, &type)); 5789566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 5799566063dSJacob Faibussowitsch PetscCall(VecSet(Y, 0)); 5809566063dSJacob Faibussowitsch if (nasm->eventrestrictinterp) PetscCall(PetscLogEventBegin(nasm->eventrestrictinterp, snes, 0, 0, 0)); 581eaedb033SPeter Brune for (i = 0; i < nasm->n; i++) { 582f10b3e88SPatrick Farrell /* scatter the solution to the global solution and the local solution */ 583f10b3e88SPatrick Farrell Xl = nasm->x[i]; 58470c78f05SPeter Brune Xlloc = nasm->xl[i]; 58570c78f05SPeter Brune oscat = nasm->oscatter[i]; 586f10b3e88SPatrick Farrell oscat_copy = nasm->oscatter_copy[i]; 587f10b3e88SPatrick Farrell gscat = nasm->gscatter[i]; 5889566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(oscat, X, Xl, INSERT_VALUES, SCATTER_FORWARD)); 5899566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(gscat, X, Xlloc, INSERT_VALUES, SCATTER_FORWARD)); 59070c78f05SPeter Brune if (B) { 59170c78f05SPeter Brune /* scatter the RHS to the local RHS */ 59270c78f05SPeter Brune Bl = nasm->b[i]; 5939566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(oscat_copy, B, Bl, INSERT_VALUES, SCATTER_FORWARD)); 59470c78f05SPeter Brune } 59570c78f05SPeter Brune } 5969566063dSJacob Faibussowitsch if (nasm->eventrestrictinterp) PetscCall(PetscLogEventEnd(nasm->eventrestrictinterp, snes, 0, 0, 0)); 597b20c023fSPeter Brune 5989566063dSJacob Faibussowitsch if (nasm->eventsubsolve) PetscCall(PetscLogEventBegin(nasm->eventsubsolve, snes, 0, 0, 0)); 59970c78f05SPeter Brune for (i = 0; i < nasm->n; i++) { 60070c78f05SPeter Brune Xl = nasm->x[i]; 60170c78f05SPeter Brune Xlloc = nasm->xl[i]; 60270c78f05SPeter Brune Yl = nasm->y[i]; 603258e1594SPeter Brune subsnes = nasm->subsnes[i]; 6049566063dSJacob Faibussowitsch PetscCall(SNESGetDM(subsnes, &subdm)); 605111ade9eSPeter Brune iscat = nasm->iscatter[i]; 606111ade9eSPeter Brune oscat = nasm->oscatter[i]; 607f10b3e88SPatrick Farrell oscat_copy = nasm->oscatter_copy[i]; 608111ade9eSPeter Brune gscat = nasm->gscatter[i]; 6099566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(oscat, X, Xl, INSERT_VALUES, SCATTER_FORWARD)); 6109566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(gscat, X, Xlloc, INSERT_VALUES, SCATTER_FORWARD)); 61124b7f281SPeter Brune if (B) { 61224b7f281SPeter Brune Bl = nasm->b[i]; 6139566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(oscat_copy, B, Bl, INSERT_VALUES, SCATTER_FORWARD)); 614ed3c11a9SPeter Brune } else Bl = NULL; 615f10b3e88SPatrick Farrell 6169566063dSJacob Faibussowitsch PetscCall(DMSubDomainRestrict(dm, oscat, gscat, subdm)); 6179566063dSJacob Faibussowitsch PetscCall(VecCopy(Xl, Yl)); 6189566063dSJacob Faibussowitsch PetscCall(SNESSolve(subsnes, Bl, Xl)); 6199566063dSJacob Faibussowitsch PetscCall(VecAYPX(Yl, -1.0, Xl)); 6209566063dSJacob Faibussowitsch PetscCall(VecScale(Yl, nasm->damping)); 621e0331734SPeter Brune if (type == PC_ASM_BASIC) { 6229566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(oscat, Yl, Y, ADD_VALUES, SCATTER_REVERSE)); 6239566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(oscat, Yl, Y, ADD_VALUES, SCATTER_REVERSE)); 624e0331734SPeter Brune } else if (type == PC_ASM_RESTRICT) { 6259566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(iscat, Yl, Y, ADD_VALUES, SCATTER_REVERSE)); 6269566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(iscat, Yl, Y, ADD_VALUES, SCATTER_REVERSE)); 627ce94432eSBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONGSTATE, "Only basic and restrict types are supported for SNESNASM"); 628eaedb033SPeter Brune } 6299566063dSJacob Faibussowitsch if (nasm->eventsubsolve) PetscCall(PetscLogEventEnd(nasm->eventsubsolve, snes, 0, 0, 0)); 6309566063dSJacob Faibussowitsch if (nasm->eventrestrictinterp) PetscCall(PetscLogEventBegin(nasm->eventrestrictinterp, snes, 0, 0, 0)); 6311baa6e33SBarry Smith if (nasm->weight_set) PetscCall(VecPointwiseMult(Y, Y, nasm->weight)); 6329566063dSJacob Faibussowitsch if (nasm->eventrestrictinterp) PetscCall(PetscLogEventEnd(nasm->eventrestrictinterp, snes, 0, 0, 0)); 6339566063dSJacob Faibussowitsch PetscCall(SNESNASMGetDamping(snes, &dmp)); 6349566063dSJacob Faibussowitsch PetscCall(VecAXPY(X, dmp, Y)); 635eaedb033SPeter Brune PetscFunctionReturn(0); 636eaedb033SPeter Brune } 637eaedb033SPeter Brune 6389371c9d4SSatish Balay static PetscErrorCode SNESNASMComputeFinalJacobian_Private(SNES snes, Vec Xfinal) { 639602bec5dSPeter Brune Vec X = Xfinal; 640d728fb7dSPeter Brune SNES_NASM *nasm = (SNES_NASM *)snes->data; 641d728fb7dSPeter Brune SNES subsnes; 642ca44f815SPeter Brune PetscInt i, lag = 1; 643e59f0a30SPeter Brune Vec Xlloc, Xl, Fl, F; 644d728fb7dSPeter Brune VecScatter oscat, gscat; 645d728fb7dSPeter Brune DM dm, subdm; 646d1e9a80fSBarry Smith 647d728fb7dSPeter Brune PetscFunctionBegin; 648602bec5dSPeter Brune if (nasm->fjtype == 2) X = nasm->xinit; 649e59f0a30SPeter Brune F = snes->vec_func; 6509566063dSJacob Faibussowitsch if (snes->normschedule == SNES_NORM_NONE) PetscCall(SNESComputeFunction(snes, X, F)); 6519566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobian(snes, X, snes->jacobian, snes->jacobian_pre)); 6529566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 6539566063dSJacob Faibussowitsch if (nasm->eventrestrictinterp) PetscCall(PetscLogEventBegin(nasm->eventrestrictinterp, snes, 0, 0, 0)); 654602bec5dSPeter Brune if (nasm->fjtype != 1) { 655d728fb7dSPeter Brune for (i = 0; i < nasm->n; i++) { 656d728fb7dSPeter Brune Xlloc = nasm->xl[i]; 657d728fb7dSPeter Brune gscat = nasm->gscatter[i]; 6589566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(gscat, X, Xlloc, INSERT_VALUES, SCATTER_FORWARD)); 659602bec5dSPeter Brune } 660d728fb7dSPeter Brune } 6619566063dSJacob Faibussowitsch if (nasm->eventrestrictinterp) PetscCall(PetscLogEventEnd(nasm->eventrestrictinterp, snes, 0, 0, 0)); 662d728fb7dSPeter Brune for (i = 0; i < nasm->n; i++) { 663e59f0a30SPeter Brune Fl = nasm->subsnes[i]->vec_func; 664d728fb7dSPeter Brune Xl = nasm->x[i]; 665d728fb7dSPeter Brune Xlloc = nasm->xl[i]; 666d728fb7dSPeter Brune subsnes = nasm->subsnes[i]; 667d728fb7dSPeter Brune oscat = nasm->oscatter[i]; 668d728fb7dSPeter Brune gscat = nasm->gscatter[i]; 6699566063dSJacob Faibussowitsch if (nasm->fjtype != 1) PetscCall(VecScatterEnd(gscat, X, Xlloc, INSERT_VALUES, SCATTER_FORWARD)); 6709566063dSJacob Faibussowitsch PetscCall(SNESGetDM(subsnes, &subdm)); 6719566063dSJacob Faibussowitsch PetscCall(DMSubDomainRestrict(dm, oscat, gscat, subdm)); 672602bec5dSPeter Brune if (nasm->fjtype != 1) { 6739566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(subdm, Xlloc, INSERT_VALUES, Xl)); 6749566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(subdm, Xlloc, INSERT_VALUES, Xl)); 675602bec5dSPeter Brune } 676ca44f815SPeter Brune if (subsnes->lagjacobian == -1) subsnes->lagjacobian = -2; 677ca44f815SPeter Brune else if (subsnes->lagjacobian > 1) lag = subsnes->lagjacobian; 6789566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(subsnes, Xl, Fl)); 6799566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobian(subsnes, Xl, subsnes->jacobian, subsnes->jacobian_pre)); 680ca44f815SPeter Brune if (lag > 1) subsnes->lagjacobian = lag; 681d728fb7dSPeter Brune } 682d728fb7dSPeter Brune PetscFunctionReturn(0); 683d728fb7dSPeter Brune } 684d728fb7dSPeter Brune 6859371c9d4SSatish Balay static PetscErrorCode SNESSolve_NASM(SNES snes) { 686eaedb033SPeter Brune Vec F; 687eaedb033SPeter Brune Vec X; 688eaedb033SPeter Brune Vec B; 689111ade9eSPeter Brune Vec Y; 690eaedb033SPeter Brune PetscInt i; 691ed3c11a9SPeter Brune PetscReal fnorm = 0.0; 692365a6726SPeter Brune SNESNormSchedule normschedule; 693d728fb7dSPeter Brune SNES_NASM *nasm = (SNES_NASM *)snes->data; 694eaedb033SPeter Brune 695eaedb033SPeter Brune PetscFunctionBegin; 696c579b300SPatrick Farrell 6970b121fc5SBarry 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); 698c579b300SPatrick Farrell 6999566063dSJacob Faibussowitsch PetscCall(PetscCitationsRegister(SNESCitation, &SNEScite)); 700eaedb033SPeter Brune X = snes->vec_sol; 701111ade9eSPeter Brune Y = snes->vec_sol_update; 702eaedb033SPeter Brune F = snes->vec_func; 703eaedb033SPeter Brune B = snes->vec_rhs; 704eaedb033SPeter Brune 7059566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes)); 706eaedb033SPeter Brune snes->iter = 0; 707eaedb033SPeter Brune snes->norm = 0.; 7089566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes)); 709eaedb033SPeter Brune snes->reason = SNES_CONVERGED_ITERATING; 7109566063dSJacob Faibussowitsch PetscCall(SNESGetNormSchedule(snes, &normschedule)); 711365a6726SPeter Brune if (normschedule == SNES_NORM_ALWAYS || normschedule == SNES_NORM_INITIAL_ONLY || normschedule == SNES_NORM_INITIAL_FINAL_ONLY) { 712eaedb033SPeter Brune /* compute the initial function and preconditioned update delX */ 713eaedb033SPeter Brune if (!snes->vec_func_init_set) { 7149566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, X, F)); 7151aa26658SKarl Rupp } else snes->vec_func_init_set = PETSC_FALSE; 716eaedb033SPeter Brune 7179566063dSJacob Faibussowitsch PetscCall(VecNorm(F, NORM_2, &fnorm)); /* fnorm <- ||F|| */ 718422a814eSBarry Smith SNESCheckFunctionNorm(snes, fnorm); 7199566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes)); 720eaedb033SPeter Brune snes->iter = 0; 721eaedb033SPeter Brune snes->norm = fnorm; 7229566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes)); 7239566063dSJacob Faibussowitsch PetscCall(SNESLogConvergenceHistory(snes, snes->norm, 0)); 7249566063dSJacob Faibussowitsch PetscCall(SNESMonitor(snes, 0, snes->norm)); 725eaedb033SPeter Brune 726eaedb033SPeter Brune /* test convergence */ 727dbbe0bcdSBarry Smith PetscUseTypeMethod(snes, converged, 0, 0.0, 0.0, fnorm, &snes->reason, snes->cnvP); 728eaedb033SPeter Brune if (snes->reason) PetscFunctionReturn(0); 729eaedb033SPeter Brune } else { 7309566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes)); 7319566063dSJacob Faibussowitsch PetscCall(SNESLogConvergenceHistory(snes, snes->norm, 0)); 7329566063dSJacob Faibussowitsch PetscCall(SNESMonitor(snes, 0, snes->norm)); 733eaedb033SPeter Brune } 734eaedb033SPeter Brune 735eaedb033SPeter Brune /* Call general purpose update function */ 736dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, update, snes->iter); 737602bec5dSPeter Brune /* copy the initial solution over for later */ 7389566063dSJacob Faibussowitsch if (nasm->fjtype == 2) PetscCall(VecCopy(X, nasm->xinit)); 739eaedb033SPeter Brune 740eaedb033SPeter Brune for (i = 0; i < snes->max_its; i++) { 7419566063dSJacob Faibussowitsch PetscCall(SNESNASMSolveLocal_Private(snes, B, Y, X)); 742365a6726SPeter Brune if (normschedule == SNES_NORM_ALWAYS || ((i == snes->max_its - 1) && (normschedule == SNES_NORM_INITIAL_FINAL_ONLY || normschedule == SNES_NORM_FINAL_ONLY))) { 7439566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, X, F)); 7449566063dSJacob Faibussowitsch PetscCall(VecNorm(F, NORM_2, &fnorm)); /* fnorm <- ||F|| */ 745422a814eSBarry Smith SNESCheckFunctionNorm(snes, fnorm); 746eaedb033SPeter Brune } 747eaedb033SPeter Brune /* Monitor convergence */ 7489566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes)); 749eaedb033SPeter Brune snes->iter = i + 1; 750eaedb033SPeter Brune snes->norm = fnorm; 7519566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes)); 7529566063dSJacob Faibussowitsch PetscCall(SNESLogConvergenceHistory(snes, snes->norm, 0)); 7539566063dSJacob Faibussowitsch PetscCall(SNESMonitor(snes, snes->iter, snes->norm)); 754eaedb033SPeter Brune /* Test for convergence */ 755dbbe0bcdSBarry Smith if (normschedule == SNES_NORM_ALWAYS) PetscUseTypeMethod(snes, converged, snes->iter, 0.0, 0.0, fnorm, &snes->reason, snes->cnvP); 756d728fb7dSPeter Brune if (snes->reason) break; 757eaedb033SPeter Brune /* Call general purpose update function */ 758dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, update, snes->iter); 759eaedb033SPeter Brune } 76007b62357SFande Kong if (nasm->finaljacobian) { 7619566063dSJacob Faibussowitsch PetscCall(SNESNASMComputeFinalJacobian_Private(snes, X)); 76207b62357SFande Kong SNESCheckJacobianDomainerror(snes); 76307b62357SFande Kong } 764365a6726SPeter Brune if (normschedule == SNES_NORM_ALWAYS) { 765eaedb033SPeter Brune if (i == snes->max_its) { 76663a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Maximum number of iterations has been reached: %" PetscInt_FMT "\n", snes->max_its)); 767eaedb033SPeter Brune if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 768eaedb033SPeter Brune } 7691aa26658SKarl Rupp } else if (!snes->reason) snes->reason = SNES_CONVERGED_ITS; /* NASM is meant to be used as a preconditioner */ 770eaedb033SPeter Brune PetscFunctionReturn(0); 771eaedb033SPeter Brune } 772eaedb033SPeter Brune 773eaedb033SPeter Brune /*MC 774f3f228e0SPierre Jolivet SNESNASM - Nonlinear Additive Schwarz 775eaedb033SPeter Brune 77670c78603SPeter Brune Options Database: 77770c78603SPeter Brune + -snes_nasm_log - enable logging events for the communication and solve stages 77870c78603SPeter Brune . -snes_nasm_type <basic,restrict> - type of subdomain update used 7795dfa0f3bSBarry Smith . -snes_asm_damping <dmp> - the new solution is obtained as old solution plus dmp times (sum of the solutions on the subdomains) 78070c78603SPeter Brune . -snes_nasm_finaljacobian - compute the local and global jacobians of the final iterate 781150d49b7SHong Zhang . -snes_nasm_finaljacobian_type <finalinner,finalouter,initial> - pick state the jacobian is calculated at 78270c78603SPeter Brune . -sub_snes_ - options prefix of the subdomain nonlinear solves 78370c78603SPeter Brune . -sub_ksp_ - options prefix of the subdomain Krylov solver 78470c78603SPeter Brune - -sub_pc_ - options prefix of the subdomain preconditioner 78570c78603SPeter Brune 786eaedb033SPeter Brune Level: advanced 787eaedb033SPeter Brune 788951fe5abSBarry Smith Developer Note: This is a non-Newton based nonlinear solver that does not directly require a Jacobian; hence the flag snes->usesksp is set to 7897f851d37SRichard Tran Mills false and SNESView() and -snes_view do not display a KSP object. However, if the flag nasm->finaljacobian is set (for example, if 790951fe5abSBarry Smith NASM is used as a nonlinear preconditioner for KSPASPIN) then SNESSetUpMatrices() is called to generate the Jacobian (needed by KSPASPIN) 791951fe5abSBarry Smith and this utilizes the KSP for storing the matrices, but the KSP is never used for solving a linear system. Note that when SNESNASM is 792951fe5abSBarry Smith used by SNESASPIN they share the same Jacobian matrices because SNESSetUp() (called on the outer SNES KSPASPIN) causes the inner SNES 793951fe5abSBarry Smith object (in this case SNESNASM) to inherit the outer Jacobian matrices. 794951fe5abSBarry Smith 7954f02bc6aSBarry Smith References: 796606c0280SSatish Balay . * - Peter R. Brune, Matthew G. Knepley, Barry F. Smith, and Xuemin Tu, "Composing Scalable Nonlinear Algebraic Solvers", 7974f02bc6aSBarry Smith SIAM Review, 57(4), 2015 7984f02bc6aSBarry Smith 799db781477SPatrick Sanan .seealso: `SNESCreate()`, `SNES`, `SNESSetType()`, `SNESType`, `SNESNASMSetType()`, `SNESNASMGetType()`, `SNESNASMSetSubdomains()`, `SNESNASMGetSubdomains()`, `SNESNASMGetSubdomainVecs()`, `SNESNASMSetComputeFinalJacobian()`, `SNESNASMSetDamping()`, `SNESNASMGetDamping()` 800eaedb033SPeter Brune M*/ 801eaedb033SPeter Brune 8029371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode SNESCreate_NASM(SNES snes) { 803eaedb033SPeter Brune SNES_NASM *nasm; 804eaedb033SPeter Brune 805eaedb033SPeter Brune PetscFunctionBegin; 8069566063dSJacob Faibussowitsch PetscCall(PetscNewLog(snes, &nasm)); 807eaedb033SPeter Brune snes->data = (void *)nasm; 808eaedb033SPeter Brune 809eaedb033SPeter Brune nasm->n = PETSC_DECIDE; 8109e5d0892SLisandro Dalcin nasm->subsnes = NULL; 8119e5d0892SLisandro Dalcin nasm->x = NULL; 8129e5d0892SLisandro Dalcin nasm->xl = NULL; 8139e5d0892SLisandro Dalcin nasm->y = NULL; 8149e5d0892SLisandro Dalcin nasm->b = NULL; 8159e5d0892SLisandro Dalcin nasm->oscatter = NULL; 8169e5d0892SLisandro Dalcin nasm->oscatter_copy = NULL; 8179e5d0892SLisandro Dalcin nasm->iscatter = NULL; 8189e5d0892SLisandro Dalcin nasm->gscatter = NULL; 819610116beSPeter Brune nasm->damping = 1.; 820111ade9eSPeter Brune 821111ade9eSPeter Brune nasm->type = PC_ASM_BASIC; 822d728fb7dSPeter Brune nasm->finaljacobian = PETSC_FALSE; 823f10b3e88SPatrick Farrell nasm->weight_set = PETSC_FALSE; 824eaedb033SPeter Brune 825eaedb033SPeter Brune snes->ops->destroy = SNESDestroy_NASM; 826eaedb033SPeter Brune snes->ops->setup = SNESSetUp_NASM; 827eaedb033SPeter Brune snes->ops->setfromoptions = SNESSetFromOptions_NASM; 828eaedb033SPeter Brune snes->ops->view = SNESView_NASM; 829eaedb033SPeter Brune snes->ops->solve = SNESSolve_NASM; 830eaedb033SPeter Brune snes->ops->reset = SNESReset_NASM; 831eaedb033SPeter Brune 832eaedb033SPeter Brune snes->usesksp = PETSC_FALSE; 833efd4aadfSBarry Smith snes->usesnpc = PETSC_FALSE; 834eaedb033SPeter Brune 8354fc747eaSLawrence Mitchell snes->alwayscomputesfinalresidual = PETSC_FALSE; 8364fc747eaSLawrence Mitchell 837602bec5dSPeter Brune nasm->fjtype = 0; 838602bec5dSPeter Brune nasm->xinit = NULL; 8390298fd71SBarry Smith nasm->eventrestrictinterp = 0; 8400298fd71SBarry Smith nasm->eventsubsolve = 0; 841b20c023fSPeter Brune 842eaedb033SPeter Brune if (!snes->tolerancesset) { 843eaedb033SPeter Brune snes->max_its = 10000; 844eaedb033SPeter Brune snes->max_funcs = 10000; 845eaedb033SPeter Brune } 846eaedb033SPeter Brune 8479566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMSetType_C", SNESNASMSetType_NASM)); 8489566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMGetType_C", SNESNASMGetType_NASM)); 8499566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMSetSubdomains_C", SNESNASMSetSubdomains_NASM)); 8509566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMGetSubdomains_C", SNESNASMGetSubdomains_NASM)); 8519566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMSetDamping_C", SNESNASMSetDamping_NASM)); 8529566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMGetDamping_C", SNESNASMGetDamping_NASM)); 8539566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMGetSubdomainVecs_C", SNESNASMGetSubdomainVecs_NASM)); 8549566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESNASMSetComputeFinalJacobian_C", SNESNASMSetComputeFinalJacobian_NASM)); 855eaedb033SPeter Brune PetscFunctionReturn(0); 856eaedb033SPeter Brune } 85799e0435eSBarry Smith 858448b6425SPatrick Farrell /*@ 859448b6425SPatrick Farrell SNESNASMGetSNES - Gets a subsolver 860448b6425SPatrick Farrell 861448b6425SPatrick Farrell Not collective 862448b6425SPatrick Farrell 863448b6425SPatrick Farrell Input Parameters: 864448b6425SPatrick Farrell + snes - the SNES context 865448b6425SPatrick Farrell - i - the number of the subsnes to get 866448b6425SPatrick Farrell 867448b6425SPatrick Farrell Output Parameters: 868448b6425SPatrick Farrell . subsnes - the subsolver context 869448b6425SPatrick Farrell 870448b6425SPatrick Farrell Level: intermediate 871448b6425SPatrick Farrell 872db781477SPatrick Sanan .seealso: `SNESNASM`, `SNESNASMGetNumber()` 873448b6425SPatrick Farrell @*/ 8749371c9d4SSatish Balay PetscErrorCode SNESNASMGetSNES(SNES snes, PetscInt i, SNES *subsnes) { 875448b6425SPatrick Farrell SNES_NASM *nasm = (SNES_NASM *)snes->data; 876448b6425SPatrick Farrell 877448b6425SPatrick Farrell PetscFunctionBegin; 8780b121fc5SBarry Smith PetscCheck(i >= 0 && i < nasm->n, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "No such subsolver"); 879448b6425SPatrick Farrell *subsnes = nasm->subsnes[i]; 880448b6425SPatrick Farrell PetscFunctionReturn(0); 881448b6425SPatrick Farrell } 882448b6425SPatrick Farrell 883448b6425SPatrick Farrell /*@ 884448b6425SPatrick Farrell SNESNASMGetNumber - Gets number of subsolvers 885448b6425SPatrick Farrell 886448b6425SPatrick Farrell Not collective 887448b6425SPatrick Farrell 888448b6425SPatrick Farrell Input Parameters: 889448b6425SPatrick Farrell . snes - the SNES context 890448b6425SPatrick Farrell 891448b6425SPatrick Farrell Output Parameters: 892448b6425SPatrick Farrell . n - the number of subsolvers 893448b6425SPatrick Farrell 894448b6425SPatrick Farrell Level: intermediate 895448b6425SPatrick Farrell 896db781477SPatrick Sanan .seealso: `SNESNASM`, `SNESNASMGetSNES()` 897448b6425SPatrick Farrell @*/ 8989371c9d4SSatish Balay PetscErrorCode SNESNASMGetNumber(SNES snes, PetscInt *n) { 899448b6425SPatrick Farrell SNES_NASM *nasm = (SNES_NASM *)snes->data; 900448b6425SPatrick Farrell 901448b6425SPatrick Farrell PetscFunctionBegin; 902448b6425SPatrick Farrell *n = nasm->n; 903448b6425SPatrick Farrell PetscFunctionReturn(0); 904448b6425SPatrick Farrell } 905448b6425SPatrick Farrell 906f10b3e88SPatrick Farrell /*@ 907f10b3e88SPatrick Farrell SNESNASMSetWeight - Sets weight to use when adding overlapping updates 908f10b3e88SPatrick Farrell 909f10b3e88SPatrick Farrell Collective 910f10b3e88SPatrick Farrell 911f10b3e88SPatrick Farrell Input Parameters: 912f10b3e88SPatrick Farrell + snes - the SNES context 913f10b3e88SPatrick Farrell - weight - the weights to use (typically 1/N for each dof, where N is the number of patches it appears in) 914f10b3e88SPatrick Farrell 915f10b3e88SPatrick Farrell Level: intermediate 916f10b3e88SPatrick Farrell 917db781477SPatrick Sanan .seealso: `SNESNASM` 918f10b3e88SPatrick Farrell @*/ 9199371c9d4SSatish Balay PetscErrorCode SNESNASMSetWeight(SNES snes, Vec weight) { 920f10b3e88SPatrick Farrell SNES_NASM *nasm = (SNES_NASM *)snes->data; 921f10b3e88SPatrick Farrell 922f10b3e88SPatrick Farrell PetscFunctionBegin; 923f10b3e88SPatrick Farrell 9249566063dSJacob Faibussowitsch PetscCall(VecDestroy(&nasm->weight)); 925f10b3e88SPatrick Farrell nasm->weight_set = PETSC_TRUE; 926f10b3e88SPatrick Farrell nasm->weight = weight; 9279566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)nasm->weight)); 928f10b3e88SPatrick Farrell 929f10b3e88SPatrick Farrell PetscFunctionReturn(0); 930f10b3e88SPatrick Farrell } 931