xref: /petsc/src/ksp/pc/impls/asm/asm.c (revision 26cc229b24afffee8e9a203ddc8754b40d660fc7)
14b9ad928SBarry Smith /*
24b9ad928SBarry Smith   This file defines an additive Schwarz preconditioner for any Mat implementation.
34b9ad928SBarry Smith 
44b9ad928SBarry Smith   Note that each processor may have any number of subdomains. But in order to
54b9ad928SBarry Smith   deal easily with the VecScatter(), we treat each processor as if it has the
64b9ad928SBarry Smith   same number of subdomains.
74b9ad928SBarry Smith 
84b9ad928SBarry Smith        n - total number of true subdomains on all processors
94b9ad928SBarry Smith        n_local_true - actual number of subdomains on this processor
104b9ad928SBarry Smith        n_local = maximum over all processors of n_local_true
114b9ad928SBarry Smith */
124b9ad928SBarry Smith 
1334eca32bSPierre Jolivet #include <petsc/private/pcasmimpl.h> /*I "petscpc.h" I*/
14*26cc229bSBarry Smith #include "petsc/private/matimpl.h"
154b9ad928SBarry Smith 
166849ba73SBarry Smith static PetscErrorCode PCView_ASM(PC pc,PetscViewer viewer)
174b9ad928SBarry Smith {
1892bb6962SLisandro Dalcin   PC_ASM            *osm = (PC_ASM*)pc->data;
1913f74950SBarry Smith   PetscMPIInt       rank;
204d219a6aSLisandro Dalcin   PetscInt          i,bsz;
21ace3abfcSBarry Smith   PetscBool         iascii,isstring;
224b9ad928SBarry Smith   PetscViewer       sviewer;
23ed155784SPierre Jolivet   PetscViewerFormat format;
24ed155784SPierre Jolivet   const char        *prefix;
254b9ad928SBarry Smith 
264b9ad928SBarry Smith   PetscFunctionBegin;
279566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii));
289566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring));
2932077d6dSBarry Smith   if (iascii) {
303d03bb48SJed Brown     char overlaps[256] = "user-defined overlap",blocks[256] = "total subdomain blocks not yet set";
3163a3b9bcSJacob Faibussowitsch     if (osm->overlap >= 0) PetscCall(PetscSNPrintf(overlaps,sizeof(overlaps),"amount of overlap = %" PetscInt_FMT,osm->overlap));
3263a3b9bcSJacob Faibussowitsch     if (osm->n > 0) PetscCall(PetscSNPrintf(blocks,sizeof(blocks),"total subdomain blocks = %" PetscInt_FMT,osm->n));
339566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  %s, %s\n",blocks,overlaps));
349566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  restriction/interpolation type - %s\n",PCASMTypes[osm->type]));
359566063dSJacob Faibussowitsch     if (osm->dm_subdomains) PetscCall(PetscViewerASCIIPrintf(viewer,"  Additive Schwarz: using DM to define subdomains\n"));
369566063dSJacob Faibussowitsch     if (osm->loctype != PC_COMPOSITE_ADDITIVE) PetscCall(PetscViewerASCIIPrintf(viewer,"  Additive Schwarz: local solve composition type - %s\n",PCCompositeTypes[osm->loctype]));
379566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank));
389566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer,&format));
39ed155784SPierre Jolivet     if (format != PETSC_VIEWER_ASCII_INFO_DETAIL) {
404d219a6aSLisandro Dalcin       if (osm->ksp) {
419566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer,"  Local solver information for first block is in the following KSP and PC objects on rank 0:\n"));
429566063dSJacob Faibussowitsch         PetscCall(PCGetOptionsPrefix(pc,&prefix));
439566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer,"  Use -%sksp_view ::ascii_info_detail to display information for all blocks\n",prefix?prefix:""));
449566063dSJacob Faibussowitsch         PetscCall(PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer));
45dd400576SPatrick Sanan         if (rank == 0) {
469566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPushTab(viewer));
479566063dSJacob Faibussowitsch           PetscCall(KSPView(osm->ksp[0],sviewer));
489566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPopTab(viewer));
494b9ad928SBarry Smith         }
509566063dSJacob Faibussowitsch         PetscCall(PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer));
514d219a6aSLisandro Dalcin       }
524b9ad928SBarry Smith     } else {
539566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushSynchronized(viewer));
5463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer,"  [%d] number of local blocks = %" PetscInt_FMT "\n",(int)rank,osm->n_local_true));
559566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(viewer));
569566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"  Local solver information for each block is in the following KSP and PC objects:\n"));
579566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(viewer));
589566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"- - - - - - - - - - - - - - - - - -\n"));
599566063dSJacob Faibussowitsch       PetscCall(PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer));
60dd2fa690SBarry Smith       for (i=0; i<osm->n_local_true; i++) {
619566063dSJacob Faibussowitsch         PetscCall(ISGetLocalSize(osm->is[i],&bsz));
6263a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(sviewer,"[%d] local block number %" PetscInt_FMT ", size = %" PetscInt_FMT "\n",(int)rank,i,bsz));
639566063dSJacob Faibussowitsch         PetscCall(KSPView(osm->ksp[i],sviewer));
649566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(sviewer,"- - - - - - - - - - - - - - - - - -\n"));
654b9ad928SBarry Smith       }
669566063dSJacob Faibussowitsch       PetscCall(PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer));
679566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(viewer));
689566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(viewer));
699566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopSynchronized(viewer));
704b9ad928SBarry Smith     }
714b9ad928SBarry Smith   } else if (isstring) {
7263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerStringSPrintf(viewer," blocks=%" PetscInt_FMT ", overlap=%" PetscInt_FMT ", type=%s",osm->n,osm->overlap,PCASMTypes[osm->type]));
739566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer));
749566063dSJacob Faibussowitsch     if (osm->ksp) PetscCall(KSPView(osm->ksp[0],sviewer));
759566063dSJacob Faibussowitsch     PetscCall(PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer));
764b9ad928SBarry Smith   }
774b9ad928SBarry Smith   PetscFunctionReturn(0);
784b9ad928SBarry Smith }
794b9ad928SBarry Smith 
8092bb6962SLisandro Dalcin static PetscErrorCode PCASMPrintSubdomains(PC pc)
8192bb6962SLisandro Dalcin {
8292bb6962SLisandro Dalcin   PC_ASM         *osm = (PC_ASM*)pc->data;
8392bb6962SLisandro Dalcin   const char     *prefix;
8492bb6962SLisandro Dalcin   char           fname[PETSC_MAX_PATH_LEN+1];
85643535aeSDmitry Karpeev   PetscViewer    viewer, sviewer;
86643535aeSDmitry Karpeev   char           *s;
8792bb6962SLisandro Dalcin   PetscInt       i,j,nidx;
8892bb6962SLisandro Dalcin   const PetscInt *idx;
89643535aeSDmitry Karpeev   PetscMPIInt    rank, size;
90846783a0SBarry Smith 
9192bb6962SLisandro Dalcin   PetscFunctionBegin;
929566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size));
939566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pc), &rank));
949566063dSJacob Faibussowitsch   PetscCall(PCGetOptionsPrefix(pc,&prefix));
959566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetString(NULL,prefix,"-pc_asm_print_subdomains",fname,sizeof(fname),NULL));
969566063dSJacob Faibussowitsch   if (fname[0] == 0) PetscCall(PetscStrcpy(fname,"stdout"));
979566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIOpen(PetscObjectComm((PetscObject)pc),fname,&viewer));
98643535aeSDmitry Karpeev   for (i=0; i<osm->n_local; i++) {
99643535aeSDmitry Karpeev     if (i < osm->n_local_true) {
1009566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(osm->is[i],&nidx));
1019566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(osm->is[i],&idx));
102643535aeSDmitry Karpeev       /* Print to a string viewer; no more than 15 characters per index plus 512 char for the header.*/
10336a9e3b9SBarry Smith #define len  16*(nidx+1)+512
1049566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(len,&s));
1059566063dSJacob Faibussowitsch       PetscCall(PetscViewerStringOpen(PETSC_COMM_SELF, s, len, &sviewer));
10636a9e3b9SBarry Smith #undef len
10763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerStringSPrintf(sviewer, "[%d:%d] Subdomain %" PetscInt_FMT " with overlap:\n", rank, size, i));
10892bb6962SLisandro Dalcin       for (j=0; j<nidx; j++) {
10963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerStringSPrintf(sviewer,"%" PetscInt_FMT " ",idx[j]));
11092bb6962SLisandro Dalcin       }
1119566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(osm->is[i],&idx));
1129566063dSJacob Faibussowitsch       PetscCall(PetscViewerStringSPrintf(sviewer,"\n"));
1139566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&sviewer));
1149566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushSynchronized(viewer));
11563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%s", s));
1169566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(viewer));
1179566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopSynchronized(viewer));
1189566063dSJacob Faibussowitsch       PetscCall(PetscFree(s));
1192b691e39SMatthew Knepley       if (osm->is_local) {
120643535aeSDmitry Karpeev         /* Print to a string viewer; no more than 15 characters per index plus 512 char for the header.*/
12136a9e3b9SBarry Smith #define len  16*(nidx+1)+512
1229566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(len, &s));
1239566063dSJacob Faibussowitsch         PetscCall(PetscViewerStringOpen(PETSC_COMM_SELF, s, len, &sviewer));
12436a9e3b9SBarry Smith #undef len
12563a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerStringSPrintf(sviewer, "[%d:%d] Subdomain %" PetscInt_FMT " without overlap:\n", rank, size, i));
1269566063dSJacob Faibussowitsch         PetscCall(ISGetLocalSize(osm->is_local[i],&nidx));
1279566063dSJacob Faibussowitsch         PetscCall(ISGetIndices(osm->is_local[i],&idx));
1282b691e39SMatthew Knepley         for (j=0; j<nidx; j++) {
12963a3b9bcSJacob Faibussowitsch           PetscCall(PetscViewerStringSPrintf(sviewer,"%" PetscInt_FMT " ",idx[j]));
1302b691e39SMatthew Knepley         }
1319566063dSJacob Faibussowitsch         PetscCall(ISRestoreIndices(osm->is_local[i],&idx));
1329566063dSJacob Faibussowitsch         PetscCall(PetscViewerStringSPrintf(sviewer,"\n"));
1339566063dSJacob Faibussowitsch         PetscCall(PetscViewerDestroy(&sviewer));
1349566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushSynchronized(viewer));
13563a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%s", s));
1369566063dSJacob Faibussowitsch         PetscCall(PetscViewerFlush(viewer));
1379566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopSynchronized(viewer));
1389566063dSJacob Faibussowitsch         PetscCall(PetscFree(s));
139643535aeSDmitry Karpeev       }
1402fa5cd67SKarl Rupp     } else {
141643535aeSDmitry Karpeev       /* Participate in collective viewer calls. */
1429566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushSynchronized(viewer));
1439566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(viewer));
1449566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopSynchronized(viewer));
145643535aeSDmitry Karpeev       /* Assume either all ranks have is_local or none do. */
146643535aeSDmitry Karpeev       if (osm->is_local) {
1479566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushSynchronized(viewer));
1489566063dSJacob Faibussowitsch         PetscCall(PetscViewerFlush(viewer));
1499566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopSynchronized(viewer));
150643535aeSDmitry Karpeev       }
151fdc48646SDmitry Karpeev     }
15292bb6962SLisandro Dalcin   }
1539566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(viewer));
1549566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(&viewer));
15592bb6962SLisandro Dalcin   PetscFunctionReturn(0);
15692bb6962SLisandro Dalcin }
15792bb6962SLisandro Dalcin 
1586849ba73SBarry Smith static PetscErrorCode PCSetUp_ASM(PC pc)
1594b9ad928SBarry Smith {
1604b9ad928SBarry Smith   PC_ASM         *osm = (PC_ASM*)pc->data;
16157501b6eSBarry Smith   PetscBool      flg;
16287e86712SBarry Smith   PetscInt       i,m,m_local;
1634b9ad928SBarry Smith   MatReuse       scall = MAT_REUSE_MATRIX;
1644b9ad928SBarry Smith   IS             isl;
1654b9ad928SBarry Smith   KSP            ksp;
1664b9ad928SBarry Smith   PC             subpc;
1672dcb1b2aSMatthew Knepley   const char     *prefix,*pprefix;
16823ce1328SBarry Smith   Vec            vec;
1690298fd71SBarry Smith   DM             *domain_dm = NULL;
1704b9ad928SBarry Smith 
1714b9ad928SBarry Smith   PetscFunctionBegin;
1724b9ad928SBarry Smith   if (!pc->setupcalled) {
173265a2120SBarry Smith     PetscInt m;
17492bb6962SLisandro Dalcin 
1752b837212SDmitry Karpeev     /* Note: if subdomains have been set either via PCASMSetTotalSubdomains() or via PCASMSetLocalSubdomains(), osm->n_local_true will not be PETSC_DECIDE */
1762b837212SDmitry Karpeev     if (osm->n_local_true == PETSC_DECIDE) {
17769ca1f37SDmitry Karpeev       /* no subdomains given */
17865db9045SDmitry Karpeev       /* try pc->dm first, if allowed */
179d709ea83SDmitry Karpeev       if (osm->dm_subdomains && pc->dm) {
180feb221f8SDmitry Karpeev         PetscInt  num_domains, d;
181feb221f8SDmitry Karpeev         char      **domain_names;
1828d4ac253SDmitry Karpeev         IS        *inner_domain_is, *outer_domain_is;
1839566063dSJacob Faibussowitsch         PetscCall(DMCreateDomainDecomposition(pc->dm, &num_domains, &domain_names, &inner_domain_is, &outer_domain_is, &domain_dm));
184704f0395SPatrick Sanan         osm->overlap = -1; /* We do not want to increase the overlap of the IS.
185704f0395SPatrick Sanan                               A future improvement of this code might allow one to use
186704f0395SPatrick Sanan                               DM-defined subdomains and also increase the overlap,
187704f0395SPatrick Sanan                               but that is not currently supported */
18869ca1f37SDmitry Karpeev         if (num_domains) {
1899566063dSJacob Faibussowitsch           PetscCall(PCASMSetLocalSubdomains(pc, num_domains, outer_domain_is, inner_domain_is));
19069ca1f37SDmitry Karpeev         }
191feb221f8SDmitry Karpeev         for (d = 0; d < num_domains; ++d) {
1929566063dSJacob Faibussowitsch           if (domain_names)    PetscCall(PetscFree(domain_names[d]));
1939566063dSJacob Faibussowitsch           if (inner_domain_is) PetscCall(ISDestroy(&inner_domain_is[d]));
1949566063dSJacob Faibussowitsch           if (outer_domain_is) PetscCall(ISDestroy(&outer_domain_is[d]));
195feb221f8SDmitry Karpeev         }
1969566063dSJacob Faibussowitsch         PetscCall(PetscFree(domain_names));
1979566063dSJacob Faibussowitsch         PetscCall(PetscFree(inner_domain_is));
1989566063dSJacob Faibussowitsch         PetscCall(PetscFree(outer_domain_is));
199feb221f8SDmitry Karpeev       }
2002b837212SDmitry Karpeev       if (osm->n_local_true == PETSC_DECIDE) {
20169ca1f37SDmitry Karpeev         /* still no subdomains; use one subdomain per processor */
2022b837212SDmitry Karpeev         osm->n_local_true = 1;
203feb221f8SDmitry Karpeev       }
2042b837212SDmitry Karpeev     }
2052b837212SDmitry Karpeev     { /* determine the global and max number of subdomains */
2066ac3741eSJed Brown       struct {PetscInt max,sum;} inwork,outwork;
207c10200c1SHong Zhang       PetscMPIInt size;
208c10200c1SHong Zhang 
2096ac3741eSJed Brown       inwork.max   = osm->n_local_true;
2106ac3741eSJed Brown       inwork.sum   = osm->n_local_true;
2111c2dc1cbSBarry Smith       PetscCall(MPIU_Allreduce(&inwork,&outwork,1,MPIU_2INT,MPIU_MAXSUM_OP,PetscObjectComm((PetscObject)pc)));
2126ac3741eSJed Brown       osm->n_local = outwork.max;
2136ac3741eSJed Brown       osm->n       = outwork.sum;
214c10200c1SHong Zhang 
2159566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size));
216c10200c1SHong Zhang       if (outwork.max == 1 && outwork.sum == size) {
2177dae84e0SHong Zhang         /* osm->n_local_true = 1 on all processes, set this option may enable use of optimized MatCreateSubMatrices() implementation */
2189566063dSJacob Faibussowitsch         PetscCall(MatSetOption(pc->pmat,MAT_SUBMAT_SINGLEIS,PETSC_TRUE));
219c10200c1SHong Zhang       }
2204b9ad928SBarry Smith     }
22178904715SLisandro Dalcin     if (!osm->is) { /* create the index sets */
2229566063dSJacob Faibussowitsch       PetscCall(PCASMCreateSubdomains(pc->pmat,osm->n_local_true,&osm->is));
2234b9ad928SBarry Smith     }
224f5234e35SJed Brown     if (osm->n_local_true > 1 && !osm->is_local) {
2259566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(osm->n_local_true,&osm->is_local));
226f5234e35SJed Brown       for (i=0; i<osm->n_local_true; i++) {
227f5234e35SJed Brown         if (osm->overlap > 0) { /* With positive overlap, osm->is[i] will be modified */
2289566063dSJacob Faibussowitsch           PetscCall(ISDuplicate(osm->is[i],&osm->is_local[i]));
2299566063dSJacob Faibussowitsch           PetscCall(ISCopy(osm->is[i],osm->is_local[i]));
230f5234e35SJed Brown         } else {
2319566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)osm->is[i]));
232f5234e35SJed Brown           osm->is_local[i] = osm->is[i];
233f5234e35SJed Brown         }
234f5234e35SJed Brown       }
235f5234e35SJed Brown     }
2369566063dSJacob Faibussowitsch     PetscCall(PCGetOptionsPrefix(pc,&prefix));
2373d03bb48SJed Brown     if (osm->overlap > 0) {
2384b9ad928SBarry Smith       /* Extend the "overlapping" regions by a number of steps */
2399566063dSJacob Faibussowitsch       PetscCall(MatIncreaseOverlap(pc->pmat,osm->n_local_true,osm->is,osm->overlap));
2403d03bb48SJed Brown     }
2416ed231c7SMatthew Knepley     if (osm->sort_indices) {
24292bb6962SLisandro Dalcin       for (i=0; i<osm->n_local_true; i++) {
2439566063dSJacob Faibussowitsch         PetscCall(ISSort(osm->is[i]));
2442b691e39SMatthew Knepley         if (osm->is_local) {
2459566063dSJacob Faibussowitsch           PetscCall(ISSort(osm->is_local[i]));
2462b691e39SMatthew Knepley         }
2474b9ad928SBarry Smith       }
2486ed231c7SMatthew Knepley     }
24998d3e228SPierre Jolivet     flg = PETSC_FALSE;
25098d3e228SPierre Jolivet     PetscCall(PetscOptionsHasName(NULL,prefix,"-pc_asm_print_subdomains",&flg));
25198d3e228SPierre Jolivet     if (flg) PetscCall(PCASMPrintSubdomains(pc));
252f6991133SBarry Smith     if (!osm->ksp) {
25378904715SLisandro Dalcin       /* Create the local solvers */
2549566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(osm->n_local_true,&osm->ksp));
255feb221f8SDmitry Karpeev       if (domain_dm) {
2569566063dSJacob Faibussowitsch         PetscCall(PetscInfo(pc,"Setting up ASM subproblems using the embedded DM\n"));
257feb221f8SDmitry Karpeev       }
25892bb6962SLisandro Dalcin       for (i=0; i<osm->n_local_true; i++) {
2599566063dSJacob Faibussowitsch         PetscCall(KSPCreate(PETSC_COMM_SELF,&ksp));
2609566063dSJacob Faibussowitsch         PetscCall(KSPSetErrorIfNotConverged(ksp,pc->erroriffailure));
2619566063dSJacob Faibussowitsch         PetscCall(PetscLogObjectParent((PetscObject)pc,(PetscObject)ksp));
2629566063dSJacob Faibussowitsch         PetscCall(PetscObjectIncrementTabLevel((PetscObject)ksp,(PetscObject)pc,1));
2639566063dSJacob Faibussowitsch         PetscCall(KSPSetType(ksp,KSPPREONLY));
2649566063dSJacob Faibussowitsch         PetscCall(KSPGetPC(ksp,&subpc));
2659566063dSJacob Faibussowitsch         PetscCall(PCGetOptionsPrefix(pc,&prefix));
2669566063dSJacob Faibussowitsch         PetscCall(KSPSetOptionsPrefix(ksp,prefix));
2679566063dSJacob Faibussowitsch         PetscCall(KSPAppendOptionsPrefix(ksp,"sub_"));
268feb221f8SDmitry Karpeev         if (domain_dm) {
2699566063dSJacob Faibussowitsch           PetscCall(KSPSetDM(ksp, domain_dm[i]));
2709566063dSJacob Faibussowitsch           PetscCall(KSPSetDMActive(ksp, PETSC_FALSE));
2719566063dSJacob Faibussowitsch           PetscCall(DMDestroy(&domain_dm[i]));
272feb221f8SDmitry Karpeev         }
2734b9ad928SBarry Smith         osm->ksp[i] = ksp;
2744b9ad928SBarry Smith       }
275feb221f8SDmitry Karpeev       if (domain_dm) {
2769566063dSJacob Faibussowitsch         PetscCall(PetscFree(domain_dm));
277feb221f8SDmitry Karpeev       }
278f6991133SBarry Smith     }
2791dd8081eSeaulisa 
2809566063dSJacob Faibussowitsch     PetscCall(ISConcatenate(PETSC_COMM_SELF, osm->n_local_true, osm->is, &osm->lis));
2819566063dSJacob Faibussowitsch     PetscCall(ISSortRemoveDups(osm->lis));
2829566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(osm->lis, &m));
2831dd8081eSeaulisa 
2844b9ad928SBarry Smith     scall = MAT_INITIAL_MATRIX;
2854b9ad928SBarry Smith   } else {
2864b9ad928SBarry Smith     /*
2874b9ad928SBarry Smith        Destroy the blocks from the previous iteration
2884b9ad928SBarry Smith     */
289e09e08ccSBarry Smith     if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
2909566063dSJacob Faibussowitsch       PetscCall(MatDestroyMatrices(osm->n_local_true,&osm->pmat));
2914b9ad928SBarry Smith       scall = MAT_INITIAL_MATRIX;
2924b9ad928SBarry Smith     }
2934b9ad928SBarry Smith   }
2944b9ad928SBarry Smith 
295b58cb649SBarry Smith   /* Destroy previous submatrices of a different type than pc->pmat since MAT_REUSE_MATRIX won't work in that case */
29682b5ce2aSStefano Zampini   if (scall == MAT_REUSE_MATRIX && osm->sub_mat_type) {
297b58cb649SBarry Smith     if (osm->n_local_true > 0) {
2989566063dSJacob Faibussowitsch       PetscCall(MatDestroySubMatrices(osm->n_local_true,&osm->pmat));
299b58cb649SBarry Smith     }
300b58cb649SBarry Smith     scall = MAT_INITIAL_MATRIX;
301b58cb649SBarry Smith   }
302b58cb649SBarry Smith 
30392bb6962SLisandro Dalcin   /*
30492bb6962SLisandro Dalcin      Extract out the submatrices
30592bb6962SLisandro Dalcin   */
3069566063dSJacob Faibussowitsch   PetscCall(MatCreateSubMatrices(pc->pmat,osm->n_local_true,osm->is,osm->is,scall,&osm->pmat));
30792bb6962SLisandro Dalcin   if (scall == MAT_INITIAL_MATRIX) {
3089566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)pc->pmat,&pprefix));
30992bb6962SLisandro Dalcin     for (i=0; i<osm->n_local_true; i++) {
3109566063dSJacob Faibussowitsch       PetscCall(PetscLogObjectParent((PetscObject)pc,(PetscObject)osm->pmat[i]));
3119566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetOptionsPrefix((PetscObject)osm->pmat[i],pprefix));
31292bb6962SLisandro Dalcin     }
31392bb6962SLisandro Dalcin   }
31480ec0b7dSPatrick Sanan 
31580ec0b7dSPatrick Sanan   /* Convert the types of the submatrices (if needbe) */
31680ec0b7dSPatrick Sanan   if (osm->sub_mat_type) {
31780ec0b7dSPatrick Sanan     for (i=0; i<osm->n_local_true; i++) {
3189566063dSJacob Faibussowitsch       PetscCall(MatConvert(osm->pmat[i],osm->sub_mat_type,MAT_INPLACE_MATRIX,&(osm->pmat[i])));
31980ec0b7dSPatrick Sanan     }
32080ec0b7dSPatrick Sanan   }
32180ec0b7dSPatrick Sanan 
32280ec0b7dSPatrick Sanan   if (!pc->setupcalled) {
32356ea09ceSStefano Zampini     VecType vtype;
32456ea09ceSStefano Zampini 
32580ec0b7dSPatrick Sanan     /* Create the local work vectors (from the local matrices) and scatter contexts */
3269566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(pc->pmat,&vec,NULL));
3275b3c0d42Seaulisa 
3287827d75bSBarry Smith     PetscCheck(!osm->is_local || (osm->type != PC_ASM_INTERPOLATE && osm->type != PC_ASM_NONE),PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot use interpolate or none PCASMType if is_local was provided to PCASMSetLocalSubdomains()");
3291dd8081eSeaulisa     if (osm->is_local && osm->type == PC_ASM_RESTRICT && osm->loctype == PC_COMPOSITE_ADDITIVE) {
3309566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(osm->n_local_true,&osm->lprolongation));
3311dd8081eSeaulisa     }
3329566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(osm->n_local_true,&osm->lrestriction));
3339566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(osm->n_local_true,&osm->x));
3349566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(osm->n_local_true,&osm->y));
335347574c9Seaulisa 
3369566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(osm->lis,&m));
3379566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF,m,0,1,&isl));
3389566063dSJacob Faibussowitsch     PetscCall(MatGetVecType(osm->pmat[0],&vtype));
3399566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF,&osm->lx));
3409566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(osm->lx,m,m));
3419566063dSJacob Faibussowitsch     PetscCall(VecSetType(osm->lx,vtype));
3429566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(osm->lx, &osm->ly));
3439566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(vec,osm->lis,osm->lx,isl,&osm->restriction));
3449566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&isl));
345347574c9Seaulisa 
34680ec0b7dSPatrick Sanan     for (i=0; i<osm->n_local_true; ++i) {
3475b3c0d42Seaulisa       ISLocalToGlobalMapping ltog;
3485b3c0d42Seaulisa       IS                     isll;
3495b3c0d42Seaulisa       const PetscInt         *idx_is;
3505b3c0d42Seaulisa       PetscInt               *idx_lis,nout;
3515b3c0d42Seaulisa 
3529566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(osm->is[i],&m));
3539566063dSJacob Faibussowitsch       PetscCall(MatCreateVecs(osm->pmat[i],&osm->x[i],NULL));
3549566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(osm->x[i],&osm->y[i]));
35555817e79SBarry Smith 
356b0de9f23SBarry Smith       /* generate a scatter from ly to y[i] picking all the overlapping is[i] entries */
3579566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingCreateIS(osm->lis,&ltog));
3589566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(osm->is[i],&m));
3599566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(osm->is[i], &idx_is));
3609566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(m,&idx_lis));
3619566063dSJacob Faibussowitsch       PetscCall(ISGlobalToLocalMappingApply(ltog,IS_GTOLM_DROP,m,idx_is,&nout,idx_lis));
3627827d75bSBarry Smith       PetscCheck(nout == m,PETSC_COMM_SELF,PETSC_ERR_PLIB,"is not a subset of lis");
3639566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(osm->is[i], &idx_is));
3649566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PETSC_COMM_SELF,m,idx_lis,PETSC_OWN_POINTER,&isll));
3659566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingDestroy(&ltog));
3669566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_SELF,m,0,1,&isl));
3679566063dSJacob Faibussowitsch       PetscCall(VecScatterCreate(osm->ly,isll,osm->y[i],isl,&osm->lrestriction[i]));
3689566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&isll));
3699566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&isl));
370910cf402Sprj-       if (osm->lprolongation) { /* generate a scatter from y[i] to ly picking only the the non-overlapping is_local[i] entries */
371d8b3b5e3Seaulisa         ISLocalToGlobalMapping ltog;
372d8b3b5e3Seaulisa         IS                     isll,isll_local;
373d8b3b5e3Seaulisa         const PetscInt         *idx_local;
374d8b3b5e3Seaulisa         PetscInt               *idx1, *idx2, nout;
375d8b3b5e3Seaulisa 
3769566063dSJacob Faibussowitsch         PetscCall(ISGetLocalSize(osm->is_local[i],&m_local));
3779566063dSJacob Faibussowitsch         PetscCall(ISGetIndices(osm->is_local[i], &idx_local));
378d8b3b5e3Seaulisa 
3799566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingCreateIS(osm->is[i],&ltog));
3809566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(m_local,&idx1));
3819566063dSJacob Faibussowitsch         PetscCall(ISGlobalToLocalMappingApply(ltog,IS_GTOLM_DROP,m_local,idx_local,&nout,idx1));
3829566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingDestroy(&ltog));
3837827d75bSBarry Smith         PetscCheck(nout == m_local,PETSC_COMM_SELF,PETSC_ERR_PLIB,"is_local not a subset of is");
3849566063dSJacob Faibussowitsch         PetscCall(ISCreateGeneral(PETSC_COMM_SELF,m_local,idx1,PETSC_OWN_POINTER,&isll));
385d8b3b5e3Seaulisa 
3869566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingCreateIS(osm->lis,&ltog));
3879566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(m_local,&idx2));
3889566063dSJacob Faibussowitsch         PetscCall(ISGlobalToLocalMappingApply(ltog,IS_GTOLM_DROP,m_local,idx_local,&nout,idx2));
3899566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingDestroy(&ltog));
3907827d75bSBarry Smith         PetscCheck(nout == m_local,PETSC_COMM_SELF,PETSC_ERR_PLIB,"is_local not a subset of lis");
3919566063dSJacob Faibussowitsch         PetscCall(ISCreateGeneral(PETSC_COMM_SELF,m_local,idx2,PETSC_OWN_POINTER,&isll_local));
392d8b3b5e3Seaulisa 
3939566063dSJacob Faibussowitsch         PetscCall(ISRestoreIndices(osm->is_local[i], &idx_local));
3949566063dSJacob Faibussowitsch         PetscCall(VecScatterCreate(osm->y[i],isll,osm->ly,isll_local,&osm->lprolongation[i]));
395d8b3b5e3Seaulisa 
3969566063dSJacob Faibussowitsch         PetscCall(ISDestroy(&isll));
3979566063dSJacob Faibussowitsch         PetscCall(ISDestroy(&isll_local));
398d8b3b5e3Seaulisa       }
39980ec0b7dSPatrick Sanan     }
4009566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&vec));
40180ec0b7dSPatrick Sanan   }
40280ec0b7dSPatrick Sanan 
403fb745f2cSMatthew G. Knepley   if (osm->loctype == PC_COMPOSITE_MULTIPLICATIVE) {
404235cc4ceSMatthew G. Knepley     IS      *cis;
405235cc4ceSMatthew G. Knepley     PetscInt c;
406235cc4ceSMatthew G. Knepley 
4079566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(osm->n_local_true, &cis));
408235cc4ceSMatthew G. Knepley     for (c = 0; c < osm->n_local_true; ++c) cis[c] = osm->lis;
4099566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrices(pc->pmat, osm->n_local_true, osm->is, cis, scall, &osm->lmats));
4109566063dSJacob Faibussowitsch     PetscCall(PetscFree(cis));
411fb745f2cSMatthew G. Knepley   }
4124b9ad928SBarry Smith 
4134b9ad928SBarry Smith   /* Return control to the user so that the submatrices can be modified (e.g., to apply
4144b9ad928SBarry Smith      different boundary conditions for the submatrices than for the global problem) */
4159566063dSJacob Faibussowitsch   PetscCall(PCModifySubMatrices(pc,osm->n_local_true,osm->is,osm->is,osm->pmat,pc->modifysubmatricesP));
4164b9ad928SBarry Smith 
41792bb6962SLisandro Dalcin   /*
41892bb6962SLisandro Dalcin      Loop over subdomains putting them into local ksp
41992bb6962SLisandro Dalcin   */
4209566063dSJacob Faibussowitsch   PetscCall(KSPGetOptionsPrefix(osm->ksp[0],&prefix));
42192bb6962SLisandro Dalcin   for (i=0; i<osm->n_local_true; i++) {
4229566063dSJacob Faibussowitsch     PetscCall(KSPSetOperators(osm->ksp[i],osm->pmat[i],osm->pmat[i]));
4239566063dSJacob Faibussowitsch     PetscCall(MatSetOptionsPrefix(osm->pmat[i],prefix));
42492bb6962SLisandro Dalcin     if (!pc->setupcalled) {
4259566063dSJacob Faibussowitsch       PetscCall(KSPSetFromOptions(osm->ksp[i]));
4264b9ad928SBarry Smith     }
42792bb6962SLisandro Dalcin   }
4284b9ad928SBarry Smith   PetscFunctionReturn(0);
4294b9ad928SBarry Smith }
4304b9ad928SBarry Smith 
4316849ba73SBarry Smith static PetscErrorCode PCSetUpOnBlocks_ASM(PC pc)
4324b9ad928SBarry Smith {
4334b9ad928SBarry Smith   PC_ASM             *osm = (PC_ASM*)pc->data;
43413f74950SBarry Smith   PetscInt           i;
435539c167fSBarry Smith   KSPConvergedReason reason;
4364b9ad928SBarry Smith 
4374b9ad928SBarry Smith   PetscFunctionBegin;
4384b9ad928SBarry Smith   for (i=0; i<osm->n_local_true; i++) {
4399566063dSJacob Faibussowitsch     PetscCall(KSPSetUp(osm->ksp[i]));
4409566063dSJacob Faibussowitsch     PetscCall(KSPGetConvergedReason(osm->ksp[i],&reason));
441c0decd05SBarry Smith     if (reason == KSP_DIVERGED_PC_FAILED) {
442261222b2SHong Zhang       pc->failedreason = PC_SUBPC_ERROR;
443e0eafd54SHong Zhang     }
4444b9ad928SBarry Smith   }
4454b9ad928SBarry Smith   PetscFunctionReturn(0);
4464b9ad928SBarry Smith }
4474b9ad928SBarry Smith 
4486849ba73SBarry Smith static PetscErrorCode PCApply_ASM(PC pc,Vec x,Vec y)
4494b9ad928SBarry Smith {
4504b9ad928SBarry Smith   PC_ASM         *osm = (PC_ASM*)pc->data;
4511dd8081eSeaulisa   PetscInt       i,n_local_true = osm->n_local_true;
4524b9ad928SBarry Smith   ScatterMode    forward = SCATTER_FORWARD,reverse = SCATTER_REVERSE;
4534b9ad928SBarry Smith 
4544b9ad928SBarry Smith   PetscFunctionBegin;
4554b9ad928SBarry Smith   /*
45648e38a8aSPierre Jolivet      support for limiting the restriction or interpolation to only local
4574b9ad928SBarry Smith      subdomain values (leaving the other values 0).
4584b9ad928SBarry Smith   */
4594b9ad928SBarry Smith   if (!(osm->type & PC_ASM_RESTRICT)) {
4604b9ad928SBarry Smith     forward = SCATTER_FORWARD_LOCAL;
4614b9ad928SBarry Smith     /* have to zero the work RHS since scatter may leave some slots empty */
4629566063dSJacob Faibussowitsch     PetscCall(VecSet(osm->lx, 0.0));
4634b9ad928SBarry Smith   }
464347574c9Seaulisa   if (!(osm->type & PC_ASM_INTERPOLATE)) {
465347574c9Seaulisa     reverse = SCATTER_REVERSE_LOCAL;
466347574c9Seaulisa   }
4674b9ad928SBarry Smith 
468347574c9Seaulisa   if (osm->loctype == PC_COMPOSITE_MULTIPLICATIVE || osm->loctype == PC_COMPOSITE_ADDITIVE) {
469b0de9f23SBarry Smith     /* zero the global and the local solutions */
4709566063dSJacob Faibussowitsch     PetscCall(VecSet(y, 0.0));
4719566063dSJacob Faibussowitsch     PetscCall(VecSet(osm->ly, 0.0));
472347574c9Seaulisa 
47348e38a8aSPierre Jolivet     /* copy the global RHS to local RHS including the ghost nodes */
4749566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(osm->restriction, x, osm->lx, INSERT_VALUES, forward));
4759566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(osm->restriction, x, osm->lx, INSERT_VALUES, forward));
476347574c9Seaulisa 
47748e38a8aSPierre Jolivet     /* restrict local RHS to the overlapping 0-block RHS */
4789566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(osm->lrestriction[0], osm->lx, osm->x[0], INSERT_VALUES, forward));
4799566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(osm->lrestriction[0], osm->lx, osm->x[0], INSERT_VALUES, forward));
480d8b3b5e3Seaulisa 
48112cd4985SMatthew G. Knepley     /* do the local solves */
48212cd4985SMatthew G. Knepley     for (i = 0; i < n_local_true; ++i) {
483347574c9Seaulisa 
484b0de9f23SBarry Smith       /* solve the overlapping i-block */
4859566063dSJacob Faibussowitsch       PetscCall(PetscLogEventBegin(PC_ApplyOnBlocks, osm->ksp[i], osm->x[i], osm->y[i],0));
4869566063dSJacob Faibussowitsch       PetscCall(KSPSolve(osm->ksp[i], osm->x[i], osm->y[i]));
4879566063dSJacob Faibussowitsch       PetscCall(KSPCheckSolve(osm->ksp[i], pc, osm->y[i]));
4889566063dSJacob Faibussowitsch       PetscCall(PetscLogEventEnd(PC_ApplyOnBlocks, osm->ksp[i], osm->x[i], osm->y[i], 0));
489d8b3b5e3Seaulisa 
490910cf402Sprj-       if (osm->lprolongation) { /* interpolate the non-overlapping i-block solution to the local solution (only for restrictive additive) */
4919566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(osm->lprolongation[i], osm->y[i], osm->ly, ADD_VALUES, forward));
4929566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(osm->lprolongation[i], osm->y[i], osm->ly, ADD_VALUES, forward));
49348e38a8aSPierre Jolivet       } else { /* interpolate the overlapping i-block solution to the local solution */
4949566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(osm->lrestriction[i], osm->y[i], osm->ly, ADD_VALUES, reverse));
4959566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(osm->lrestriction[i], osm->y[i], osm->ly, ADD_VALUES, reverse));
496d8b3b5e3Seaulisa       }
497347574c9Seaulisa 
498347574c9Seaulisa       if (i < n_local_true-1) {
49948e38a8aSPierre Jolivet         /* restrict local RHS to the overlapping (i+1)-block RHS */
5009566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(osm->lrestriction[i+1], osm->lx, osm->x[i+1], INSERT_VALUES, forward));
5019566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(osm->lrestriction[i+1], osm->lx, osm->x[i+1], INSERT_VALUES, forward));
502347574c9Seaulisa 
503347574c9Seaulisa         if (osm->loctype == PC_COMPOSITE_MULTIPLICATIVE) {
5048966356dSPierre Jolivet           /* update the overlapping (i+1)-block RHS using the current local solution */
5059566063dSJacob Faibussowitsch           PetscCall(MatMult(osm->lmats[i+1], osm->ly, osm->y[i+1]));
5069566063dSJacob Faibussowitsch           PetscCall(VecAXPBY(osm->x[i+1],-1.,1., osm->y[i+1]));
5077c3d802fSMatthew G. Knepley         }
50812cd4985SMatthew G. Knepley       }
50912cd4985SMatthew G. Knepley     }
51048e38a8aSPierre Jolivet     /* add the local solution to the global solution including the ghost nodes */
5119566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(osm->restriction, osm->ly, y, ADD_VALUES, reverse));
5129566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(osm->restriction, osm->ly, y, ADD_VALUES, reverse));
51398921bdaSJacob Faibussowitsch   } else SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Invalid local composition type: %s", PCCompositeTypes[osm->loctype]);
5144b9ad928SBarry Smith   PetscFunctionReturn(0);
5154b9ad928SBarry Smith }
5164b9ad928SBarry Smith 
51748e38a8aSPierre Jolivet static PetscErrorCode PCMatApply_ASM(PC pc,Mat X,Mat Y)
51848e38a8aSPierre Jolivet {
51948e38a8aSPierre Jolivet   PC_ASM         *osm = (PC_ASM*)pc->data;
52048e38a8aSPierre Jolivet   Mat            Z,W;
52148e38a8aSPierre Jolivet   Vec            x;
52248e38a8aSPierre Jolivet   PetscInt       i,m,N;
52348e38a8aSPierre Jolivet   ScatterMode    forward = SCATTER_FORWARD,reverse = SCATTER_REVERSE;
52448e38a8aSPierre Jolivet 
52548e38a8aSPierre Jolivet   PetscFunctionBegin;
5267827d75bSBarry Smith   PetscCheck(osm->n_local_true <= 1,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Not yet implemented");
52748e38a8aSPierre Jolivet   /*
52848e38a8aSPierre Jolivet      support for limiting the restriction or interpolation to only local
52948e38a8aSPierre Jolivet      subdomain values (leaving the other values 0).
53048e38a8aSPierre Jolivet   */
53148e38a8aSPierre Jolivet   if (!(osm->type & PC_ASM_RESTRICT)) {
53248e38a8aSPierre Jolivet     forward = SCATTER_FORWARD_LOCAL;
53348e38a8aSPierre Jolivet     /* have to zero the work RHS since scatter may leave some slots empty */
5349566063dSJacob Faibussowitsch     PetscCall(VecSet(osm->lx, 0.0));
53548e38a8aSPierre Jolivet   }
53648e38a8aSPierre Jolivet   if (!(osm->type & PC_ASM_INTERPOLATE)) {
53748e38a8aSPierre Jolivet     reverse = SCATTER_REVERSE_LOCAL;
53848e38a8aSPierre Jolivet   }
5399566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(osm->x[0], &m));
5409566063dSJacob Faibussowitsch   PetscCall(MatGetSize(X, NULL, &N));
5419566063dSJacob Faibussowitsch   PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, m, N, NULL, &Z));
54248e38a8aSPierre Jolivet   if (osm->loctype == PC_COMPOSITE_MULTIPLICATIVE || osm->loctype == PC_COMPOSITE_ADDITIVE) {
54348e38a8aSPierre Jolivet     /* zero the global and the local solutions */
5449566063dSJacob Faibussowitsch     PetscCall(MatZeroEntries(Y));
5459566063dSJacob Faibussowitsch     PetscCall(VecSet(osm->ly, 0.0));
54648e38a8aSPierre Jolivet 
54748e38a8aSPierre Jolivet     for (i = 0; i < N; ++i) {
5489566063dSJacob Faibussowitsch       PetscCall(MatDenseGetColumnVecRead(X, i, &x));
54948e38a8aSPierre Jolivet       /* copy the global RHS to local RHS including the ghost nodes */
5509566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(osm->restriction, x, osm->lx, INSERT_VALUES, forward));
5519566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(osm->restriction, x, osm->lx, INSERT_VALUES, forward));
5529566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreColumnVecRead(X, i, &x));
55348e38a8aSPierre Jolivet 
5549566063dSJacob Faibussowitsch       PetscCall(MatDenseGetColumnVecWrite(Z, i, &x));
55548e38a8aSPierre Jolivet       /* restrict local RHS to the overlapping 0-block RHS */
5569566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(osm->lrestriction[0], osm->lx, x, INSERT_VALUES, forward));
5579566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(osm->lrestriction[0], osm->lx, x, INSERT_VALUES, forward));
5589566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreColumnVecWrite(Z, i, &x));
55948e38a8aSPierre Jolivet     }
5609566063dSJacob Faibussowitsch     PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, m, N, NULL, &W));
56148e38a8aSPierre Jolivet     /* solve the overlapping 0-block */
5629566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(PC_ApplyOnBlocks, osm->ksp[0], Z, W, 0));
5639566063dSJacob Faibussowitsch     PetscCall(KSPMatSolve(osm->ksp[0], Z, W));
5649566063dSJacob Faibussowitsch     PetscCall(KSPCheckSolve(osm->ksp[0], pc, NULL));
5659566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(PC_ApplyOnBlocks, osm->ksp[0], Z, W,0));
5669566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&Z));
56748e38a8aSPierre Jolivet 
56848e38a8aSPierre Jolivet     for (i = 0; i < N; ++i) {
5699566063dSJacob Faibussowitsch       PetscCall(VecSet(osm->ly, 0.0));
5709566063dSJacob Faibussowitsch       PetscCall(MatDenseGetColumnVecRead(W, i, &x));
57148e38a8aSPierre Jolivet       if (osm->lprolongation) { /* interpolate the non-overlapping 0-block solution to the local solution (only for restrictive additive) */
5729566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(osm->lprolongation[0], x, osm->ly, ADD_VALUES, forward));
5739566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(osm->lprolongation[0], x, osm->ly, ADD_VALUES, forward));
57448e38a8aSPierre Jolivet       } else { /* interpolate the overlapping 0-block solution to the local solution */
5759566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(osm->lrestriction[0], x, osm->ly, ADD_VALUES, reverse));
5769566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(osm->lrestriction[0], x, osm->ly, ADD_VALUES, reverse));
57748e38a8aSPierre Jolivet       }
5789566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreColumnVecRead(W, i, &x));
57948e38a8aSPierre Jolivet 
5809566063dSJacob Faibussowitsch       PetscCall(MatDenseGetColumnVecWrite(Y, i, &x));
58148e38a8aSPierre Jolivet       /* add the local solution to the global solution including the ghost nodes */
5829566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(osm->restriction, osm->ly, x, ADD_VALUES, reverse));
5839566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(osm->restriction, osm->ly, x, ADD_VALUES, reverse));
5849566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreColumnVecWrite(Y, i, &x));
58548e38a8aSPierre Jolivet     }
5869566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&W));
58798921bdaSJacob Faibussowitsch   } else SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Invalid local composition type: %s", PCCompositeTypes[osm->loctype]);
58848e38a8aSPierre Jolivet   PetscFunctionReturn(0);
58948e38a8aSPierre Jolivet }
59048e38a8aSPierre Jolivet 
5916849ba73SBarry Smith static PetscErrorCode PCApplyTranspose_ASM(PC pc,Vec x,Vec y)
5924b9ad928SBarry Smith {
5934b9ad928SBarry Smith   PC_ASM         *osm = (PC_ASM*)pc->data;
5941dd8081eSeaulisa   PetscInt       i,n_local_true = osm->n_local_true;
5954b9ad928SBarry Smith   ScatterMode    forward = SCATTER_FORWARD,reverse = SCATTER_REVERSE;
5964b9ad928SBarry Smith 
5974b9ad928SBarry Smith   PetscFunctionBegin;
5984b9ad928SBarry Smith   /*
5994b9ad928SBarry Smith      Support for limiting the restriction or interpolation to only local
6004b9ad928SBarry Smith      subdomain values (leaving the other values 0).
6014b9ad928SBarry Smith 
6024b9ad928SBarry Smith      Note: these are reversed from the PCApply_ASM() because we are applying the
6034b9ad928SBarry Smith      transpose of the three terms
6044b9ad928SBarry Smith   */
605d8b3b5e3Seaulisa 
6064b9ad928SBarry Smith   if (!(osm->type & PC_ASM_INTERPOLATE)) {
6074b9ad928SBarry Smith     forward = SCATTER_FORWARD_LOCAL;
6084b9ad928SBarry Smith     /* have to zero the work RHS since scatter may leave some slots empty */
6099566063dSJacob Faibussowitsch     PetscCall(VecSet(osm->lx, 0.0));
6104b9ad928SBarry Smith   }
6112fa5cd67SKarl Rupp   if (!(osm->type & PC_ASM_RESTRICT)) reverse = SCATTER_REVERSE_LOCAL;
6124b9ad928SBarry Smith 
613b0de9f23SBarry Smith   /* zero the global and the local solutions */
6149566063dSJacob Faibussowitsch   PetscCall(VecSet(y, 0.0));
6159566063dSJacob Faibussowitsch   PetscCall(VecSet(osm->ly, 0.0));
616d8b3b5e3Seaulisa 
617b0de9f23SBarry Smith   /* Copy the global RHS to local RHS including the ghost nodes */
6189566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(osm->restriction, x, osm->lx, INSERT_VALUES, forward));
6199566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(osm->restriction, x, osm->lx, INSERT_VALUES, forward));
620d8b3b5e3Seaulisa 
621b0de9f23SBarry Smith   /* Restrict local RHS to the overlapping 0-block RHS */
6229566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(osm->lrestriction[0], osm->lx, osm->x[0], INSERT_VALUES, forward));
6239566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(osm->lrestriction[0], osm->lx, osm->x[0], INSERT_VALUES, forward));
624d8b3b5e3Seaulisa 
6254b9ad928SBarry Smith   /* do the local solves */
626d8b3b5e3Seaulisa   for (i = 0; i < n_local_true; ++i) {
627d8b3b5e3Seaulisa 
628b0de9f23SBarry Smith     /* solve the overlapping i-block */
6299566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(PC_ApplyOnBlocks,osm->ksp[i],osm->x[i],osm->y[i],0));
6309566063dSJacob Faibussowitsch     PetscCall(KSPSolveTranspose(osm->ksp[i], osm->x[i], osm->y[i]));
6319566063dSJacob Faibussowitsch     PetscCall(KSPCheckSolve(osm->ksp[i],pc,osm->y[i]));
6329566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(PC_ApplyOnBlocks,osm->ksp[i],osm->x[i],osm->y[i],0));
633d8b3b5e3Seaulisa 
634910cf402Sprj-     if (osm->lprolongation) { /* interpolate the non-overlapping i-block solution to the local solution */
6359566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(osm->lprolongation[i], osm->y[i], osm->ly, ADD_VALUES, forward));
6369566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(osm->lprolongation[i], osm->y[i], osm->ly, ADD_VALUES, forward));
637910cf402Sprj-     } else { /* interpolate the overlapping i-block solution to the local solution */
6389566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(osm->lrestriction[i], osm->y[i], osm->ly, ADD_VALUES, reverse));
6399566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(osm->lrestriction[i], osm->y[i], osm->ly, ADD_VALUES, reverse));
6404b9ad928SBarry Smith     }
641d8b3b5e3Seaulisa 
642d8b3b5e3Seaulisa     if (i < n_local_true-1) {
643b0de9f23SBarry Smith       /* Restrict local RHS to the overlapping (i+1)-block RHS */
6449566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(osm->lrestriction[i+1], osm->lx, osm->x[i+1], INSERT_VALUES, forward));
6459566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(osm->lrestriction[i+1], osm->lx, osm->x[i+1], INSERT_VALUES, forward));
6464b9ad928SBarry Smith     }
6474b9ad928SBarry Smith   }
648b0de9f23SBarry Smith   /* Add the local solution to the global solution including the ghost nodes */
6499566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(osm->restriction, osm->ly, y, ADD_VALUES, reverse));
6509566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(osm->restriction, osm->ly, y, ADD_VALUES, reverse));
6514b9ad928SBarry Smith   PetscFunctionReturn(0);
6524b9ad928SBarry Smith }
6534b9ad928SBarry Smith 
654e91c6855SBarry Smith static PetscErrorCode PCReset_ASM(PC pc)
6554b9ad928SBarry Smith {
6564b9ad928SBarry Smith   PC_ASM         *osm = (PC_ASM*)pc->data;
65713f74950SBarry Smith   PetscInt       i;
6584b9ad928SBarry Smith 
6594b9ad928SBarry Smith   PetscFunctionBegin;
66092bb6962SLisandro Dalcin   if (osm->ksp) {
66192bb6962SLisandro Dalcin     for (i=0; i<osm->n_local_true; i++) {
6629566063dSJacob Faibussowitsch       PetscCall(KSPReset(osm->ksp[i]));
66392bb6962SLisandro Dalcin     }
66492bb6962SLisandro Dalcin   }
665e09e08ccSBarry Smith   if (osm->pmat) {
66692bb6962SLisandro Dalcin     if (osm->n_local_true > 0) {
6679566063dSJacob Faibussowitsch       PetscCall(MatDestroySubMatrices(osm->n_local_true,&osm->pmat));
66892bb6962SLisandro Dalcin     }
66992bb6962SLisandro Dalcin   }
6701dd8081eSeaulisa   if (osm->lrestriction) {
6719566063dSJacob Faibussowitsch     PetscCall(VecScatterDestroy(&osm->restriction));
6721dd8081eSeaulisa     for (i=0; i<osm->n_local_true; i++) {
6739566063dSJacob Faibussowitsch       PetscCall(VecScatterDestroy(&osm->lrestriction[i]));
6749566063dSJacob Faibussowitsch       if (osm->lprolongation) PetscCall(VecScatterDestroy(&osm->lprolongation[i]));
6759566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&osm->x[i]));
6769566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&osm->y[i]));
6774b9ad928SBarry Smith     }
6789566063dSJacob Faibussowitsch     PetscCall(PetscFree(osm->lrestriction));
6799566063dSJacob Faibussowitsch     if (osm->lprolongation) PetscCall(PetscFree(osm->lprolongation));
6809566063dSJacob Faibussowitsch     PetscCall(PetscFree(osm->x));
6819566063dSJacob Faibussowitsch     PetscCall(PetscFree(osm->y));
6821dd8081eSeaulisa 
68392bb6962SLisandro Dalcin   }
6849566063dSJacob Faibussowitsch   PetscCall(PCASMDestroySubdomains(osm->n_local_true,osm->is,osm->is_local));
6859566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&osm->lis));
6869566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&osm->lx));
6879566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&osm->ly));
688347574c9Seaulisa   if (osm->loctype == PC_COMPOSITE_MULTIPLICATIVE) {
6899566063dSJacob Faibussowitsch     PetscCall(MatDestroyMatrices(osm->n_local_true, &osm->lmats));
690fb745f2cSMatthew G. Knepley   }
6912fa5cd67SKarl Rupp 
6929566063dSJacob Faibussowitsch   PetscCall(PetscFree(osm->sub_mat_type));
69380ec0b7dSPatrick Sanan 
6940a545947SLisandro Dalcin   osm->is       = NULL;
6950a545947SLisandro Dalcin   osm->is_local = NULL;
696e91c6855SBarry Smith   PetscFunctionReturn(0);
697e91c6855SBarry Smith }
698e91c6855SBarry Smith 
699e91c6855SBarry Smith static PetscErrorCode PCDestroy_ASM(PC pc)
700e91c6855SBarry Smith {
701e91c6855SBarry Smith   PC_ASM         *osm = (PC_ASM*)pc->data;
702e91c6855SBarry Smith   PetscInt       i;
703e91c6855SBarry Smith 
704e91c6855SBarry Smith   PetscFunctionBegin;
7059566063dSJacob Faibussowitsch   PetscCall(PCReset_ASM(pc));
706e91c6855SBarry Smith   if (osm->ksp) {
707e91c6855SBarry Smith     for (i=0; i<osm->n_local_true; i++) {
7089566063dSJacob Faibussowitsch       PetscCall(KSPDestroy(&osm->ksp[i]));
709e91c6855SBarry Smith     }
7109566063dSJacob Faibussowitsch     PetscCall(PetscFree(osm->ksp));
711e91c6855SBarry Smith   }
7129566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
71396322394SPierre Jolivet 
7149566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCASMSetLocalSubdomains_C",NULL));
7159566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCASMSetTotalSubdomains_C",NULL));
7169566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCASMSetOverlap_C",NULL));
7179566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCASMSetType_C",NULL));
7189566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCASMGetType_C",NULL));
7199566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCASMSetLocalType_C",NULL));
7209566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCASMGetLocalType_C",NULL));
7219566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCASMSetSortIndices_C",NULL));
7229566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCASMGetSubKSP_C",NULL));
7239566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCASMGetSubMatType_C",NULL));
7249566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCASMSetSubMatType_C",NULL));
7254b9ad928SBarry Smith   PetscFunctionReturn(0);
7264b9ad928SBarry Smith }
7274b9ad928SBarry Smith 
7284416b707SBarry Smith static PetscErrorCode PCSetFromOptions_ASM(PetscOptionItems *PetscOptionsObject,PC pc)
7294b9ad928SBarry Smith {
7304b9ad928SBarry Smith   PC_ASM         *osm = (PC_ASM*)pc->data;
7319dcbbd2bSBarry Smith   PetscInt       blocks,ovl;
73257501b6eSBarry Smith   PetscBool      flg;
73392bb6962SLisandro Dalcin   PCASMType      asmtype;
73412cd4985SMatthew G. Knepley   PCCompositeType loctype;
73580ec0b7dSPatrick Sanan   char           sub_mat_type[256];
7364b9ad928SBarry Smith 
7374b9ad928SBarry Smith   PetscFunctionBegin;
738d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject,"Additive Schwarz options");
7399566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_asm_dm_subdomains","Use DMCreateDomainDecomposition() to define subdomains","PCASMSetDMSubdomains",osm->dm_subdomains,&osm->dm_subdomains,&flg));
7409566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_asm_blocks","Number of subdomains","PCASMSetTotalSubdomains",osm->n,&blocks,&flg));
74165db9045SDmitry Karpeev   if (flg) {
7429566063dSJacob Faibussowitsch     PetscCall(PCASMSetTotalSubdomains(pc,blocks,NULL,NULL));
743d709ea83SDmitry Karpeev     osm->dm_subdomains = PETSC_FALSE;
74465db9045SDmitry Karpeev   }
7459566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_asm_local_blocks","Number of local subdomains","PCASMSetLocalSubdomains",osm->n_local_true,&blocks,&flg));
746342c94f9SMatthew G. Knepley   if (flg) {
7479566063dSJacob Faibussowitsch     PetscCall(PCASMSetLocalSubdomains(pc,blocks,NULL,NULL));
748342c94f9SMatthew G. Knepley     osm->dm_subdomains = PETSC_FALSE;
749342c94f9SMatthew G. Knepley   }
7509566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_asm_overlap","Number of grid points overlap","PCASMSetOverlap",osm->overlap,&ovl,&flg));
75165db9045SDmitry Karpeev   if (flg) {
7529566063dSJacob Faibussowitsch     PetscCall(PCASMSetOverlap(pc,ovl));
753d709ea83SDmitry Karpeev     osm->dm_subdomains = PETSC_FALSE;
75465db9045SDmitry Karpeev   }
75590d69ab7SBarry Smith   flg  = PETSC_FALSE;
7569566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-pc_asm_type","Type of restriction/extension","PCASMSetType",PCASMTypes,(PetscEnum)osm->type,(PetscEnum*)&asmtype,&flg));
7579566063dSJacob Faibussowitsch   if (flg) PetscCall(PCASMSetType(pc,asmtype));
75812cd4985SMatthew G. Knepley   flg  = PETSC_FALSE;
7599566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-pc_asm_local_type","Type of local solver composition","PCASMSetLocalType",PCCompositeTypes,(PetscEnum)osm->loctype,(PetscEnum*)&loctype,&flg));
7609566063dSJacob Faibussowitsch   if (flg) PetscCall(PCASMSetLocalType(pc,loctype));
7619566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-pc_asm_sub_mat_type","Subsolve Matrix Type","PCASMSetSubMatType",MatList,NULL,sub_mat_type,256,&flg));
76280ec0b7dSPatrick Sanan   if (flg) {
7639566063dSJacob Faibussowitsch     PetscCall(PCASMSetSubMatType(pc,sub_mat_type));
76480ec0b7dSPatrick Sanan   }
765d0609cedSBarry Smith   PetscOptionsHeadEnd();
7664b9ad928SBarry Smith   PetscFunctionReturn(0);
7674b9ad928SBarry Smith }
7684b9ad928SBarry Smith 
7694b9ad928SBarry Smith /*------------------------------------------------------------------------------------*/
7704b9ad928SBarry Smith 
7711e6b0712SBarry Smith static PetscErrorCode  PCASMSetLocalSubdomains_ASM(PC pc,PetscInt n,IS is[],IS is_local[])
7724b9ad928SBarry Smith {
7734b9ad928SBarry Smith   PC_ASM         *osm = (PC_ASM*)pc->data;
77492bb6962SLisandro Dalcin   PetscInt       i;
7754b9ad928SBarry Smith 
7764b9ad928SBarry Smith   PetscFunctionBegin;
77763a3b9bcSJacob Faibussowitsch   PetscCheck(n >= 1,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Each process must have 1 or more blocks, n = %" PetscInt_FMT,n);
7787827d75bSBarry Smith   PetscCheck(!pc->setupcalled || (n == osm->n_local_true && !is),PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"PCASMSetLocalSubdomains() should be called before calling PCSetUp().");
779e7e72b3dSBarry Smith 
7804b9ad928SBarry Smith   if (!pc->setupcalled) {
78192bb6962SLisandro Dalcin     if (is) {
7829566063dSJacob Faibussowitsch       for (i=0; i<n; i++) PetscCall(PetscObjectReference((PetscObject)is[i]));
78392bb6962SLisandro Dalcin     }
784832fc9a5SMatthew Knepley     if (is_local) {
7859566063dSJacob Faibussowitsch       for (i=0; i<n; i++) PetscCall(PetscObjectReference((PetscObject)is_local[i]));
786832fc9a5SMatthew Knepley     }
7879566063dSJacob Faibussowitsch     PetscCall(PCASMDestroySubdomains(osm->n_local_true,osm->is,osm->is_local));
7882fa5cd67SKarl Rupp 
7894b9ad928SBarry Smith     osm->n_local_true = n;
7900a545947SLisandro Dalcin     osm->is           = NULL;
7910a545947SLisandro Dalcin     osm->is_local     = NULL;
79292bb6962SLisandro Dalcin     if (is) {
7939566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(n,&osm->is));
7942fa5cd67SKarl Rupp       for (i=0; i<n; i++) osm->is[i] = is[i];
7953d03bb48SJed Brown       /* Flag indicating that the user has set overlapping subdomains so PCASM should not increase their size. */
7963d03bb48SJed Brown       osm->overlap = -1;
79792bb6962SLisandro Dalcin     }
7982b691e39SMatthew Knepley     if (is_local) {
7999566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(n,&osm->is_local));
8002fa5cd67SKarl Rupp       for (i=0; i<n; i++) osm->is_local[i] = is_local[i];
801a35b7b57SDmitry Karpeev       if (!is) {
8029566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(osm->n_local_true,&osm->is));
803a35b7b57SDmitry Karpeev         for (i=0; i<osm->n_local_true; i++) {
804a35b7b57SDmitry Karpeev           if (osm->overlap > 0) { /* With positive overlap, osm->is[i] will be modified */
8059566063dSJacob Faibussowitsch             PetscCall(ISDuplicate(osm->is_local[i],&osm->is[i]));
8069566063dSJacob Faibussowitsch             PetscCall(ISCopy(osm->is_local[i],osm->is[i]));
807a35b7b57SDmitry Karpeev           } else {
8089566063dSJacob Faibussowitsch             PetscCall(PetscObjectReference((PetscObject)osm->is_local[i]));
809a35b7b57SDmitry Karpeev             osm->is[i] = osm->is_local[i];
810a35b7b57SDmitry Karpeev           }
811a35b7b57SDmitry Karpeev         }
812a35b7b57SDmitry Karpeev       }
8132b691e39SMatthew Knepley     }
8144b9ad928SBarry Smith   }
8154b9ad928SBarry Smith   PetscFunctionReturn(0);
8164b9ad928SBarry Smith }
8174b9ad928SBarry Smith 
8181e6b0712SBarry Smith static PetscErrorCode  PCASMSetTotalSubdomains_ASM(PC pc,PetscInt N,IS *is,IS *is_local)
8194b9ad928SBarry Smith {
8204b9ad928SBarry Smith   PC_ASM         *osm = (PC_ASM*)pc->data;
82113f74950SBarry Smith   PetscMPIInt    rank,size;
82278904715SLisandro Dalcin   PetscInt       n;
8234b9ad928SBarry Smith 
8244b9ad928SBarry Smith   PetscFunctionBegin;
82563a3b9bcSJacob Faibussowitsch   PetscCheck(N >= 1,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Number of total blocks must be > 0, N = %" PetscInt_FMT,N);
8267827d75bSBarry Smith   PetscCheck(!is && !is_local,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Use PCASMSetLocalSubdomains() to set specific index sets\n\they cannot be set globally yet.");
8274b9ad928SBarry Smith 
8284b9ad928SBarry Smith   /*
829880770e9SJed Brown      Split the subdomains equally among all processors
8304b9ad928SBarry Smith   */
8319566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank));
8329566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size));
8334b9ad928SBarry Smith   n    = N/size + ((N % size) > rank);
83463a3b9bcSJacob Faibussowitsch   PetscCheck(n,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Process %d must have at least one block: total processors %d total blocks %" PetscInt_FMT,(int)rank,(int)size,N);
8357827d75bSBarry Smith   PetscCheck(!pc->setupcalled || n == osm->n_local_true,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"PCASMSetTotalSubdomains() should be called before PCSetUp().");
8364b9ad928SBarry Smith   if (!pc->setupcalled) {
8379566063dSJacob Faibussowitsch     PetscCall(PCASMDestroySubdomains(osm->n_local_true,osm->is,osm->is_local));
8382fa5cd67SKarl Rupp 
8394b9ad928SBarry Smith     osm->n_local_true = n;
8400a545947SLisandro Dalcin     osm->is           = NULL;
8410a545947SLisandro Dalcin     osm->is_local     = NULL;
8424b9ad928SBarry Smith   }
8434b9ad928SBarry Smith   PetscFunctionReturn(0);
8444b9ad928SBarry Smith }
8454b9ad928SBarry Smith 
8461e6b0712SBarry Smith static PetscErrorCode  PCASMSetOverlap_ASM(PC pc,PetscInt ovl)
8474b9ad928SBarry Smith {
84892bb6962SLisandro Dalcin   PC_ASM *osm = (PC_ASM*)pc->data;
8494b9ad928SBarry Smith 
8504b9ad928SBarry Smith   PetscFunctionBegin;
8517827d75bSBarry Smith   PetscCheck(ovl >= 0,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Negative overlap value requested");
8527827d75bSBarry Smith   PetscCheck(!pc->setupcalled || ovl == osm->overlap,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"PCASMSetOverlap() should be called before PCSetUp().");
8532fa5cd67SKarl Rupp   if (!pc->setupcalled) osm->overlap = ovl;
8544b9ad928SBarry Smith   PetscFunctionReturn(0);
8554b9ad928SBarry Smith }
8564b9ad928SBarry Smith 
8571e6b0712SBarry Smith static PetscErrorCode  PCASMSetType_ASM(PC pc,PCASMType type)
8584b9ad928SBarry Smith {
85992bb6962SLisandro Dalcin   PC_ASM *osm = (PC_ASM*)pc->data;
8604b9ad928SBarry Smith 
8614b9ad928SBarry Smith   PetscFunctionBegin;
8624b9ad928SBarry Smith   osm->type     = type;
863bf108f30SBarry Smith   osm->type_set = PETSC_TRUE;
8644b9ad928SBarry Smith   PetscFunctionReturn(0);
8654b9ad928SBarry Smith }
8664b9ad928SBarry Smith 
867c60c7ad4SBarry Smith static PetscErrorCode  PCASMGetType_ASM(PC pc,PCASMType *type)
868c60c7ad4SBarry Smith {
869c60c7ad4SBarry Smith   PC_ASM *osm = (PC_ASM*)pc->data;
870c60c7ad4SBarry Smith 
871c60c7ad4SBarry Smith   PetscFunctionBegin;
872c60c7ad4SBarry Smith   *type = osm->type;
873c60c7ad4SBarry Smith   PetscFunctionReturn(0);
874c60c7ad4SBarry Smith }
875c60c7ad4SBarry Smith 
87612cd4985SMatthew G. Knepley static PetscErrorCode  PCASMSetLocalType_ASM(PC pc, PCCompositeType type)
87712cd4985SMatthew G. Knepley {
87812cd4985SMatthew G. Knepley   PC_ASM *osm = (PC_ASM *) pc->data;
87912cd4985SMatthew G. Knepley 
88012cd4985SMatthew G. Knepley   PetscFunctionBegin;
8817827d75bSBarry Smith   PetscCheck(type == PC_COMPOSITE_ADDITIVE || type == PC_COMPOSITE_MULTIPLICATIVE,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Only supports additive or multiplicative as the local type");
88212cd4985SMatthew G. Knepley   osm->loctype = type;
88312cd4985SMatthew G. Knepley   PetscFunctionReturn(0);
88412cd4985SMatthew G. Knepley }
88512cd4985SMatthew G. Knepley 
88612cd4985SMatthew G. Knepley static PetscErrorCode  PCASMGetLocalType_ASM(PC pc, PCCompositeType *type)
88712cd4985SMatthew G. Knepley {
88812cd4985SMatthew G. Knepley   PC_ASM *osm = (PC_ASM *) pc->data;
88912cd4985SMatthew G. Knepley 
89012cd4985SMatthew G. Knepley   PetscFunctionBegin;
89112cd4985SMatthew G. Knepley   *type = osm->loctype;
89212cd4985SMatthew G. Knepley   PetscFunctionReturn(0);
89312cd4985SMatthew G. Knepley }
89412cd4985SMatthew G. Knepley 
8951e6b0712SBarry Smith static PetscErrorCode  PCASMSetSortIndices_ASM(PC pc,PetscBool  doSort)
8966ed231c7SMatthew Knepley {
8976ed231c7SMatthew Knepley   PC_ASM *osm = (PC_ASM*)pc->data;
8986ed231c7SMatthew Knepley 
8996ed231c7SMatthew Knepley   PetscFunctionBegin;
9006ed231c7SMatthew Knepley   osm->sort_indices = doSort;
9016ed231c7SMatthew Knepley   PetscFunctionReturn(0);
9026ed231c7SMatthew Knepley }
9036ed231c7SMatthew Knepley 
9041e6b0712SBarry Smith static PetscErrorCode  PCASMGetSubKSP_ASM(PC pc,PetscInt *n_local,PetscInt *first_local,KSP **ksp)
9054b9ad928SBarry Smith {
90692bb6962SLisandro Dalcin   PC_ASM         *osm = (PC_ASM*)pc->data;
9074b9ad928SBarry Smith 
9084b9ad928SBarry Smith   PetscFunctionBegin;
9097827d75bSBarry Smith   PetscCheck(osm->n_local_true >= 1,PetscObjectComm((PetscObject)pc),PETSC_ERR_ORDER,"Need to call PCSetUp() on PC (or KSPSetUp() on the outer KSP object) before calling here");
9104b9ad928SBarry Smith 
9112fa5cd67SKarl Rupp   if (n_local) *n_local = osm->n_local_true;
91292bb6962SLisandro Dalcin   if (first_local) {
9139566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Scan(&osm->n_local_true,first_local,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc)));
91492bb6962SLisandro Dalcin     *first_local -= osm->n_local_true;
91592bb6962SLisandro Dalcin   }
916ed155784SPierre Jolivet   if (ksp) *ksp   = osm->ksp;
9174b9ad928SBarry Smith   PetscFunctionReturn(0);
9184b9ad928SBarry Smith }
9194b9ad928SBarry Smith 
92080ec0b7dSPatrick Sanan static PetscErrorCode  PCASMGetSubMatType_ASM(PC pc,MatType *sub_mat_type)
92180ec0b7dSPatrick Sanan {
92280ec0b7dSPatrick Sanan   PC_ASM         *osm = (PC_ASM*)pc->data;
92380ec0b7dSPatrick Sanan 
92480ec0b7dSPatrick Sanan   PetscFunctionBegin;
92580ec0b7dSPatrick Sanan   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
92680ec0b7dSPatrick Sanan   PetscValidPointer(sub_mat_type,2);
92780ec0b7dSPatrick Sanan   *sub_mat_type = osm->sub_mat_type;
92880ec0b7dSPatrick Sanan   PetscFunctionReturn(0);
92980ec0b7dSPatrick Sanan }
93080ec0b7dSPatrick Sanan 
93180ec0b7dSPatrick Sanan static PetscErrorCode PCASMSetSubMatType_ASM(PC pc,MatType sub_mat_type)
93280ec0b7dSPatrick Sanan {
93380ec0b7dSPatrick Sanan   PC_ASM            *osm = (PC_ASM*)pc->data;
93480ec0b7dSPatrick Sanan 
93580ec0b7dSPatrick Sanan   PetscFunctionBegin;
93680ec0b7dSPatrick Sanan   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
9379566063dSJacob Faibussowitsch   PetscCall(PetscFree(osm->sub_mat_type));
9389566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(sub_mat_type,(char**)&osm->sub_mat_type));
93980ec0b7dSPatrick Sanan   PetscFunctionReturn(0);
94080ec0b7dSPatrick Sanan }
94180ec0b7dSPatrick Sanan 
9424b9ad928SBarry Smith /*@C
9431093a601SBarry Smith     PCASMSetLocalSubdomains - Sets the local subdomains (for this processor only) for the additive Schwarz preconditioner.
9444b9ad928SBarry Smith 
945d083f849SBarry Smith     Collective on pc
9464b9ad928SBarry Smith 
9474b9ad928SBarry Smith     Input Parameters:
9484b9ad928SBarry Smith +   pc - the preconditioner context
9494b9ad928SBarry Smith .   n - the number of subdomains for this processor (default value = 1)
9508c03b21aSDmitry Karpeev .   is - the index set that defines the subdomains for this processor
9510298fd71SBarry Smith          (or NULL for PETSc to determine subdomains)
952f1ee410cSBarry Smith -   is_local - the index sets that define the local part of the subdomains for this processor, not used unless PCASMType is PC_ASM_RESTRICT
953f1ee410cSBarry Smith          (or NULL to not provide these)
9544b9ad928SBarry Smith 
955342c94f9SMatthew G. Knepley     Options Database Key:
956342c94f9SMatthew G. Knepley     To set the total number of subdomain blocks rather than specify the
957342c94f9SMatthew G. Knepley     index sets, use the option
958342c94f9SMatthew G. Knepley .    -pc_asm_local_blocks <blks> - Sets local blocks
959342c94f9SMatthew G. Knepley 
9604b9ad928SBarry Smith     Notes:
9611093a601SBarry Smith     The IS numbering is in the parallel, global numbering of the vector for both is and is_local
9624b9ad928SBarry Smith 
9634b9ad928SBarry Smith     By default the ASM preconditioner uses 1 block per processor.
9644b9ad928SBarry Smith 
9654b9ad928SBarry Smith     Use PCASMSetTotalSubdomains() to set the subdomains for all processors.
9664b9ad928SBarry Smith 
967f1ee410cSBarry Smith     If is_local is provided and PCASMType is PC_ASM_RESTRICT then the solution only over the is_local region is interpolated
968f1ee410cSBarry Smith     back to form the global solution (this is the standard restricted additive Schwarz method)
969f1ee410cSBarry Smith 
970f1ee410cSBarry Smith     If the is_local is provided and PCASMType is PC_ASM_INTERPOLATE or PC_ASM_NONE then an error is generated since there is
971f1ee410cSBarry Smith     no code to handle that case.
972f1ee410cSBarry Smith 
9734b9ad928SBarry Smith     Level: advanced
9744b9ad928SBarry Smith 
975db781477SPatrick Sanan .seealso: `PCASMSetTotalSubdomains()`, `PCASMSetOverlap()`, `PCASMGetSubKSP()`,
976db781477SPatrick Sanan           `PCASMCreateSubdomains2D()`, `PCASMGetLocalSubdomains()`, `PCASMType`, `PCASMSetType()`
9774b9ad928SBarry Smith @*/
9787087cfbeSBarry Smith PetscErrorCode  PCASMSetLocalSubdomains(PC pc,PetscInt n,IS is[],IS is_local[])
9794b9ad928SBarry Smith {
9804b9ad928SBarry Smith   PetscFunctionBegin;
9810700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
982cac4c232SBarry Smith   PetscTryMethod(pc,"PCASMSetLocalSubdomains_C",(PC,PetscInt,IS[],IS[]),(pc,n,is,is_local));
9834b9ad928SBarry Smith   PetscFunctionReturn(0);
9844b9ad928SBarry Smith }
9854b9ad928SBarry Smith 
9864b9ad928SBarry Smith /*@C
987feb221f8SDmitry Karpeev     PCASMSetTotalSubdomains - Sets the subdomains for all processors for the
9884b9ad928SBarry Smith     additive Schwarz preconditioner.  Either all or no processors in the
9894b9ad928SBarry Smith     PC communicator must call this routine, with the same index sets.
9904b9ad928SBarry Smith 
991d083f849SBarry Smith     Collective on pc
9924b9ad928SBarry Smith 
9934b9ad928SBarry Smith     Input Parameters:
9944b9ad928SBarry Smith +   pc - the preconditioner context
995feb221f8SDmitry Karpeev .   N  - the number of subdomains for all processors
996feb221f8SDmitry Karpeev .   is - the index sets that define the subdomains for all processors
997dfaa0c5fSBarry Smith          (or NULL to ask PETSc to determine the subdomains)
9982b691e39SMatthew Knepley -   is_local - the index sets that define the local part of the subdomains for this processor
999f1ee410cSBarry Smith          (or NULL to not provide this information)
10004b9ad928SBarry Smith 
10014b9ad928SBarry Smith     Options Database Key:
10024b9ad928SBarry Smith     To set the total number of subdomain blocks rather than specify the
10034b9ad928SBarry Smith     index sets, use the option
10044b9ad928SBarry Smith .    -pc_asm_blocks <blks> - Sets total blocks
10054b9ad928SBarry Smith 
10064b9ad928SBarry Smith     Notes:
1007f1ee410cSBarry Smith     Currently you cannot use this to set the actual subdomains with the argument is or is_local.
10084b9ad928SBarry Smith 
10094b9ad928SBarry Smith     By default the ASM preconditioner uses 1 block per processor.
10104b9ad928SBarry Smith 
10114b9ad928SBarry Smith     These index sets cannot be destroyed until after completion of the
10124b9ad928SBarry Smith     linear solves for which the ASM preconditioner is being used.
10134b9ad928SBarry Smith 
10144b9ad928SBarry Smith     Use PCASMSetLocalSubdomains() to set local subdomains.
10154b9ad928SBarry Smith 
10161093a601SBarry Smith     The IS numbering is in the parallel, global numbering of the vector for both is and is_local
10171093a601SBarry Smith 
10184b9ad928SBarry Smith     Level: advanced
10194b9ad928SBarry Smith 
1020db781477SPatrick Sanan .seealso: `PCASMSetLocalSubdomains()`, `PCASMSetOverlap()`, `PCASMGetSubKSP()`,
1021db781477SPatrick Sanan           `PCASMCreateSubdomains2D()`
10224b9ad928SBarry Smith @*/
10237087cfbeSBarry Smith PetscErrorCode  PCASMSetTotalSubdomains(PC pc,PetscInt N,IS is[],IS is_local[])
10244b9ad928SBarry Smith {
10254b9ad928SBarry Smith   PetscFunctionBegin;
10260700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1027cac4c232SBarry Smith   PetscTryMethod(pc,"PCASMSetTotalSubdomains_C",(PC,PetscInt,IS[],IS[]),(pc,N,is,is_local));
10284b9ad928SBarry Smith   PetscFunctionReturn(0);
10294b9ad928SBarry Smith }
10304b9ad928SBarry Smith 
10314b9ad928SBarry Smith /*@
10324b9ad928SBarry Smith     PCASMSetOverlap - Sets the overlap between a pair of subdomains for the
10334b9ad928SBarry Smith     additive Schwarz preconditioner.  Either all or no processors in the
1034f1ee410cSBarry Smith     PC communicator must call this routine.
10354b9ad928SBarry Smith 
1036d083f849SBarry Smith     Logically Collective on pc
10374b9ad928SBarry Smith 
10384b9ad928SBarry Smith     Input Parameters:
10394b9ad928SBarry Smith +   pc  - the preconditioner context
10404b9ad928SBarry Smith -   ovl - the amount of overlap between subdomains (ovl >= 0, default value = 1)
10414b9ad928SBarry Smith 
10424b9ad928SBarry Smith     Options Database Key:
10434b9ad928SBarry Smith .   -pc_asm_overlap <ovl> - Sets overlap
10444b9ad928SBarry Smith 
10454b9ad928SBarry Smith     Notes:
10464b9ad928SBarry Smith     By default the ASM preconditioner uses 1 block per processor.  To use
10474b9ad928SBarry Smith     multiple blocks per perocessor, see PCASMSetTotalSubdomains() and
10484b9ad928SBarry Smith     PCASMSetLocalSubdomains() (and the option -pc_asm_blocks <blks>).
10494b9ad928SBarry Smith 
10504b9ad928SBarry Smith     The overlap defaults to 1, so if one desires that no additional
10514b9ad928SBarry Smith     overlap be computed beyond what may have been set with a call to
10524b9ad928SBarry Smith     PCASMSetTotalSubdomains() or PCASMSetLocalSubdomains(), then ovl
10534b9ad928SBarry Smith     must be set to be 0.  In particular, if one does not explicitly set
10544b9ad928SBarry Smith     the subdomains an application code, then all overlap would be computed
10554b9ad928SBarry Smith     internally by PETSc, and using an overlap of 0 would result in an ASM
10564b9ad928SBarry Smith     variant that is equivalent to the block Jacobi preconditioner.
10574b9ad928SBarry Smith 
1058f1ee410cSBarry Smith     The default algorithm used by PETSc to increase overlap is fast, but not scalable,
1059f1ee410cSBarry Smith     use the option -mat_increase_overlap_scalable when the problem and number of processes is large.
1060f1ee410cSBarry Smith 
10614b9ad928SBarry Smith     Note that one can define initial index sets with any overlap via
1062f1ee410cSBarry Smith     PCASMSetLocalSubdomains(); the routine
10634b9ad928SBarry Smith     PCASMSetOverlap() merely allows PETSc to extend that overlap further
10644b9ad928SBarry Smith     if desired.
10654b9ad928SBarry Smith 
10664b9ad928SBarry Smith     Level: intermediate
10674b9ad928SBarry Smith 
1068db781477SPatrick Sanan .seealso: `PCASMSetTotalSubdomains()`, `PCASMSetLocalSubdomains()`, `PCASMGetSubKSP()`,
1069db781477SPatrick Sanan           `PCASMCreateSubdomains2D()`, `PCASMGetLocalSubdomains()`, `MatIncreaseOverlap()`
10704b9ad928SBarry Smith @*/
10717087cfbeSBarry Smith PetscErrorCode  PCASMSetOverlap(PC pc,PetscInt ovl)
10724b9ad928SBarry Smith {
10734b9ad928SBarry Smith   PetscFunctionBegin;
10740700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1075c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(pc,ovl,2);
1076cac4c232SBarry Smith   PetscTryMethod(pc,"PCASMSetOverlap_C",(PC,PetscInt),(pc,ovl));
10774b9ad928SBarry Smith   PetscFunctionReturn(0);
10784b9ad928SBarry Smith }
10794b9ad928SBarry Smith 
10804b9ad928SBarry Smith /*@
10814b9ad928SBarry Smith     PCASMSetType - Sets the type of restriction and interpolation used
10824b9ad928SBarry Smith     for local problems in the additive Schwarz method.
10834b9ad928SBarry Smith 
1084d083f849SBarry Smith     Logically Collective on pc
10854b9ad928SBarry Smith 
10864b9ad928SBarry Smith     Input Parameters:
10874b9ad928SBarry Smith +   pc  - the preconditioner context
10884b9ad928SBarry Smith -   type - variant of ASM, one of
10894b9ad928SBarry Smith .vb
10904b9ad928SBarry Smith       PC_ASM_BASIC       - full interpolation and restriction
109182b5ce2aSStefano Zampini       PC_ASM_RESTRICT    - full restriction, local processor interpolation (default)
10924b9ad928SBarry Smith       PC_ASM_INTERPOLATE - full interpolation, local processor restriction
10934b9ad928SBarry Smith       PC_ASM_NONE        - local processor restriction and interpolation
10944b9ad928SBarry Smith .ve
10954b9ad928SBarry Smith 
10964b9ad928SBarry Smith     Options Database Key:
10974b9ad928SBarry Smith .   -pc_asm_type [basic,restrict,interpolate,none] - Sets ASM type
10984b9ad928SBarry Smith 
109995452b02SPatrick Sanan     Notes:
110095452b02SPatrick Sanan     if the is_local arguments are passed to PCASMSetLocalSubdomains() then they are used when PC_ASM_RESTRICT has been selected
1101f1ee410cSBarry Smith     to limit the local processor interpolation
1102f1ee410cSBarry Smith 
11034b9ad928SBarry Smith     Level: intermediate
11044b9ad928SBarry Smith 
1105db781477SPatrick Sanan .seealso: `PCASMSetTotalSubdomains()`, `PCASMSetTotalSubdomains()`, `PCASMGetSubKSP()`,
1106db781477SPatrick Sanan           `PCASMCreateSubdomains2D()`, `PCASMType`, `PCASMSetLocalType()`, `PCASMGetLocalType()`
11074b9ad928SBarry Smith @*/
11087087cfbeSBarry Smith PetscErrorCode  PCASMSetType(PC pc,PCASMType type)
11094b9ad928SBarry Smith {
11104b9ad928SBarry Smith   PetscFunctionBegin;
11110700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1112c5eb9154SBarry Smith   PetscValidLogicalCollectiveEnum(pc,type,2);
1113cac4c232SBarry Smith   PetscTryMethod(pc,"PCASMSetType_C",(PC,PCASMType),(pc,type));
11144b9ad928SBarry Smith   PetscFunctionReturn(0);
11154b9ad928SBarry Smith }
11164b9ad928SBarry Smith 
1117c60c7ad4SBarry Smith /*@
1118c60c7ad4SBarry Smith     PCASMGetType - Gets the type of restriction and interpolation used
1119c60c7ad4SBarry Smith     for local problems in the additive Schwarz method.
1120c60c7ad4SBarry Smith 
1121d083f849SBarry Smith     Logically Collective on pc
1122c60c7ad4SBarry Smith 
1123c60c7ad4SBarry Smith     Input Parameter:
1124c60c7ad4SBarry Smith .   pc  - the preconditioner context
1125c60c7ad4SBarry Smith 
1126c60c7ad4SBarry Smith     Output Parameter:
1127c60c7ad4SBarry Smith .   type - variant of ASM, one of
1128c60c7ad4SBarry Smith 
1129c60c7ad4SBarry Smith .vb
1130c60c7ad4SBarry Smith       PC_ASM_BASIC       - full interpolation and restriction
1131c60c7ad4SBarry Smith       PC_ASM_RESTRICT    - full restriction, local processor interpolation
1132c60c7ad4SBarry Smith       PC_ASM_INTERPOLATE - full interpolation, local processor restriction
1133c60c7ad4SBarry Smith       PC_ASM_NONE        - local processor restriction and interpolation
1134c60c7ad4SBarry Smith .ve
1135c60c7ad4SBarry Smith 
1136c60c7ad4SBarry Smith     Options Database Key:
1137c60c7ad4SBarry Smith .   -pc_asm_type [basic,restrict,interpolate,none] - Sets ASM type
1138c60c7ad4SBarry Smith 
1139c60c7ad4SBarry Smith     Level: intermediate
1140c60c7ad4SBarry Smith 
1141db781477SPatrick Sanan .seealso: `PCASMSetTotalSubdomains()`, `PCASMSetTotalSubdomains()`, `PCASMGetSubKSP()`,
1142db781477SPatrick Sanan           `PCASMCreateSubdomains2D()`, `PCASMType`, `PCASMSetType()`, `PCASMSetLocalType()`, `PCASMGetLocalType()`
1143c60c7ad4SBarry Smith @*/
1144c60c7ad4SBarry Smith PetscErrorCode  PCASMGetType(PC pc,PCASMType *type)
1145c60c7ad4SBarry Smith {
1146c60c7ad4SBarry Smith   PetscFunctionBegin;
1147c60c7ad4SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1148cac4c232SBarry Smith   PetscUseMethod(pc,"PCASMGetType_C",(PC,PCASMType*),(pc,type));
1149c60c7ad4SBarry Smith   PetscFunctionReturn(0);
1150c60c7ad4SBarry Smith }
1151c60c7ad4SBarry Smith 
115212cd4985SMatthew G. Knepley /*@
115312cd4985SMatthew G. Knepley   PCASMSetLocalType - Sets the type of composition used for local problems in the additive Schwarz method.
115412cd4985SMatthew G. Knepley 
1155d083f849SBarry Smith   Logically Collective on pc
115612cd4985SMatthew G. Knepley 
115712cd4985SMatthew G. Knepley   Input Parameters:
115812cd4985SMatthew G. Knepley + pc  - the preconditioner context
115912cd4985SMatthew G. Knepley - type - type of composition, one of
116012cd4985SMatthew G. Knepley .vb
116112cd4985SMatthew G. Knepley   PC_COMPOSITE_ADDITIVE       - local additive combination
116212cd4985SMatthew G. Knepley   PC_COMPOSITE_MULTIPLICATIVE - local multiplicative combination
116312cd4985SMatthew G. Knepley .ve
116412cd4985SMatthew G. Knepley 
116512cd4985SMatthew G. Knepley   Options Database Key:
116612cd4985SMatthew G. Knepley . -pc_asm_local_type [additive,multiplicative] - Sets local solver composition type
116712cd4985SMatthew G. Knepley 
116812cd4985SMatthew G. Knepley   Level: intermediate
116912cd4985SMatthew G. Knepley 
1170db781477SPatrick Sanan .seealso: `PCASMSetType()`, `PCASMGetType()`, `PCASMGetLocalType()`, `PCASM`, `PCASMType`, `PCASMSetType()`, `PCASMGetType()`, `PCCompositeType`
117112cd4985SMatthew G. Knepley @*/
117212cd4985SMatthew G. Knepley PetscErrorCode PCASMSetLocalType(PC pc, PCCompositeType type)
117312cd4985SMatthew G. Knepley {
117412cd4985SMatthew G. Knepley   PetscFunctionBegin;
117512cd4985SMatthew G. Knepley   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
117612cd4985SMatthew G. Knepley   PetscValidLogicalCollectiveEnum(pc, type, 2);
1177cac4c232SBarry Smith   PetscTryMethod(pc, "PCASMSetLocalType_C", (PC, PCCompositeType), (pc, type));
117812cd4985SMatthew G. Knepley   PetscFunctionReturn(0);
117912cd4985SMatthew G. Knepley }
118012cd4985SMatthew G. Knepley 
118112cd4985SMatthew G. Knepley /*@
118212cd4985SMatthew G. Knepley   PCASMGetLocalType - Gets the type of composition used for local problems in the additive Schwarz method.
118312cd4985SMatthew G. Knepley 
1184d083f849SBarry Smith   Logically Collective on pc
118512cd4985SMatthew G. Knepley 
118612cd4985SMatthew G. Knepley   Input Parameter:
118712cd4985SMatthew G. Knepley . pc  - the preconditioner context
118812cd4985SMatthew G. Knepley 
118912cd4985SMatthew G. Knepley   Output Parameter:
119012cd4985SMatthew G. Knepley . type - type of composition, one of
119112cd4985SMatthew G. Knepley .vb
119212cd4985SMatthew G. Knepley   PC_COMPOSITE_ADDITIVE       - local additive combination
119312cd4985SMatthew G. Knepley   PC_COMPOSITE_MULTIPLICATIVE - local multiplicative combination
119412cd4985SMatthew G. Knepley .ve
119512cd4985SMatthew G. Knepley 
119612cd4985SMatthew G. Knepley   Options Database Key:
119712cd4985SMatthew G. Knepley . -pc_asm_local_type [additive,multiplicative] - Sets local solver composition type
119812cd4985SMatthew G. Knepley 
119912cd4985SMatthew G. Knepley   Level: intermediate
120012cd4985SMatthew G. Knepley 
1201db781477SPatrick Sanan .seealso: `PCASMSetType()`, `PCASMGetType()`, `PCASMSetLocalType()`, `PCASMCreate()`, `PCASMType`, `PCASMSetType()`, `PCASMGetType()`, `PCCompositeType`
120212cd4985SMatthew G. Knepley @*/
120312cd4985SMatthew G. Knepley PetscErrorCode PCASMGetLocalType(PC pc, PCCompositeType *type)
120412cd4985SMatthew G. Knepley {
120512cd4985SMatthew G. Knepley   PetscFunctionBegin;
120612cd4985SMatthew G. Knepley   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
120712cd4985SMatthew G. Knepley   PetscValidPointer(type, 2);
1208cac4c232SBarry Smith   PetscUseMethod(pc, "PCASMGetLocalType_C", (PC, PCCompositeType *), (pc, type));
120912cd4985SMatthew G. Knepley   PetscFunctionReturn(0);
121012cd4985SMatthew G. Knepley }
121112cd4985SMatthew G. Knepley 
12126ed231c7SMatthew Knepley /*@
12136ed231c7SMatthew Knepley     PCASMSetSortIndices - Determines whether subdomain indices are sorted.
12146ed231c7SMatthew Knepley 
1215d083f849SBarry Smith     Logically Collective on pc
12166ed231c7SMatthew Knepley 
12176ed231c7SMatthew Knepley     Input Parameters:
12186ed231c7SMatthew Knepley +   pc  - the preconditioner context
12196ed231c7SMatthew Knepley -   doSort - sort the subdomain indices
12206ed231c7SMatthew Knepley 
12216ed231c7SMatthew Knepley     Level: intermediate
12226ed231c7SMatthew Knepley 
1223db781477SPatrick Sanan .seealso: `PCASMSetLocalSubdomains()`, `PCASMSetTotalSubdomains()`, `PCASMGetSubKSP()`,
1224db781477SPatrick Sanan           `PCASMCreateSubdomains2D()`
12256ed231c7SMatthew Knepley @*/
12267087cfbeSBarry Smith PetscErrorCode  PCASMSetSortIndices(PC pc,PetscBool doSort)
12276ed231c7SMatthew Knepley {
12286ed231c7SMatthew Knepley   PetscFunctionBegin;
12290700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1230acfcf0e5SJed Brown   PetscValidLogicalCollectiveBool(pc,doSort,2);
1231cac4c232SBarry Smith   PetscTryMethod(pc,"PCASMSetSortIndices_C",(PC,PetscBool),(pc,doSort));
12326ed231c7SMatthew Knepley   PetscFunctionReturn(0);
12336ed231c7SMatthew Knepley }
12346ed231c7SMatthew Knepley 
12354b9ad928SBarry Smith /*@C
12364b9ad928SBarry Smith    PCASMGetSubKSP - Gets the local KSP contexts for all blocks on
12374b9ad928SBarry Smith    this processor.
12384b9ad928SBarry Smith 
1239d083f849SBarry Smith    Collective on pc iff first_local is requested
12404b9ad928SBarry Smith 
12414b9ad928SBarry Smith    Input Parameter:
12424b9ad928SBarry Smith .  pc - the preconditioner context
12434b9ad928SBarry Smith 
12444b9ad928SBarry Smith    Output Parameters:
12450298fd71SBarry Smith +  n_local - the number of blocks on this processor or NULL
12460298fd71SBarry Smith .  first_local - the global number of the first block on this processor or NULL,
12470298fd71SBarry Smith                  all processors must request or all must pass NULL
12484b9ad928SBarry Smith -  ksp - the array of KSP contexts
12494b9ad928SBarry Smith 
12504b9ad928SBarry Smith    Note:
1251d29017ddSJed Brown    After PCASMGetSubKSP() the array of KSPes is not to be freed.
12524b9ad928SBarry Smith 
12534b9ad928SBarry Smith    You must call KSPSetUp() before calling PCASMGetSubKSP().
12544b9ad928SBarry Smith 
1255d29017ddSJed Brown    Fortran note:
12562bf68e3eSBarry Smith    The output argument 'ksp' must be an array of sufficient length or PETSC_NULL_KSP. The latter can be used to learn the necessary length.
1257d29017ddSJed Brown 
12584b9ad928SBarry Smith    Level: advanced
12594b9ad928SBarry Smith 
1260db781477SPatrick Sanan .seealso: `PCASMSetTotalSubdomains()`, `PCASMSetTotalSubdomains()`, `PCASMSetOverlap()`,
1261db781477SPatrick Sanan           `PCASMCreateSubdomains2D()`,
12624b9ad928SBarry Smith @*/
12637087cfbeSBarry Smith PetscErrorCode  PCASMGetSubKSP(PC pc,PetscInt *n_local,PetscInt *first_local,KSP *ksp[])
12644b9ad928SBarry Smith {
12654b9ad928SBarry Smith   PetscFunctionBegin;
12660700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1267cac4c232SBarry Smith   PetscUseMethod(pc,"PCASMGetSubKSP_C",(PC,PetscInt*,PetscInt*,KSP **),(pc,n_local,first_local,ksp));
12684b9ad928SBarry Smith   PetscFunctionReturn(0);
12694b9ad928SBarry Smith }
12704b9ad928SBarry Smith 
12714b9ad928SBarry Smith /* -------------------------------------------------------------------------------------*/
12724b9ad928SBarry Smith /*MC
12733b09bd56SBarry Smith    PCASM - Use the (restricted) additive Schwarz method, each block is (approximately) solved with
12744b9ad928SBarry Smith            its own KSP object.
12754b9ad928SBarry Smith 
12764b9ad928SBarry Smith    Options Database Keys:
127749517cdeSBarry Smith +  -pc_asm_blocks <blks> - Sets total blocks
12784b9ad928SBarry Smith .  -pc_asm_overlap <ovl> - Sets overlap
1279f1ee410cSBarry Smith .  -pc_asm_type [basic,restrict,interpolate,none] - Sets ASM type, default is restrict
1280f1ee410cSBarry Smith -  -pc_asm_local_type [additive, multiplicative] - Sets ASM type, default is additive
12814b9ad928SBarry Smith 
12823b09bd56SBarry Smith      IMPORTANT: If you run with, for example, 3 blocks on 1 processor or 3 blocks on 3 processors you
12833b09bd56SBarry Smith       will get a different convergence rate due to the default option of -pc_asm_type restrict. Use
12843b09bd56SBarry Smith       -pc_asm_type basic to use the standard ASM.
12853b09bd56SBarry Smith 
128695452b02SPatrick Sanan    Notes:
128795452b02SPatrick Sanan     Each processor can have one or more blocks, but a block cannot be shared by more
1288f1ee410cSBarry Smith      than one processor. Use PCGASM for subdomains shared by multiple processes. Defaults to one block per processor.
12894b9ad928SBarry Smith 
12903b09bd56SBarry Smith      To set options on the solvers for each block append -sub_ to all the KSP, and PC
1291d7ee0231SBarry Smith         options database keys. For example, -sub_pc_type ilu -sub_pc_factor_levels 1 -sub_ksp_type preonly
12924b9ad928SBarry Smith 
1293a8c7a070SBarry Smith      To set the options on the solvers separate for each block call PCASMGetSubKSP()
12944b9ad928SBarry Smith          and set the options directly on the resulting KSP object (you can access its PC
12954b9ad928SBarry Smith          with KSPGetPC())
12964b9ad928SBarry Smith 
12974b9ad928SBarry Smith    Level: beginner
12984b9ad928SBarry Smith 
1299c582cd25SBarry Smith     References:
1300606c0280SSatish Balay +   * - M Dryja, OB Widlund, An additive variant of the Schwarz alternating method for the case of many subregions
130196a0c994SBarry Smith      Courant Institute, New York University Technical report
1302606c0280SSatish Balay -   * - Barry Smith, Petter Bjorstad, and William Gropp, Domain Decompositions: Parallel Multilevel Methods for Elliptic Partial Differential Equations,
130396a0c994SBarry Smith     Cambridge University Press.
1304c582cd25SBarry Smith 
1305db781477SPatrick Sanan .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`,
1306db781477SPatrick Sanan           `PCBJACOBI`, `PCASMGetSubKSP()`, `PCASMSetLocalSubdomains()`, `PCASMType`, `PCASMGetType()`, `PCASMSetLocalType()`, `PCASMGetLocalType()`
1307db781477SPatrick Sanan           `PCASMSetTotalSubdomains()`, `PCSetModifySubMatrices()`, `PCASMSetOverlap()`, `PCASMSetType()`, `PCCompositeType`
1308e09e08ccSBarry Smith 
13094b9ad928SBarry Smith M*/
13104b9ad928SBarry Smith 
13118cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_ASM(PC pc)
13124b9ad928SBarry Smith {
13134b9ad928SBarry Smith   PC_ASM         *osm;
13144b9ad928SBarry Smith 
13154b9ad928SBarry Smith   PetscFunctionBegin;
13169566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(pc,&osm));
13172fa5cd67SKarl Rupp 
13184b9ad928SBarry Smith   osm->n                 = PETSC_DECIDE;
13194b9ad928SBarry Smith   osm->n_local           = 0;
13202b837212SDmitry Karpeev   osm->n_local_true      = PETSC_DECIDE;
13214b9ad928SBarry Smith   osm->overlap           = 1;
13220a545947SLisandro Dalcin   osm->ksp               = NULL;
13230a545947SLisandro Dalcin   osm->restriction       = NULL;
13240a545947SLisandro Dalcin   osm->lprolongation     = NULL;
13250a545947SLisandro Dalcin   osm->lrestriction      = NULL;
13260a545947SLisandro Dalcin   osm->x                 = NULL;
13270a545947SLisandro Dalcin   osm->y                 = NULL;
13280a545947SLisandro Dalcin   osm->is                = NULL;
13290a545947SLisandro Dalcin   osm->is_local          = NULL;
13300a545947SLisandro Dalcin   osm->mat               = NULL;
13310a545947SLisandro Dalcin   osm->pmat              = NULL;
13324b9ad928SBarry Smith   osm->type              = PC_ASM_RESTRICT;
133312cd4985SMatthew G. Knepley   osm->loctype           = PC_COMPOSITE_ADDITIVE;
13346ed231c7SMatthew Knepley   osm->sort_indices      = PETSC_TRUE;
1335d709ea83SDmitry Karpeev   osm->dm_subdomains     = PETSC_FALSE;
133680ec0b7dSPatrick Sanan   osm->sub_mat_type      = NULL;
13374b9ad928SBarry Smith 
133892bb6962SLisandro Dalcin   pc->data                 = (void*)osm;
13394b9ad928SBarry Smith   pc->ops->apply           = PCApply_ASM;
134048e38a8aSPierre Jolivet   pc->ops->matapply        = PCMatApply_ASM;
13414b9ad928SBarry Smith   pc->ops->applytranspose  = PCApplyTranspose_ASM;
13424b9ad928SBarry Smith   pc->ops->setup           = PCSetUp_ASM;
1343e91c6855SBarry Smith   pc->ops->reset           = PCReset_ASM;
13444b9ad928SBarry Smith   pc->ops->destroy         = PCDestroy_ASM;
13454b9ad928SBarry Smith   pc->ops->setfromoptions  = PCSetFromOptions_ASM;
13464b9ad928SBarry Smith   pc->ops->setuponblocks   = PCSetUpOnBlocks_ASM;
13474b9ad928SBarry Smith   pc->ops->view            = PCView_ASM;
13480a545947SLisandro Dalcin   pc->ops->applyrichardson = NULL;
13494b9ad928SBarry Smith 
13509566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCASMSetLocalSubdomains_C",PCASMSetLocalSubdomains_ASM));
13519566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCASMSetTotalSubdomains_C",PCASMSetTotalSubdomains_ASM));
13529566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCASMSetOverlap_C",PCASMSetOverlap_ASM));
13539566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCASMSetType_C",PCASMSetType_ASM));
13549566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCASMGetType_C",PCASMGetType_ASM));
13559566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCASMSetLocalType_C",PCASMSetLocalType_ASM));
13569566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCASMGetLocalType_C",PCASMGetLocalType_ASM));
13579566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCASMSetSortIndices_C",PCASMSetSortIndices_ASM));
13589566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCASMGetSubKSP_C",PCASMGetSubKSP_ASM));
13599566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCASMGetSubMatType_C",PCASMGetSubMatType_ASM));
13609566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCASMSetSubMatType_C",PCASMSetSubMatType_ASM));
13614b9ad928SBarry Smith   PetscFunctionReturn(0);
13624b9ad928SBarry Smith }
13634b9ad928SBarry Smith 
136492bb6962SLisandro Dalcin /*@C
136592bb6962SLisandro Dalcin    PCASMCreateSubdomains - Creates the index sets for the overlapping Schwarz
13663b8d980fSPierre Jolivet    preconditioner for any problem on a general grid.
136792bb6962SLisandro Dalcin 
136892bb6962SLisandro Dalcin    Collective
136992bb6962SLisandro Dalcin 
137092bb6962SLisandro Dalcin    Input Parameters:
137192bb6962SLisandro Dalcin +  A - The global matrix operator
137292bb6962SLisandro Dalcin -  n - the number of local blocks
137392bb6962SLisandro Dalcin 
137492bb6962SLisandro Dalcin    Output Parameters:
137592bb6962SLisandro Dalcin .  outis - the array of index sets defining the subdomains
137692bb6962SLisandro Dalcin 
137792bb6962SLisandro Dalcin    Level: advanced
137892bb6962SLisandro Dalcin 
13797d6bfa3bSBarry Smith    Note: this generates nonoverlapping subdomains; the PCASM will generate the overlap
13807d6bfa3bSBarry Smith     from these if you use PCASMSetLocalSubdomains()
13817d6bfa3bSBarry Smith 
13827d6bfa3bSBarry Smith     In the Fortran version you must provide the array outis[] already allocated of length n.
13837d6bfa3bSBarry Smith 
1384db781477SPatrick Sanan .seealso: `PCASMSetLocalSubdomains()`, `PCASMDestroySubdomains()`
138592bb6962SLisandro Dalcin @*/
13867087cfbeSBarry Smith PetscErrorCode  PCASMCreateSubdomains(Mat A, PetscInt n, IS* outis[])
138792bb6962SLisandro Dalcin {
138892bb6962SLisandro Dalcin   MatPartitioning mpart;
138992bb6962SLisandro Dalcin   const char      *prefix;
139092bb6962SLisandro Dalcin   PetscInt        i,j,rstart,rend,bs;
1391976e8c5aSLisandro Dalcin   PetscBool       hasop, isbaij = PETSC_FALSE,foundpart = PETSC_FALSE;
13920298fd71SBarry Smith   Mat             Ad     = NULL, adj;
139392bb6962SLisandro Dalcin   IS              ispart,isnumb,*is;
139492bb6962SLisandro Dalcin 
139592bb6962SLisandro Dalcin   PetscFunctionBegin;
13960700a824SBarry Smith   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
139792bb6962SLisandro Dalcin   PetscValidPointer(outis,3);
139863a3b9bcSJacob Faibussowitsch   PetscCheck(n >= 1,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"number of local blocks must be > 0, n = %" PetscInt_FMT,n);
139992bb6962SLisandro Dalcin 
140092bb6962SLisandro Dalcin   /* Get prefix, row distribution, and block size */
14019566063dSJacob Faibussowitsch   PetscCall(MatGetOptionsPrefix(A,&prefix));
14029566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(A,&rstart,&rend));
14039566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(A,&bs));
140463a3b9bcSJacob Faibussowitsch   PetscCheck(rstart/bs*bs == rstart && rend/bs*bs == rend,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"bad row distribution [%" PetscInt_FMT ",%" PetscInt_FMT ") for matrix block size %" PetscInt_FMT,rstart,rend,bs);
140565e19b50SBarry Smith 
140692bb6962SLisandro Dalcin   /* Get diagonal block from matrix if possible */
14079566063dSJacob Faibussowitsch   PetscCall(MatHasOperation(A,MATOP_GET_DIAGONAL_BLOCK,&hasop));
1408976e8c5aSLisandro Dalcin   if (hasop) {
14099566063dSJacob Faibussowitsch     PetscCall(MatGetDiagonalBlock(A,&Ad));
141092bb6962SLisandro Dalcin   }
141192bb6962SLisandro Dalcin   if (Ad) {
14129566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)Ad,MATSEQBAIJ,&isbaij));
14139566063dSJacob Faibussowitsch     if (!isbaij) PetscCall(PetscObjectBaseTypeCompare((PetscObject)Ad,MATSEQSBAIJ,&isbaij));
141492bb6962SLisandro Dalcin   }
141592bb6962SLisandro Dalcin   if (Ad && n > 1) {
1416ace3abfcSBarry Smith     PetscBool match,done;
141792bb6962SLisandro Dalcin     /* Try to setup a good matrix partitioning if available */
14189566063dSJacob Faibussowitsch     PetscCall(MatPartitioningCreate(PETSC_COMM_SELF,&mpart));
14199566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)mpart,prefix));
14209566063dSJacob Faibussowitsch     PetscCall(MatPartitioningSetFromOptions(mpart));
14219566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)mpart,MATPARTITIONINGCURRENT,&match));
142292bb6962SLisandro Dalcin     if (!match) {
14239566063dSJacob Faibussowitsch       PetscCall(PetscObjectTypeCompare((PetscObject)mpart,MATPARTITIONINGSQUARE,&match));
142492bb6962SLisandro Dalcin     }
142592bb6962SLisandro Dalcin     if (!match) { /* assume a "good" partitioner is available */
14261a83f524SJed Brown       PetscInt       na;
14271a83f524SJed Brown       const PetscInt *ia,*ja;
14289566063dSJacob Faibussowitsch       PetscCall(MatGetRowIJ(Ad,0,PETSC_TRUE,isbaij,&na,&ia,&ja,&done));
142992bb6962SLisandro Dalcin       if (done) {
143092bb6962SLisandro Dalcin         /* Build adjacency matrix by hand. Unfortunately a call to
143192bb6962SLisandro Dalcin            MatConvert(Ad,MATMPIADJ,MAT_INITIAL_MATRIX,&adj) will
143292bb6962SLisandro Dalcin            remove the block-aij structure and we cannot expect
143392bb6962SLisandro Dalcin            MatPartitioning to split vertices as we need */
14340a545947SLisandro Dalcin         PetscInt       i,j,len,nnz,cnt,*iia=NULL,*jja=NULL;
14351a83f524SJed Brown         const PetscInt *row;
143692bb6962SLisandro Dalcin         nnz = 0;
143792bb6962SLisandro Dalcin         for (i=0; i<na; i++) { /* count number of nonzeros */
143892bb6962SLisandro Dalcin           len = ia[i+1] - ia[i];
143992bb6962SLisandro Dalcin           row = ja + ia[i];
144092bb6962SLisandro Dalcin           for (j=0; j<len; j++) {
144192bb6962SLisandro Dalcin             if (row[j] == i) { /* don't count diagonal */
144292bb6962SLisandro Dalcin               len--; break;
144392bb6962SLisandro Dalcin             }
144492bb6962SLisandro Dalcin           }
144592bb6962SLisandro Dalcin           nnz += len;
144692bb6962SLisandro Dalcin         }
14479566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(na+1,&iia));
14489566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(nnz,&jja));
144992bb6962SLisandro Dalcin         nnz    = 0;
145092bb6962SLisandro Dalcin         iia[0] = 0;
145192bb6962SLisandro Dalcin         for (i=0; i<na; i++) { /* fill adjacency */
145292bb6962SLisandro Dalcin           cnt = 0;
145392bb6962SLisandro Dalcin           len = ia[i+1] - ia[i];
145492bb6962SLisandro Dalcin           row = ja + ia[i];
145592bb6962SLisandro Dalcin           for (j=0; j<len; j++) {
145692bb6962SLisandro Dalcin             if (row[j] != i) { /* if not diagonal */
145792bb6962SLisandro Dalcin               jja[nnz+cnt++] = row[j];
145892bb6962SLisandro Dalcin             }
145992bb6962SLisandro Dalcin           }
146092bb6962SLisandro Dalcin           nnz     += cnt;
146192bb6962SLisandro Dalcin           iia[i+1] = nnz;
146292bb6962SLisandro Dalcin         }
146392bb6962SLisandro Dalcin         /* Partitioning of the adjacency matrix */
14649566063dSJacob Faibussowitsch         PetscCall(MatCreateMPIAdj(PETSC_COMM_SELF,na,na,iia,jja,NULL,&adj));
14659566063dSJacob Faibussowitsch         PetscCall(MatPartitioningSetAdjacency(mpart,adj));
14669566063dSJacob Faibussowitsch         PetscCall(MatPartitioningSetNParts(mpart,n));
14679566063dSJacob Faibussowitsch         PetscCall(MatPartitioningApply(mpart,&ispart));
14689566063dSJacob Faibussowitsch         PetscCall(ISPartitioningToNumbering(ispart,&isnumb));
14699566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&adj));
147092bb6962SLisandro Dalcin         foundpart = PETSC_TRUE;
147192bb6962SLisandro Dalcin       }
14729566063dSJacob Faibussowitsch       PetscCall(MatRestoreRowIJ(Ad,0,PETSC_TRUE,isbaij,&na,&ia,&ja,&done));
147392bb6962SLisandro Dalcin     }
14749566063dSJacob Faibussowitsch     PetscCall(MatPartitioningDestroy(&mpart));
147592bb6962SLisandro Dalcin   }
147692bb6962SLisandro Dalcin 
14779566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n,&is));
147892bb6962SLisandro Dalcin   *outis = is;
147992bb6962SLisandro Dalcin 
148092bb6962SLisandro Dalcin   if (!foundpart) {
148192bb6962SLisandro Dalcin 
148292bb6962SLisandro Dalcin     /* Partitioning by contiguous chunks of rows */
148392bb6962SLisandro Dalcin 
148492bb6962SLisandro Dalcin     PetscInt mbs   = (rend-rstart)/bs;
148592bb6962SLisandro Dalcin     PetscInt start = rstart;
148692bb6962SLisandro Dalcin     for (i=0; i<n; i++) {
148792bb6962SLisandro Dalcin       PetscInt count = (mbs/n + ((mbs % n) > i)) * bs;
14889566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_SELF,count,start,1,&is[i]));
148992bb6962SLisandro Dalcin       start += count;
149092bb6962SLisandro Dalcin     }
149192bb6962SLisandro Dalcin 
149292bb6962SLisandro Dalcin   } else {
149392bb6962SLisandro Dalcin 
149492bb6962SLisandro Dalcin     /* Partitioning by adjacency of diagonal block  */
149592bb6962SLisandro Dalcin 
149692bb6962SLisandro Dalcin     const PetscInt *numbering;
149792bb6962SLisandro Dalcin     PetscInt       *count,nidx,*indices,*newidx,start=0;
149892bb6962SLisandro Dalcin     /* Get node count in each partition */
14999566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n,&count));
15009566063dSJacob Faibussowitsch     PetscCall(ISPartitioningCount(ispart,n,count));
150192bb6962SLisandro Dalcin     if (isbaij && bs > 1) { /* adjust for the block-aij case */
150292bb6962SLisandro Dalcin       for (i=0; i<n; i++) count[i] *= bs;
150392bb6962SLisandro Dalcin     }
150492bb6962SLisandro Dalcin     /* Build indices from node numbering */
15059566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(isnumb,&nidx));
15069566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nidx,&indices));
150792bb6962SLisandro Dalcin     for (i=0; i<nidx; i++) indices[i] = i; /* needs to be initialized */
15089566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(isnumb,&numbering));
15099566063dSJacob Faibussowitsch     PetscCall(PetscSortIntWithPermutation(nidx,numbering,indices));
15109566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(isnumb,&numbering));
151192bb6962SLisandro Dalcin     if (isbaij && bs > 1) { /* adjust for the block-aij case */
15129566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nidx*bs,&newidx));
15132fa5cd67SKarl Rupp       for (i=0; i<nidx; i++) {
15142fa5cd67SKarl Rupp         for (j=0; j<bs; j++) newidx[i*bs+j] = indices[i]*bs + j;
15152fa5cd67SKarl Rupp       }
15169566063dSJacob Faibussowitsch       PetscCall(PetscFree(indices));
151792bb6962SLisandro Dalcin       nidx   *= bs;
151892bb6962SLisandro Dalcin       indices = newidx;
151992bb6962SLisandro Dalcin     }
152092bb6962SLisandro Dalcin     /* Shift to get global indices */
152192bb6962SLisandro Dalcin     for (i=0; i<nidx; i++) indices[i] += rstart;
152292bb6962SLisandro Dalcin 
152392bb6962SLisandro Dalcin     /* Build the index sets for each block */
152492bb6962SLisandro Dalcin     for (i=0; i<n; i++) {
15259566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PETSC_COMM_SELF,count[i],&indices[start],PETSC_COPY_VALUES,&is[i]));
15269566063dSJacob Faibussowitsch       PetscCall(ISSort(is[i]));
152792bb6962SLisandro Dalcin       start += count[i];
152892bb6962SLisandro Dalcin     }
152992bb6962SLisandro Dalcin 
15309566063dSJacob Faibussowitsch     PetscCall(PetscFree(count));
15319566063dSJacob Faibussowitsch     PetscCall(PetscFree(indices));
15329566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&isnumb));
15339566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&ispart));
153492bb6962SLisandro Dalcin 
153592bb6962SLisandro Dalcin   }
153692bb6962SLisandro Dalcin   PetscFunctionReturn(0);
153792bb6962SLisandro Dalcin }
153892bb6962SLisandro Dalcin 
153992bb6962SLisandro Dalcin /*@C
154092bb6962SLisandro Dalcin    PCASMDestroySubdomains - Destroys the index sets created with
154192bb6962SLisandro Dalcin    PCASMCreateSubdomains(). Should be called after setting subdomains
154292bb6962SLisandro Dalcin    with PCASMSetLocalSubdomains().
154392bb6962SLisandro Dalcin 
154492bb6962SLisandro Dalcin    Collective
154592bb6962SLisandro Dalcin 
154692bb6962SLisandro Dalcin    Input Parameters:
154792bb6962SLisandro Dalcin +  n - the number of index sets
15482b691e39SMatthew Knepley .  is - the array of index sets
15490298fd71SBarry Smith -  is_local - the array of local index sets, can be NULL
155092bb6962SLisandro Dalcin 
155192bb6962SLisandro Dalcin    Level: advanced
155292bb6962SLisandro Dalcin 
1553db781477SPatrick Sanan .seealso: `PCASMCreateSubdomains()`, `PCASMSetLocalSubdomains()`
155492bb6962SLisandro Dalcin @*/
15557087cfbeSBarry Smith PetscErrorCode  PCASMDestroySubdomains(PetscInt n, IS is[], IS is_local[])
155692bb6962SLisandro Dalcin {
155792bb6962SLisandro Dalcin   PetscInt       i;
15585fd66863SKarl Rupp 
155992bb6962SLisandro Dalcin   PetscFunctionBegin;
1560a35b7b57SDmitry Karpeev   if (n <= 0) PetscFunctionReturn(0);
1561a35b7b57SDmitry Karpeev   if (is) {
156292bb6962SLisandro Dalcin     PetscValidPointer(is,2);
15639566063dSJacob Faibussowitsch     for (i=0; i<n; i++) PetscCall(ISDestroy(&is[i]));
15649566063dSJacob Faibussowitsch     PetscCall(PetscFree(is));
1565a35b7b57SDmitry Karpeev   }
15662b691e39SMatthew Knepley   if (is_local) {
15672b691e39SMatthew Knepley     PetscValidPointer(is_local,3);
15689566063dSJacob Faibussowitsch     for (i=0; i<n; i++) PetscCall(ISDestroy(&is_local[i]));
15699566063dSJacob Faibussowitsch     PetscCall(PetscFree(is_local));
15702b691e39SMatthew Knepley   }
157192bb6962SLisandro Dalcin   PetscFunctionReturn(0);
157292bb6962SLisandro Dalcin }
157392bb6962SLisandro Dalcin 
15744b9ad928SBarry Smith /*@
15754b9ad928SBarry Smith    PCASMCreateSubdomains2D - Creates the index sets for the overlapping Schwarz
15764b9ad928SBarry Smith    preconditioner for a two-dimensional problem on a regular grid.
15774b9ad928SBarry Smith 
15784b9ad928SBarry Smith    Not Collective
15794b9ad928SBarry Smith 
15804b9ad928SBarry Smith    Input Parameters:
15816b867d5aSJose E. Roman +  m   - the number of mesh points in the x direction
15826b867d5aSJose E. Roman .  n   - the number of mesh points in the y direction
15836b867d5aSJose E. Roman .  M   - the number of subdomains in the x direction
15846b867d5aSJose E. Roman .  N   - the number of subdomains in the y direction
15854b9ad928SBarry Smith .  dof - degrees of freedom per node
15864b9ad928SBarry Smith -  overlap - overlap in mesh lines
15874b9ad928SBarry Smith 
15884b9ad928SBarry Smith    Output Parameters:
15894b9ad928SBarry Smith +  Nsub - the number of subdomains created
15903d03bb48SJed Brown .  is - array of index sets defining overlapping (if overlap > 0) subdomains
15913d03bb48SJed Brown -  is_local - array of index sets defining non-overlapping subdomains
15924b9ad928SBarry Smith 
15934b9ad928SBarry Smith    Note:
15944b9ad928SBarry Smith    Presently PCAMSCreateSubdomains2d() is valid only for sequential
15954b9ad928SBarry Smith    preconditioners.  More general related routines are
15964b9ad928SBarry Smith    PCASMSetTotalSubdomains() and PCASMSetLocalSubdomains().
15974b9ad928SBarry Smith 
15984b9ad928SBarry Smith    Level: advanced
15994b9ad928SBarry Smith 
1600db781477SPatrick Sanan .seealso: `PCASMSetTotalSubdomains()`, `PCASMSetLocalSubdomains()`, `PCASMGetSubKSP()`,
1601db781477SPatrick Sanan           `PCASMSetOverlap()`
16024b9ad928SBarry Smith @*/
16037087cfbeSBarry Smith PetscErrorCode  PCASMCreateSubdomains2D(PetscInt m,PetscInt n,PetscInt M,PetscInt N,PetscInt dof,PetscInt overlap,PetscInt *Nsub,IS **is,IS **is_local)
16044b9ad928SBarry Smith {
16053d03bb48SJed Brown   PetscInt       i,j,height,width,ystart,xstart,yleft,yright,xleft,xright,loc_outer;
160613f74950SBarry Smith   PetscInt       nidx,*idx,loc,ii,jj,count;
16074b9ad928SBarry Smith 
16084b9ad928SBarry Smith   PetscFunctionBegin;
16097827d75bSBarry Smith   PetscCheck(dof == 1,PETSC_COMM_SELF,PETSC_ERR_SUP,"dof must be 1");
16104b9ad928SBarry Smith 
16114b9ad928SBarry Smith   *Nsub     = N*M;
16129566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(*Nsub,is));
16139566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(*Nsub,is_local));
16144b9ad928SBarry Smith   ystart    = 0;
16153d03bb48SJed Brown   loc_outer = 0;
16164b9ad928SBarry Smith   for (i=0; i<N; i++) {
16174b9ad928SBarry Smith     height = n/N + ((n % N) > i); /* height of subdomain */
16187827d75bSBarry Smith     PetscCheck(height >= 2,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Too many N subdomains for mesh dimension n");
16194b9ad928SBarry Smith     yleft  = ystart - overlap; if (yleft < 0) yleft = 0;
16204b9ad928SBarry Smith     yright = ystart + height + overlap; if (yright > n) yright = n;
16214b9ad928SBarry Smith     xstart = 0;
16224b9ad928SBarry Smith     for (j=0; j<M; j++) {
16234b9ad928SBarry Smith       width = m/M + ((m % M) > j); /* width of subdomain */
16247827d75bSBarry Smith       PetscCheck(width >= 2,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Too many M subdomains for mesh dimension m");
16254b9ad928SBarry Smith       xleft  = xstart - overlap; if (xleft < 0) xleft = 0;
16264b9ad928SBarry Smith       xright = xstart + width + overlap; if (xright > m) xright = m;
16274b9ad928SBarry Smith       nidx   = (xright - xleft)*(yright - yleft);
16289566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nidx,&idx));
16294b9ad928SBarry Smith       loc    = 0;
16304b9ad928SBarry Smith       for (ii=yleft; ii<yright; ii++) {
16314b9ad928SBarry Smith         count = m*ii + xleft;
16322fa5cd67SKarl Rupp         for (jj=xleft; jj<xright; jj++) idx[loc++] = count++;
16334b9ad928SBarry Smith       }
16349566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PETSC_COMM_SELF,nidx,idx,PETSC_COPY_VALUES,(*is)+loc_outer));
16353d03bb48SJed Brown       if (overlap == 0) {
16369566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)(*is)[loc_outer]));
16372fa5cd67SKarl Rupp 
16383d03bb48SJed Brown         (*is_local)[loc_outer] = (*is)[loc_outer];
16393d03bb48SJed Brown       } else {
16403d03bb48SJed Brown         for (loc=0,ii=ystart; ii<ystart+height; ii++) {
16413d03bb48SJed Brown           for (jj=xstart; jj<xstart+width; jj++) {
16423d03bb48SJed Brown             idx[loc++] = m*ii + jj;
16433d03bb48SJed Brown           }
16443d03bb48SJed Brown         }
16459566063dSJacob Faibussowitsch         PetscCall(ISCreateGeneral(PETSC_COMM_SELF,loc,idx,PETSC_COPY_VALUES,*is_local+loc_outer));
16463d03bb48SJed Brown       }
16479566063dSJacob Faibussowitsch       PetscCall(PetscFree(idx));
16484b9ad928SBarry Smith       xstart += width;
16493d03bb48SJed Brown       loc_outer++;
16504b9ad928SBarry Smith     }
16514b9ad928SBarry Smith     ystart += height;
16524b9ad928SBarry Smith   }
16539566063dSJacob Faibussowitsch   for (i=0; i<*Nsub; i++) PetscCall(ISSort((*is)[i]));
16544b9ad928SBarry Smith   PetscFunctionReturn(0);
16554b9ad928SBarry Smith }
16564b9ad928SBarry Smith 
16574b9ad928SBarry Smith /*@C
16584b9ad928SBarry Smith     PCASMGetLocalSubdomains - Gets the local subdomains (for this processor
16594b9ad928SBarry Smith     only) for the additive Schwarz preconditioner.
16604b9ad928SBarry Smith 
1661ad4df100SBarry Smith     Not Collective
16624b9ad928SBarry Smith 
16634b9ad928SBarry Smith     Input Parameter:
16644b9ad928SBarry Smith .   pc - the preconditioner context
16654b9ad928SBarry Smith 
16664b9ad928SBarry Smith     Output Parameters:
1667f17a6784SPierre Jolivet +   n - if requested, the number of subdomains for this processor (default value = 1)
1668f17a6784SPierre Jolivet .   is - if requested, the index sets that define the subdomains for this processor
1669f17a6784SPierre Jolivet -   is_local - if requested, the index sets that define the local part of the subdomains for this processor (can be NULL)
16704b9ad928SBarry Smith 
16714b9ad928SBarry Smith     Notes:
16724b9ad928SBarry Smith     The IS numbering is in the parallel, global numbering of the vector.
16734b9ad928SBarry Smith 
16744b9ad928SBarry Smith     Level: advanced
16754b9ad928SBarry Smith 
1676db781477SPatrick Sanan .seealso: `PCASMSetTotalSubdomains()`, `PCASMSetOverlap()`, `PCASMGetSubKSP()`,
1677db781477SPatrick Sanan           `PCASMCreateSubdomains2D()`, `PCASMSetLocalSubdomains()`, `PCASMGetLocalSubmatrices()`
16784b9ad928SBarry Smith @*/
16797087cfbeSBarry Smith PetscErrorCode  PCASMGetLocalSubdomains(PC pc,PetscInt *n,IS *is[],IS *is_local[])
16804b9ad928SBarry Smith {
16812a808120SBarry Smith   PC_ASM         *osm = (PC_ASM*)pc->data;
1682ace3abfcSBarry Smith   PetscBool      match;
16834b9ad928SBarry Smith 
16844b9ad928SBarry Smith   PetscFunctionBegin;
16850700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1686f17a6784SPierre Jolivet   if (n) PetscValidIntPointer(n,2);
168792bb6962SLisandro Dalcin   if (is) PetscValidPointer(is,3);
1688f17a6784SPierre Jolivet   if (is_local) PetscValidPointer(is_local,4);
16899566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc,PCASM,&match));
169028b400f6SJacob Faibussowitsch   PetscCheck(match,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"PC is not a PCASM");
16914b9ad928SBarry Smith   if (n) *n = osm->n_local_true;
16924b9ad928SBarry Smith   if (is) *is = osm->is;
16932b691e39SMatthew Knepley   if (is_local) *is_local = osm->is_local;
16944b9ad928SBarry Smith   PetscFunctionReturn(0);
16954b9ad928SBarry Smith }
16964b9ad928SBarry Smith 
16974b9ad928SBarry Smith /*@C
16984b9ad928SBarry Smith     PCASMGetLocalSubmatrices - Gets the local submatrices (for this processor
16994b9ad928SBarry Smith     only) for the additive Schwarz preconditioner.
17004b9ad928SBarry Smith 
1701ad4df100SBarry Smith     Not Collective
17024b9ad928SBarry Smith 
17034b9ad928SBarry Smith     Input Parameter:
17044b9ad928SBarry Smith .   pc - the preconditioner context
17054b9ad928SBarry Smith 
17064b9ad928SBarry Smith     Output Parameters:
1707f17a6784SPierre Jolivet +   n - if requested, the number of matrices for this processor (default value = 1)
1708f17a6784SPierre Jolivet -   mat - if requested, the matrices
17094b9ad928SBarry Smith 
17104b9ad928SBarry Smith     Level: advanced
17114b9ad928SBarry Smith 
171295452b02SPatrick Sanan     Notes:
171334a84908Sprj-     Call after PCSetUp() (or KSPSetUp()) but before PCApply() and before PCSetUpOnBlocks())
1714cf739d55SBarry Smith 
171534a84908Sprj-            Usually one would use PCSetModifySubMatrices() to change the submatrices in building the preconditioner.
1716cf739d55SBarry Smith 
1717db781477SPatrick Sanan .seealso: `PCASMSetTotalSubdomains()`, `PCASMSetOverlap()`, `PCASMGetSubKSP()`,
1718db781477SPatrick Sanan           `PCASMCreateSubdomains2D()`, `PCASMSetLocalSubdomains()`, `PCASMGetLocalSubdomains()`, `PCSetModifySubMatrices()`
17194b9ad928SBarry Smith @*/
17207087cfbeSBarry Smith PetscErrorCode  PCASMGetLocalSubmatrices(PC pc,PetscInt *n,Mat *mat[])
17214b9ad928SBarry Smith {
17224b9ad928SBarry Smith   PC_ASM         *osm;
1723ace3abfcSBarry Smith   PetscBool      match;
17244b9ad928SBarry Smith 
17254b9ad928SBarry Smith   PetscFunctionBegin;
17260700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1727f17a6784SPierre Jolivet   if (n) PetscValidIntPointer(n,2);
172892bb6962SLisandro Dalcin   if (mat) PetscValidPointer(mat,3);
172928b400f6SJacob Faibussowitsch   PetscCheck(pc->setupcalled,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must call after KSPSetUp() or PCSetUp().");
17309566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc,PCASM,&match));
173192bb6962SLisandro Dalcin   if (!match) {
173292bb6962SLisandro Dalcin     if (n) *n = 0;
17330298fd71SBarry Smith     if (mat) *mat = NULL;
173492bb6962SLisandro Dalcin   } else {
17354b9ad928SBarry Smith     osm = (PC_ASM*)pc->data;
17364b9ad928SBarry Smith     if (n) *n = osm->n_local_true;
17374b9ad928SBarry Smith     if (mat) *mat = osm->pmat;
173892bb6962SLisandro Dalcin   }
17394b9ad928SBarry Smith   PetscFunctionReturn(0);
17404b9ad928SBarry Smith }
1741d709ea83SDmitry Karpeev 
1742d709ea83SDmitry Karpeev /*@
1743d709ea83SDmitry Karpeev     PCASMSetDMSubdomains - Indicates whether to use DMCreateDomainDecomposition() to define the subdomains, whenever possible.
1744f1ee410cSBarry Smith 
1745d709ea83SDmitry Karpeev     Logically Collective
1746d709ea83SDmitry Karpeev 
1747d8d19677SJose E. Roman     Input Parameters:
1748d709ea83SDmitry Karpeev +   pc  - the preconditioner
1749d709ea83SDmitry Karpeev -   flg - boolean indicating whether to use subdomains defined by the DM
1750d709ea83SDmitry Karpeev 
1751d709ea83SDmitry Karpeev     Options Database Key:
1752147403d9SBarry Smith .   -pc_asm_dm_subdomains <bool> - use subdomains defined by the DM
1753d709ea83SDmitry Karpeev 
1754d709ea83SDmitry Karpeev     Level: intermediate
1755d709ea83SDmitry Karpeev 
1756d709ea83SDmitry Karpeev     Notes:
1757d709ea83SDmitry Karpeev     PCASMSetTotalSubdomains() and PCASMSetOverlap() take precedence over PCASMSetDMSubdomains(),
1758d709ea83SDmitry Karpeev     so setting either of the first two effectively turns the latter off.
1759d709ea83SDmitry Karpeev 
1760db781477SPatrick Sanan .seealso: `PCASMGetDMSubdomains()`, `PCASMSetTotalSubdomains()`, `PCASMSetOverlap()`
1761db781477SPatrick Sanan           `PCASMCreateSubdomains2D()`, `PCASMSetLocalSubdomains()`, `PCASMGetLocalSubdomains()`
1762d709ea83SDmitry Karpeev @*/
1763d709ea83SDmitry Karpeev PetscErrorCode  PCASMSetDMSubdomains(PC pc,PetscBool flg)
1764d709ea83SDmitry Karpeev {
1765d709ea83SDmitry Karpeev   PC_ASM         *osm = (PC_ASM*)pc->data;
1766d709ea83SDmitry Karpeev   PetscBool      match;
1767d709ea83SDmitry Karpeev 
1768d709ea83SDmitry Karpeev   PetscFunctionBegin;
1769d709ea83SDmitry Karpeev   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1770d709ea83SDmitry Karpeev   PetscValidLogicalCollectiveBool(pc,flg,2);
177128b400f6SJacob Faibussowitsch   PetscCheck(!pc->setupcalled,((PetscObject)pc)->comm,PETSC_ERR_ARG_WRONGSTATE,"Not for a setup PC.");
17729566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc,PCASM,&match));
1773d709ea83SDmitry Karpeev   if (match) {
1774d709ea83SDmitry Karpeev     osm->dm_subdomains = flg;
1775d709ea83SDmitry Karpeev   }
1776d709ea83SDmitry Karpeev   PetscFunctionReturn(0);
1777d709ea83SDmitry Karpeev }
1778d709ea83SDmitry Karpeev 
1779d709ea83SDmitry Karpeev /*@
1780d709ea83SDmitry Karpeev     PCASMGetDMSubdomains - Returns flag indicating whether to use DMCreateDomainDecomposition() to define the subdomains, whenever possible.
1781d709ea83SDmitry Karpeev     Not Collective
1782d709ea83SDmitry Karpeev 
1783d709ea83SDmitry Karpeev     Input Parameter:
1784d709ea83SDmitry Karpeev .   pc  - the preconditioner
1785d709ea83SDmitry Karpeev 
1786d709ea83SDmitry Karpeev     Output Parameter:
1787d709ea83SDmitry Karpeev .   flg - boolean indicating whether to use subdomains defined by the DM
1788d709ea83SDmitry Karpeev 
1789d709ea83SDmitry Karpeev     Level: intermediate
1790d709ea83SDmitry Karpeev 
1791db781477SPatrick Sanan .seealso: `PCASMSetDMSubdomains()`, `PCASMSetTotalSubdomains()`, `PCASMSetOverlap()`
1792db781477SPatrick Sanan           `PCASMCreateSubdomains2D()`, `PCASMSetLocalSubdomains()`, `PCASMGetLocalSubdomains()`
1793d709ea83SDmitry Karpeev @*/
1794d709ea83SDmitry Karpeev PetscErrorCode  PCASMGetDMSubdomains(PC pc,PetscBool* flg)
1795d709ea83SDmitry Karpeev {
1796d709ea83SDmitry Karpeev   PC_ASM         *osm = (PC_ASM*)pc->data;
1797d709ea83SDmitry Karpeev   PetscBool      match;
1798d709ea83SDmitry Karpeev 
1799d709ea83SDmitry Karpeev   PetscFunctionBegin;
1800d709ea83SDmitry Karpeev   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1801534a8f05SLisandro Dalcin   PetscValidBoolPointer(flg,2);
18029566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc,PCASM,&match));
180356ea09ceSStefano Zampini   if (match) *flg = osm->dm_subdomains;
180456ea09ceSStefano Zampini   else *flg = PETSC_FALSE;
1805d709ea83SDmitry Karpeev   PetscFunctionReturn(0);
1806d709ea83SDmitry Karpeev }
180780ec0b7dSPatrick Sanan 
180880ec0b7dSPatrick Sanan /*@
180980ec0b7dSPatrick Sanan      PCASMGetSubMatType - Gets the matrix type used for ASM subsolves, as a string.
181080ec0b7dSPatrick Sanan 
181180ec0b7dSPatrick Sanan    Not Collective
181280ec0b7dSPatrick Sanan 
181380ec0b7dSPatrick Sanan    Input Parameter:
181480ec0b7dSPatrick Sanan .  pc - the PC
181580ec0b7dSPatrick Sanan 
181680ec0b7dSPatrick Sanan    Output Parameter:
1817f1ee410cSBarry Smith .  -pc_asm_sub_mat_type - name of matrix type
181880ec0b7dSPatrick Sanan 
181980ec0b7dSPatrick Sanan    Level: advanced
182080ec0b7dSPatrick Sanan 
1821db781477SPatrick Sanan .seealso: `PCASMSetSubMatType()`, `PCASM`, `PCSetType()`, `VecSetType()`, `MatType`, `Mat`
182280ec0b7dSPatrick Sanan @*/
182356ea09ceSStefano Zampini PetscErrorCode  PCASMGetSubMatType(PC pc,MatType *sub_mat_type)
182456ea09ceSStefano Zampini {
182556ea09ceSStefano Zampini   PetscFunctionBegin;
182656ea09ceSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1827cac4c232SBarry Smith   PetscTryMethod(pc,"PCASMGetSubMatType_C",(PC,MatType*),(pc,sub_mat_type));
182880ec0b7dSPatrick Sanan   PetscFunctionReturn(0);
182980ec0b7dSPatrick Sanan }
183080ec0b7dSPatrick Sanan 
183180ec0b7dSPatrick Sanan /*@
183280ec0b7dSPatrick Sanan      PCASMSetSubMatType - Set the type of matrix used for ASM subsolves
183380ec0b7dSPatrick Sanan 
183480ec0b7dSPatrick Sanan    Collective on Mat
183580ec0b7dSPatrick Sanan 
183680ec0b7dSPatrick Sanan    Input Parameters:
183780ec0b7dSPatrick Sanan +  pc             - the PC object
183880ec0b7dSPatrick Sanan -  sub_mat_type   - matrix type
183980ec0b7dSPatrick Sanan 
184080ec0b7dSPatrick Sanan    Options Database Key:
184180ec0b7dSPatrick Sanan .  -pc_asm_sub_mat_type  <sub_mat_type> - Sets the matrix type used for subsolves, for example, seqaijviennacl. If you specify a base name like aijviennacl, the corresponding sequential type is assumed.
184280ec0b7dSPatrick Sanan 
184380ec0b7dSPatrick Sanan    Notes:
184480ec0b7dSPatrick Sanan    See "${PETSC_DIR}/include/petscmat.h" for available types
184580ec0b7dSPatrick Sanan 
184680ec0b7dSPatrick Sanan   Level: advanced
184780ec0b7dSPatrick Sanan 
1848db781477SPatrick Sanan .seealso: `PCASMGetSubMatType()`, `PCASM`, `PCSetType()`, `VecSetType()`, `MatType`, `Mat`
184980ec0b7dSPatrick Sanan @*/
185080ec0b7dSPatrick Sanan PetscErrorCode PCASMSetSubMatType(PC pc,MatType sub_mat_type)
185180ec0b7dSPatrick Sanan {
185256ea09ceSStefano Zampini   PetscFunctionBegin;
185356ea09ceSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1854cac4c232SBarry Smith   PetscTryMethod(pc,"PCASMSetSubMatType_C",(PC,MatType),(pc,sub_mat_type));
185580ec0b7dSPatrick Sanan   PetscFunctionReturn(0);
185680ec0b7dSPatrick Sanan }
1857