xref: /petsc/src/snes/impls/nasm/nasm.c (revision 48a46eb9bd028bec07ec0f396b1a3abb43f14558)
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