xref: /petsc/src/snes/impls/multiblock/multiblock.c (revision 28b400f66ebc7ae0049166a2294dfcd3df27e64b)
1af0996ceSBarry Smith #include <petsc/private/snesimpl.h> /*I "petscsnes.h" I*/
2b665c654SMatthew G Knepley #include <petscdmcomposite.h>
3c7543cceSMatthew G Knepley 
4c7543cceSMatthew G Knepley typedef struct _BlockDesc *BlockDesc;
5c7543cceSMatthew G Knepley struct _BlockDesc {
6c7543cceSMatthew G Knepley   char       *name;     /* Block name */
7c7543cceSMatthew G Knepley   PetscInt   nfields;   /* If block is defined on a DA, the number of DA fields */
8c7543cceSMatthew G Knepley   PetscInt   *fields;   /* If block is defined on a DA, the list of DA fields */
9c7543cceSMatthew G Knepley   IS         is;        /* Index sets defining the block */
10c7543cceSMatthew G Knepley   VecScatter sctx;      /* Scatter mapping global Vec to blockVec */
11c7543cceSMatthew G Knepley   SNES       snes;      /* Solver for this block */
12c7543cceSMatthew G Knepley   Vec        x;
13c7543cceSMatthew G Knepley   BlockDesc  next, previous;
14c7543cceSMatthew G Knepley };
15c7543cceSMatthew G Knepley 
16c7543cceSMatthew G Knepley typedef struct {
17c7543cceSMatthew G Knepley   PetscBool       issetup;       /* Flag is true after the all ISs and operators have been defined */
18c7543cceSMatthew G Knepley   PetscBool       defined;       /* Flag is true after the blocks have been defined, to prevent more blocks from being added */
19c7543cceSMatthew G Knepley   PetscBool       defaultblocks; /* Flag is true for a system with a set of 'k' scalar fields with the same layout (and bs = k) */
20c7543cceSMatthew G Knepley   PetscInt        numBlocks;     /* Number of blocks (can be fields, domains, etc.) */
21c7543cceSMatthew G Knepley   PetscInt        bs;            /* Block size for IS, Vec and Mat structures */
22c7543cceSMatthew G Knepley   PCCompositeType type;          /* Solver combination method (additive, multiplicative, etc.) */
23c7543cceSMatthew G Knepley   BlockDesc       blocks;        /* Linked list of block descriptors */
24c7543cceSMatthew G Knepley } SNES_Multiblock;
25c7543cceSMatthew G Knepley 
26c7543cceSMatthew G Knepley PetscErrorCode SNESReset_Multiblock(SNES snes)
27c7543cceSMatthew G Knepley {
28c7543cceSMatthew G Knepley   SNES_Multiblock *mb    = (SNES_Multiblock*) snes->data;
29c7543cceSMatthew G Knepley   BlockDesc       blocks = mb->blocks, next;
30c7543cceSMatthew G Knepley 
31c7543cceSMatthew G Knepley   PetscFunctionBegin;
32c7543cceSMatthew G Knepley   while (blocks) {
335f80ce2aSJacob Faibussowitsch     CHKERRQ(SNESReset(blocks->snes));
340c74a584SJed Brown #if 0
355f80ce2aSJacob Faibussowitsch     CHKERRQ(VecDestroy(&blocks->x));
360c74a584SJed Brown #endif
375f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterDestroy(&blocks->sctx));
385f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&blocks->is));
39c7543cceSMatthew G Knepley     next   = blocks->next;
40c7543cceSMatthew G Knepley     blocks = next;
41c7543cceSMatthew G Knepley   }
42c7543cceSMatthew G Knepley   PetscFunctionReturn(0);
43c7543cceSMatthew G Knepley }
44c7543cceSMatthew G Knepley 
45c7543cceSMatthew G Knepley /*
46c7543cceSMatthew G Knepley   SNESDestroy_Multiblock - Destroys the private SNES_Multiblock context that was created with SNESCreate_Multiblock().
47c7543cceSMatthew G Knepley 
48c7543cceSMatthew G Knepley   Input Parameter:
49c7543cceSMatthew G Knepley . snes - the SNES context
50c7543cceSMatthew G Knepley 
51c7543cceSMatthew G Knepley   Application Interface Routine: SNESDestroy()
52c7543cceSMatthew G Knepley */
53c7543cceSMatthew G Knepley PetscErrorCode SNESDestroy_Multiblock(SNES snes)
54c7543cceSMatthew G Knepley {
55c7543cceSMatthew G Knepley   SNES_Multiblock *mb    = (SNES_Multiblock*) snes->data;
56c7543cceSMatthew G Knepley   BlockDesc       blocks = mb->blocks, next;
57c7543cceSMatthew G Knepley 
58c7543cceSMatthew G Knepley   PetscFunctionBegin;
595f80ce2aSJacob Faibussowitsch   CHKERRQ(SNESReset_Multiblock(snes));
60c7543cceSMatthew G Knepley   while (blocks) {
61c7543cceSMatthew G Knepley     next   = blocks->next;
625f80ce2aSJacob Faibussowitsch     CHKERRQ(SNESDestroy(&blocks->snes));
635f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(blocks->name));
645f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(blocks->fields));
655f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(blocks));
66c7543cceSMatthew G Knepley     blocks = next;
67c7543cceSMatthew G Knepley   }
685f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(snes->data));
69c7543cceSMatthew G Knepley   PetscFunctionReturn(0);
70c7543cceSMatthew G Knepley }
71c7543cceSMatthew G Knepley 
72c7543cceSMatthew G Knepley /* Precondition: blocksize is set to a meaningful value */
73b665c654SMatthew G Knepley static PetscErrorCode SNESMultiblockSetFieldsRuntime_Private(SNES snes)
74c7543cceSMatthew G Knepley {
75c7543cceSMatthew G Knepley   SNES_Multiblock *mb = (SNES_Multiblock*) snes->data;
76c7543cceSMatthew G Knepley   PetscInt        *ifields;
77c7543cceSMatthew G Knepley   PetscInt        i, nfields;
78c7543cceSMatthew G Knepley   PetscBool       flg = PETSC_TRUE;
79c7543cceSMatthew G Knepley   char            optionname[128], name[8];
80c7543cceSMatthew G Knepley 
81c7543cceSMatthew G Knepley   PetscFunctionBegin;
825f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(mb->bs, &ifields));
83c7543cceSMatthew G Knepley   for (i = 0;; ++i) {
845f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSNPrintf(name, sizeof(name), "%D", i));
855f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSNPrintf(optionname, sizeof(optionname), "-snes_multiblock_%D_fields", i));
86c7543cceSMatthew G Knepley     nfields = mb->bs;
875f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscOptionsGetIntArray(NULL,((PetscObject) snes)->prefix, optionname, ifields, &nfields, &flg));
88c7543cceSMatthew G Knepley     if (!flg) break;
89*28b400f6SJacob Faibussowitsch     PetscCheck(nfields,PETSC_COMM_SELF, PETSC_ERR_USER, "Cannot list zero fields");
905f80ce2aSJacob Faibussowitsch     CHKERRQ(SNESMultiblockSetFields(snes, name, nfields, ifields));
91c7543cceSMatthew G Knepley   }
92c7543cceSMatthew G Knepley   if (i > 0) {
93c7543cceSMatthew G Knepley     /* Makes command-line setting of blocks take precedence over setting them in code.
94c7543cceSMatthew G Knepley        Otherwise subsequent calls to SNESMultiblockSetIS() or SNESMultiblockSetFields() would
95c7543cceSMatthew G Knepley        create new blocks, which would probably not be what the user wanted. */
96c7543cceSMatthew G Knepley     mb->defined = PETSC_TRUE;
97c7543cceSMatthew G Knepley   }
985f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(ifields));
99c7543cceSMatthew G Knepley   PetscFunctionReturn(0);
100c7543cceSMatthew G Knepley }
101c7543cceSMatthew G Knepley 
102c7543cceSMatthew G Knepley static PetscErrorCode SNESMultiblockSetDefaults(SNES snes)
103c7543cceSMatthew G Knepley {
104c7543cceSMatthew G Knepley   SNES_Multiblock *mb    = (SNES_Multiblock*) snes->data;
105c7543cceSMatthew G Knepley   BlockDesc       blocks = mb->blocks;
106c7543cceSMatthew G Knepley   PetscInt        i;
107c7543cceSMatthew G Knepley 
108c7543cceSMatthew G Knepley   PetscFunctionBegin;
109c7543cceSMatthew G Knepley   if (!blocks) {
110c7543cceSMatthew G Knepley     if (snes->dm) {
111c7543cceSMatthew G Knepley       PetscBool dmcomposite;
112c7543cceSMatthew G Knepley 
1135f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscObjectTypeCompare((PetscObject) snes->dm, DMCOMPOSITE, &dmcomposite));
114c7543cceSMatthew G Knepley       if (dmcomposite) {
115c7543cceSMatthew G Knepley         PetscInt nDM;
116c7543cceSMatthew G Knepley         IS       *fields;
117c7543cceSMatthew G Knepley 
1185f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscInfo(snes,"Setting up physics based multiblock solver using the embedded DM\n"));
1195f80ce2aSJacob Faibussowitsch         CHKERRQ(DMCompositeGetNumberDM(snes->dm, &nDM));
1205f80ce2aSJacob Faibussowitsch         CHKERRQ(DMCompositeGetGlobalISs(snes->dm, &fields));
121c7543cceSMatthew G Knepley         for (i = 0; i < nDM; ++i) {
122c7543cceSMatthew G Knepley           char name[8];
123c7543cceSMatthew G Knepley 
1245f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscSNPrintf(name, sizeof(name), "%D", i));
1255f80ce2aSJacob Faibussowitsch           CHKERRQ(SNESMultiblockSetIS(snes, name, fields[i]));
1265f80ce2aSJacob Faibussowitsch           CHKERRQ(ISDestroy(&fields[i]));
127c7543cceSMatthew G Knepley         }
1285f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscFree(fields));
129c7543cceSMatthew G Knepley       }
130c7543cceSMatthew G Knepley     } else {
131c7543cceSMatthew G Knepley       PetscBool flg    = PETSC_FALSE;
132c7543cceSMatthew G Knepley       PetscBool stokes = PETSC_FALSE;
133c7543cceSMatthew G Knepley 
134c7543cceSMatthew G Knepley       if (mb->bs <= 0) {
135b665c654SMatthew G Knepley         if (snes->jacobian_pre) {
1365f80ce2aSJacob Faibussowitsch           CHKERRQ(MatGetBlockSize(snes->jacobian_pre, &mb->bs));
1371aa26658SKarl Rupp         } else mb->bs = 1;
138c7543cceSMatthew G Knepley       }
139c7543cceSMatthew G Knepley 
1405f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscOptionsGetBool(NULL,((PetscObject) snes)->prefix, "-snes_multiblock_default", &flg, NULL));
1415f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscOptionsGetBool(NULL,((PetscObject) snes)->prefix, "-snes_multiblock_detect_saddle_point", &stokes, NULL));
142c7543cceSMatthew G Knepley       if (stokes) {
143c7543cceSMatthew G Knepley         IS       zerodiags, rest;
144c7543cceSMatthew G Knepley         PetscInt nmin, nmax;
145c7543cceSMatthew G Knepley 
1465f80ce2aSJacob Faibussowitsch         CHKERRQ(MatGetOwnershipRange(snes->jacobian_pre, &nmin, &nmax));
1475f80ce2aSJacob Faibussowitsch         CHKERRQ(MatFindZeroDiagonals(snes->jacobian_pre, &zerodiags));
1485f80ce2aSJacob Faibussowitsch         CHKERRQ(ISComplement(zerodiags, nmin, nmax, &rest));
1495f80ce2aSJacob Faibussowitsch         CHKERRQ(SNESMultiblockSetIS(snes, "0", rest));
1505f80ce2aSJacob Faibussowitsch         CHKERRQ(SNESMultiblockSetIS(snes, "1", zerodiags));
1515f80ce2aSJacob Faibussowitsch         CHKERRQ(ISDestroy(&zerodiags));
1525f80ce2aSJacob Faibussowitsch         CHKERRQ(ISDestroy(&rest));
153c7543cceSMatthew G Knepley       } else {
154c7543cceSMatthew G Knepley         if (!flg) {
155c7543cceSMatthew G Knepley           /* Allow user to set fields from command line, if bs was known at the time of SNESSetFromOptions_Multiblock()
156c7543cceSMatthew G Knepley            then it is set there. This is not ideal because we should only have options set in XXSetFromOptions(). */
1575f80ce2aSJacob Faibussowitsch           CHKERRQ(SNESMultiblockSetFieldsRuntime_Private(snes));
1585f80ce2aSJacob Faibussowitsch           if (mb->defined) CHKERRQ(PetscInfo(snes, "Blocks defined using the options database\n"));
159c7543cceSMatthew G Knepley         }
160c7543cceSMatthew G Knepley         if (flg || !mb->defined) {
1615f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscInfo(snes, "Using default splitting of fields\n"));
162c7543cceSMatthew G Knepley           for (i = 0; i < mb->bs; ++i) {
163c7543cceSMatthew G Knepley             char name[8];
164c7543cceSMatthew G Knepley 
1655f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscSNPrintf(name, sizeof(name), "%D", i));
1665f80ce2aSJacob Faibussowitsch             CHKERRQ(SNESMultiblockSetFields(snes, name, 1, &i));
167c7543cceSMatthew G Knepley           }
168c7543cceSMatthew G Knepley           mb->defaultblocks = PETSC_TRUE;
169c7543cceSMatthew G Knepley         }
170c7543cceSMatthew G Knepley       }
171c7543cceSMatthew G Knepley     }
172c7543cceSMatthew G Knepley   } else if (mb->numBlocks == 1) {
173c7543cceSMatthew G Knepley     if (blocks->is) {
174c7543cceSMatthew G Knepley       IS       is2;
175c7543cceSMatthew G Knepley       PetscInt nmin, nmax;
176c7543cceSMatthew G Knepley 
1775f80ce2aSJacob Faibussowitsch       CHKERRQ(MatGetOwnershipRange(snes->jacobian_pre, &nmin, &nmax));
1785f80ce2aSJacob Faibussowitsch       CHKERRQ(ISComplement(blocks->is, nmin, nmax, &is2));
1795f80ce2aSJacob Faibussowitsch       CHKERRQ(SNESMultiblockSetIS(snes, "1", is2));
1805f80ce2aSJacob Faibussowitsch       CHKERRQ(ISDestroy(&is2));
181f23aa3ddSBarry Smith     } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must provide at least two sets of fields to SNES multiblock");
182c7543cceSMatthew G Knepley   }
1832c71b3e2SJacob Faibussowitsch   PetscCheckFalse(mb->numBlocks < 2,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unhandled case, must have at least two blocks");
184c7543cceSMatthew G Knepley   PetscFunctionReturn(0);
185c7543cceSMatthew G Knepley }
186c7543cceSMatthew G Knepley 
187c7543cceSMatthew G Knepley /*
188c7543cceSMatthew G Knepley    SNESSetUp_Multiblock - Sets up the internal data structures for the later use
189c7543cceSMatthew G Knepley    of the SNESMULTIBLOCK nonlinear solver.
190c7543cceSMatthew G Knepley 
191c7543cceSMatthew G Knepley    Input Parameters:
192c7543cceSMatthew G Knepley +  snes - the SNES context
193c7543cceSMatthew G Knepley -  x - the solution vector
194c7543cceSMatthew G Knepley 
195c7543cceSMatthew G Knepley    Application Interface Routine: SNESSetUp()
196c7543cceSMatthew G Knepley */
197c7543cceSMatthew G Knepley PetscErrorCode SNESSetUp_Multiblock(SNES snes)
198c7543cceSMatthew G Knepley {
199c7543cceSMatthew G Knepley   SNES_Multiblock *mb = (SNES_Multiblock*) snes->data;
200c7543cceSMatthew G Knepley   BlockDesc       blocks;
201c7543cceSMatthew G Knepley   PetscInt        i, numBlocks;
202c7543cceSMatthew G Knepley 
203c7543cceSMatthew G Knepley   PetscFunctionBegin;
2045f80ce2aSJacob Faibussowitsch   CHKERRQ(SNESMultiblockSetDefaults(snes));
205c7543cceSMatthew G Knepley   numBlocks = mb->numBlocks;
206b665c654SMatthew G Knepley   blocks    = mb->blocks;
207c7543cceSMatthew G Knepley 
208c7543cceSMatthew G Knepley   /* Create ISs */
209c7543cceSMatthew G Knepley   if (!mb->issetup) {
210c7543cceSMatthew G Knepley     PetscInt  ccsize, rstart, rend, nslots, bs;
211c7543cceSMatthew G Knepley     PetscBool sorted;
212c7543cceSMatthew G Knepley 
213c7543cceSMatthew G Knepley     mb->issetup = PETSC_TRUE;
214c7543cceSMatthew G Knepley     bs          = mb->bs;
2155f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetOwnershipRange(snes->jacobian_pre, &rstart, &rend));
2165f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetLocalSize(snes->jacobian_pre, NULL, &ccsize));
217c7543cceSMatthew G Knepley     nslots      = (rend - rstart)/bs;
218c7543cceSMatthew G Knepley     for (i = 0; i < numBlocks; ++i) {
219b665c654SMatthew G Knepley       if (mb->defaultblocks) {
2205f80ce2aSJacob Faibussowitsch         CHKERRQ(ISCreateStride(PetscObjectComm((PetscObject)snes), nslots, rstart+i, numBlocks, &blocks->is));
221c7543cceSMatthew G Knepley       } else if (!blocks->is) {
222c7543cceSMatthew G Knepley         if (blocks->nfields > 1) {
223c7543cceSMatthew G Knepley           PetscInt *ii, j, k, nfields = blocks->nfields, *fields = blocks->fields;
224c7543cceSMatthew G Knepley 
2255f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscMalloc1(nfields*nslots, &ii));
226c7543cceSMatthew G Knepley           for (j = 0; j < nslots; ++j) {
227c7543cceSMatthew G Knepley             for (k = 0; k < nfields; ++k) {
228c7543cceSMatthew G Knepley               ii[nfields*j + k] = rstart + bs*j + fields[k];
229c7543cceSMatthew G Knepley             }
230c7543cceSMatthew G Knepley           }
2315f80ce2aSJacob Faibussowitsch           CHKERRQ(ISCreateGeneral(PetscObjectComm((PetscObject)snes), nslots*nfields, ii, PETSC_OWN_POINTER, &blocks->is));
232c7543cceSMatthew G Knepley         } else {
2335f80ce2aSJacob Faibussowitsch           CHKERRQ(ISCreateStride(PetscObjectComm((PetscObject)snes), nslots, rstart+blocks->fields[0], bs, &blocks->is));
234c7543cceSMatthew G Knepley         }
235c7543cceSMatthew G Knepley       }
2365f80ce2aSJacob Faibussowitsch       CHKERRQ(ISSorted(blocks->is, &sorted));
237*28b400f6SJacob Faibussowitsch       PetscCheck(sorted,PETSC_COMM_SELF, PETSC_ERR_USER, "Fields must be sorted when creating split");
238c7543cceSMatthew G Knepley       blocks = blocks->next;
239c7543cceSMatthew G Knepley     }
240c7543cceSMatthew G Knepley   }
241c7543cceSMatthew G Knepley 
242c7543cceSMatthew G Knepley #if 0
243c7543cceSMatthew G Knepley   /* Create matrices */
244c7543cceSMatthew G Knepley   ilink = jac->head;
245c7543cceSMatthew G Knepley   if (!jac->pmat) {
2465f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(nsplit,&jac->pmat));
247c7543cceSMatthew G Knepley     for (i=0; i<nsplit; i++) {
2485f80ce2aSJacob Faibussowitsch       CHKERRQ(MatCreateSubMatrix(pc->pmat,ilink->is,ilink->is,MAT_INITIAL_MATRIX,&jac->pmat[i]));
249c7543cceSMatthew G Knepley       ilink = ilink->next;
250c7543cceSMatthew G Knepley     }
251c7543cceSMatthew G Knepley   } else {
252c7543cceSMatthew G Knepley     for (i=0; i<nsplit; i++) {
2535f80ce2aSJacob Faibussowitsch       CHKERRQ(MatCreateSubMatrix(pc->pmat,ilink->is,ilink->is,MAT_REUSE_MATRIX,&jac->pmat[i]));
254c7543cceSMatthew G Knepley       ilink = ilink->next;
255c7543cceSMatthew G Knepley     }
256c7543cceSMatthew G Knepley   }
257c7543cceSMatthew G Knepley   if (jac->realdiagonal) {
258c7543cceSMatthew G Knepley     ilink = jac->head;
259c7543cceSMatthew G Knepley     if (!jac->mat) {
2605f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(nsplit,&jac->mat));
261c7543cceSMatthew G Knepley       for (i=0; i<nsplit; i++) {
2625f80ce2aSJacob Faibussowitsch         CHKERRQ(MatCreateSubMatrix(pc->mat,ilink->is,ilink->is,MAT_INITIAL_MATRIX,&jac->mat[i]));
263c7543cceSMatthew G Knepley         ilink = ilink->next;
264c7543cceSMatthew G Knepley       }
265c7543cceSMatthew G Knepley     } else {
266c7543cceSMatthew G Knepley       for (i=0; i<nsplit; i++) {
2675f80ce2aSJacob Faibussowitsch         if (jac->mat[i]) CHKERRQ(MatCreateSubMatrix(pc->mat,ilink->is,ilink->is,MAT_REUSE_MATRIX,&jac->mat[i]));
268c7543cceSMatthew G Knepley         ilink = ilink->next;
269c7543cceSMatthew G Knepley       }
270c7543cceSMatthew G Knepley     }
2711aa26658SKarl Rupp   } else jac->mat = jac->pmat;
272c7543cceSMatthew G Knepley #endif
273c7543cceSMatthew G Knepley 
274c7543cceSMatthew G Knepley #if 0
275c7543cceSMatthew G Knepley   if (jac->type != PC_COMPOSITE_ADDITIVE  && jac->type != PC_COMPOSITE_SCHUR) {
276c7543cceSMatthew G Knepley     /* extract the rows of the matrix associated with each field: used for efficient computation of residual inside algorithm */
277c7543cceSMatthew G Knepley     ilink = jac->head;
278c7543cceSMatthew G Knepley     if (!jac->Afield) {
2795f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(nsplit,&jac->Afield));
280c7543cceSMatthew G Knepley       for (i=0; i<nsplit; i++) {
2815f80ce2aSJacob Faibussowitsch         CHKERRQ(MatCreateSubMatrix(pc->mat,ilink->is,NULL,MAT_INITIAL_MATRIX,&jac->Afield[i]));
282c7543cceSMatthew G Knepley         ilink = ilink->next;
283c7543cceSMatthew G Knepley       }
284c7543cceSMatthew G Knepley     } else {
285c7543cceSMatthew G Knepley       for (i=0; i<nsplit; i++) {
2865f80ce2aSJacob Faibussowitsch         CHKERRQ(MatCreateSubMatrix(pc->mat,ilink->is,NULL,MAT_REUSE_MATRIX,&jac->Afield[i]));
287c7543cceSMatthew G Knepley         ilink = ilink->next;
288c7543cceSMatthew G Knepley       }
289c7543cceSMatthew G Knepley     }
290c7543cceSMatthew G Knepley   }
291c7543cceSMatthew G Knepley #endif
292c7543cceSMatthew G Knepley 
293b665c654SMatthew G Knepley   if (mb->type == PC_COMPOSITE_SCHUR) {
294c7543cceSMatthew G Knepley #if 0
295c7543cceSMatthew G Knepley     IS       ccis;
296c7543cceSMatthew G Knepley     PetscInt rstart,rend;
2972c71b3e2SJacob Faibussowitsch     PetscCheckFalse(nsplit != 2,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"To use Schur complement preconditioner you must have exactly 2 fields");
298c7543cceSMatthew G Knepley 
299c7543cceSMatthew G Knepley     /* When extracting off-diagonal submatrices, we take complements from this range */
3005f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetOwnershipRangeColumn(pc->mat,&rstart,&rend));
301c7543cceSMatthew G Knepley 
302c7543cceSMatthew G Knepley     /* need to handle case when one is resetting up the preconditioner */
303c7543cceSMatthew G Knepley     if (jac->schur) {
304c7543cceSMatthew G Knepley       ilink = jac->head;
3055f80ce2aSJacob Faibussowitsch       CHKERRQ(ISComplement(ilink->is,rstart,rend,&ccis));
3065f80ce2aSJacob Faibussowitsch       CHKERRQ(MatCreateSubMatrix(pc->mat,ilink->is,ccis,MAT_REUSE_MATRIX,&jac->B));
3075f80ce2aSJacob Faibussowitsch       CHKERRQ(ISDestroy(&ccis));
308c7543cceSMatthew G Knepley       ilink = ilink->next;
3095f80ce2aSJacob Faibussowitsch       CHKERRQ(ISComplement(ilink->is,rstart,rend,&ccis));
3105f80ce2aSJacob Faibussowitsch       CHKERRQ(MatCreateSubMatrix(pc->mat,ilink->is,ccis,MAT_REUSE_MATRIX,&jac->C));
3115f80ce2aSJacob Faibussowitsch       CHKERRQ(ISDestroy(&ccis));
3125f80ce2aSJacob Faibussowitsch       CHKERRQ(MatSchurComplementUpdateSubMatrices(jac->schur,jac->mat[0],jac->pmat[0],jac->B,jac->C,jac->pmat[1]));
3135f80ce2aSJacob Faibussowitsch       CHKERRQ(KSPSetOperators(jac->kspschur,jac->schur,FieldSplitSchurPre(jac),pc->flag));
314c7543cceSMatthew G Knepley 
315c7543cceSMatthew G Knepley     } else {
316c7543cceSMatthew G Knepley       KSP  ksp;
317c7543cceSMatthew G Knepley       char schurprefix[256];
318c7543cceSMatthew G Knepley 
319c7543cceSMatthew G Knepley       /* extract the A01 and A10 matrices */
320c7543cceSMatthew G Knepley       ilink = jac->head;
3215f80ce2aSJacob Faibussowitsch       CHKERRQ(ISComplement(ilink->is,rstart,rend,&ccis));
3225f80ce2aSJacob Faibussowitsch       CHKERRQ(MatCreateSubMatrix(pc->mat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->B));
3235f80ce2aSJacob Faibussowitsch       CHKERRQ(ISDestroy(&ccis));
324c7543cceSMatthew G Knepley       ilink = ilink->next;
3255f80ce2aSJacob Faibussowitsch       CHKERRQ(ISComplement(ilink->is,rstart,rend,&ccis));
3265f80ce2aSJacob Faibussowitsch       CHKERRQ(MatCreateSubMatrix(pc->mat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->C));
3275f80ce2aSJacob Faibussowitsch       CHKERRQ(ISDestroy(&ccis));
328c7543cceSMatthew G Knepley       /* Use mat[0] (diagonal block of the real matrix) preconditioned by pmat[0] */
3295f80ce2aSJacob Faibussowitsch       CHKERRQ(MatCreateSchurComplement(jac->mat[0],jac->pmat[0],jac->B,jac->C,jac->mat[1],&jac->schur));
330c7543cceSMatthew G Knepley       /* set tabbing and options prefix of KSP inside the MatSchur */
3315f80ce2aSJacob Faibussowitsch       CHKERRQ(MatSchurComplementGetKSP(jac->schur,&ksp));
3325f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscObjectIncrementTabLevel((PetscObject)ksp,(PetscObject)pc,2));
3335f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSNPrintf(schurprefix,sizeof(schurprefix),"%sfieldsplit_%s_",((PetscObject)pc)->prefix ? ((PetscObject)pc)->prefix : "",jac->head->splitname));
3345f80ce2aSJacob Faibussowitsch       CHKERRQ(KSPSetOptionsPrefix(ksp,schurprefix));
3355f80ce2aSJacob Faibussowitsch       CHKERRQ(MatSetFromOptions(jac->schur));
336c7543cceSMatthew G Knepley 
3375f80ce2aSJacob Faibussowitsch       CHKERRQ(KSPCreate(PetscObjectComm((PetscObject)pc),&jac->kspschur));
3385f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscLogObjectParent((PetscObject)pc,(PetscObject)jac->kspschur));
3395f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscObjectIncrementTabLevel((PetscObject)jac->kspschur,(PetscObject)pc,1));
3405f80ce2aSJacob Faibussowitsch       CHKERRQ(KSPSetOperators(jac->kspschur,jac->schur,FieldSplitSchurPre(jac)));
341c7543cceSMatthew G Knepley       if (jac->schurpre == PC_FIELDSPLIT_SCHUR_PRE_SELF) {
342c7543cceSMatthew G Knepley         PC pc;
3435f80ce2aSJacob Faibussowitsch         CHKERRQ(KSPGetPC(jac->kspschur,&pc));
3445f80ce2aSJacob Faibussowitsch         CHKERRQ(PCSetType(pc,PCNONE));
345c7543cceSMatthew G Knepley         /* Note: This is bad if there exist preconditioners for MATSCHURCOMPLEMENT */
346c7543cceSMatthew G Knepley       }
3475f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSNPrintf(schurprefix,sizeof(schurprefix),"%sfieldsplit_%s_",((PetscObject)pc)->prefix ? ((PetscObject)pc)->prefix : "",ilink->splitname));
3485f80ce2aSJacob Faibussowitsch       CHKERRQ(KSPSetOptionsPrefix(jac->kspschur,schurprefix));
349c7543cceSMatthew G Knepley       /* really want setfromoptions called in PCSetFromOptions_FieldSplit(), but it is not ready yet */
3505f80ce2aSJacob Faibussowitsch       CHKERRQ(KSPSetFromOptions(jac->kspschur));
351c7543cceSMatthew G Knepley 
3525f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc2(2,&jac->x,2,&jac->y));
3535f80ce2aSJacob Faibussowitsch       CHKERRQ(MatCreateVecs(jac->pmat[0],&jac->x[0],&jac->y[0]));
3545f80ce2aSJacob Faibussowitsch       CHKERRQ(MatCreateVecs(jac->pmat[1],&jac->x[1],&jac->y[1]));
355c7543cceSMatthew G Knepley       ilink    = jac->head;
356c7543cceSMatthew G Knepley       ilink->x = jac->x[0]; ilink->y = jac->y[0];
357c7543cceSMatthew G Knepley       ilink    = ilink->next;
358c7543cceSMatthew G Knepley       ilink->x = jac->x[1]; ilink->y = jac->y[1];
359c7543cceSMatthew G Knepley     }
360c7543cceSMatthew G Knepley #endif
361c7543cceSMatthew G Knepley   } else {
362c7543cceSMatthew G Knepley     /* Set up the individual SNESs */
363c7543cceSMatthew G Knepley     blocks = mb->blocks;
364c7543cceSMatthew G Knepley     i      = 0;
365c7543cceSMatthew G Knepley     while (blocks) {
366b665c654SMatthew G Knepley       /*TODO: Set these correctly */
3675f80ce2aSJacob Faibussowitsch       /*CHKERRQ(SNESSetFunction(blocks->snes, blocks->x, func));*/
3685f80ce2aSJacob Faibussowitsch       /*CHKERRQ(SNESSetJacobian(blocks->snes, blocks->x, jac));*/
3695f80ce2aSJacob Faibussowitsch       CHKERRQ(VecDuplicate(blocks->snes->vec_sol, &blocks->x));
370c7543cceSMatthew G Knepley       /* really want setfromoptions called in SNESSetFromOptions_Multiblock(), but it is not ready yet */
3715f80ce2aSJacob Faibussowitsch       CHKERRQ(SNESSetFromOptions(blocks->snes));
3725f80ce2aSJacob Faibussowitsch       CHKERRQ(SNESSetUp(blocks->snes));
373c7543cceSMatthew G Knepley       blocks = blocks->next;
374c7543cceSMatthew G Knepley       i++;
375c7543cceSMatthew G Knepley     }
376c7543cceSMatthew G Knepley   }
377c7543cceSMatthew G Knepley 
378c7543cceSMatthew G Knepley   /* Compute scatter contexts needed by multiplicative versions and non-default splits */
379c7543cceSMatthew G Knepley   if (!mb->blocks->sctx) {
380c7543cceSMatthew G Knepley     Vec xtmp;
381c7543cceSMatthew G Knepley 
382c7543cceSMatthew G Knepley     blocks = mb->blocks;
3835f80ce2aSJacob Faibussowitsch     CHKERRQ(MatCreateVecs(snes->jacobian_pre, &xtmp, NULL));
384c7543cceSMatthew G Knepley     while (blocks) {
3855f80ce2aSJacob Faibussowitsch       CHKERRQ(VecScatterCreate(xtmp, blocks->is, blocks->x, NULL, &blocks->sctx));
386c7543cceSMatthew G Knepley       blocks = blocks->next;
387c7543cceSMatthew G Knepley     }
3885f80ce2aSJacob Faibussowitsch     CHKERRQ(VecDestroy(&xtmp));
389c7543cceSMatthew G Knepley   }
390c7543cceSMatthew G Knepley   PetscFunctionReturn(0);
391c7543cceSMatthew G Knepley }
392c7543cceSMatthew G Knepley 
393c7543cceSMatthew G Knepley /*
394c7543cceSMatthew G Knepley   SNESSetFromOptions_Multiblock - Sets various parameters for the SNESMULTIBLOCK method.
395c7543cceSMatthew G Knepley 
396c7543cceSMatthew G Knepley   Input Parameter:
397c7543cceSMatthew G Knepley . snes - the SNES context
398c7543cceSMatthew G Knepley 
399c7543cceSMatthew G Knepley   Application Interface Routine: SNESSetFromOptions()
400c7543cceSMatthew G Knepley */
4014416b707SBarry Smith static PetscErrorCode SNESSetFromOptions_Multiblock(PetscOptionItems *PetscOptionsObject,SNES snes)
402c7543cceSMatthew G Knepley {
403c7543cceSMatthew G Knepley   SNES_Multiblock *mb = (SNES_Multiblock*) snes->data;
404c7543cceSMatthew G Knepley   PCCompositeType ctype;
405c7543cceSMatthew G Knepley   PetscInt        bs;
406c7543cceSMatthew G Knepley   PetscBool       flg;
407c7543cceSMatthew G Knepley 
408c7543cceSMatthew G Knepley   PetscFunctionBegin;
4095f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsHead(PetscOptionsObject,"SNES Multiblock options"));
4105f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsInt("-snes_multiblock_block_size", "Blocksize that defines number of fields", "PCFieldSplitSetBlockSize", mb->bs, &bs, &flg));
4115f80ce2aSJacob Faibussowitsch   if (flg) CHKERRQ(SNESMultiblockSetBlockSize(snes, bs));
4125f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsEnum("-snes_multiblock_type", "Type of composition", "PCFieldSplitSetType", PCCompositeTypes, (PetscEnum) mb->type, (PetscEnum*) &ctype, &flg));
413c7543cceSMatthew G Knepley   if (flg) {
4145f80ce2aSJacob Faibussowitsch     CHKERRQ(SNESMultiblockSetType(snes,ctype));
415c7543cceSMatthew G Knepley   }
416c7543cceSMatthew G Knepley   /* Only setup fields once */
417b665c654SMatthew G Knepley   if ((mb->bs > 0) && (mb->numBlocks == 0)) {
418c7543cceSMatthew G Knepley     /* only allow user to set fields from command line if bs is already known, otherwise user can set them in SNESMultiblockSetDefaults() */
4195f80ce2aSJacob Faibussowitsch     CHKERRQ(SNESMultiblockSetFieldsRuntime_Private(snes));
4205f80ce2aSJacob Faibussowitsch     if (mb->defined) CHKERRQ(PetscInfo(snes, "Blocks defined using the options database\n"));
421c7543cceSMatthew G Knepley   }
4225f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsTail());
423c7543cceSMatthew G Knepley   PetscFunctionReturn(0);
424c7543cceSMatthew G Knepley }
425c7543cceSMatthew G Knepley 
426c7543cceSMatthew G Knepley /*
427c7543cceSMatthew G Knepley   SNESView_Multiblock - Prints info from the SNESMULTIBLOCK data structure.
428c7543cceSMatthew G Knepley 
429c7543cceSMatthew G Knepley   Input Parameters:
430c7543cceSMatthew G Knepley + SNES - the SNES context
431c7543cceSMatthew G Knepley - viewer - visualization context
432c7543cceSMatthew G Knepley 
433c7543cceSMatthew G Knepley   Application Interface Routine: SNESView()
434c7543cceSMatthew G Knepley */
435c7543cceSMatthew G Knepley static PetscErrorCode SNESView_Multiblock(SNES snes, PetscViewer viewer)
436c7543cceSMatthew G Knepley {
437c7543cceSMatthew G Knepley   SNES_Multiblock *mb    = (SNES_Multiblock*) snes->data;
438c7543cceSMatthew G Knepley   BlockDesc       blocks = mb->blocks;
439c7543cceSMatthew G Knepley   PetscBool       iascii;
440c7543cceSMatthew G Knepley 
441c7543cceSMatthew G Knepley   PetscFunctionBegin;
4425f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii));
443c7543cceSMatthew G Knepley   if (iascii) {
4445f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Multiblock with %s composition: total blocks = %D, blocksize = %D\n", PCCompositeTypes[mb->type], mb->numBlocks, mb->bs));
4455f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Solver info for each split is in the following SNES objects:\n"));
4465f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPushTab(viewer));
447c7543cceSMatthew G Knepley     while (blocks) {
448c7543cceSMatthew G Knepley       if (blocks->fields) {
449c7543cceSMatthew G Knepley         PetscInt j;
450c7543cceSMatthew G Knepley 
4515f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIPrintf(viewer, "  Block %s Fields ", blocks->name));
4525f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
453c7543cceSMatthew G Knepley         for (j = 0; j < blocks->nfields; ++j) {
454c7543cceSMatthew G Knepley           if (j > 0) {
4555f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscViewerASCIIPrintf(viewer, ","));
456c7543cceSMatthew G Knepley           }
4575f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscViewerASCIIPrintf(viewer, " %D", blocks->fields[j]));
458c7543cceSMatthew G Knepley         }
4595f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIPrintf(viewer, "\n"));
4605f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
461c7543cceSMatthew G Knepley       } else {
4625f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIPrintf(viewer, "  Block %s Defined by IS\n", blocks->name));
463c7543cceSMatthew G Knepley       }
4645f80ce2aSJacob Faibussowitsch       CHKERRQ(SNESView(blocks->snes, viewer));
465c7543cceSMatthew G Knepley       blocks = blocks->next;
466c7543cceSMatthew G Knepley     }
4675f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPopTab(viewer));
468c7543cceSMatthew G Knepley   }
469c7543cceSMatthew G Knepley   PetscFunctionReturn(0);
470c7543cceSMatthew G Knepley }
471c7543cceSMatthew G Knepley 
472c7543cceSMatthew G Knepley /*
473c7543cceSMatthew G Knepley   SNESSolve_Multiblock - Solves a nonlinear system with the Multiblock method.
474c7543cceSMatthew G Knepley 
475c7543cceSMatthew G Knepley   Input Parameters:
476c7543cceSMatthew G Knepley . snes - the SNES context
477c7543cceSMatthew G Knepley 
478c7543cceSMatthew G Knepley   Output Parameter:
479c7543cceSMatthew G Knepley . outits - number of iterations until termination
480c7543cceSMatthew G Knepley 
481c7543cceSMatthew G Knepley   Application Interface Routine: SNESSolve()
482c7543cceSMatthew G Knepley */
483c7543cceSMatthew G Knepley PetscErrorCode SNESSolve_Multiblock(SNES snes)
484c7543cceSMatthew G Knepley {
485c7543cceSMatthew G Knepley   SNES_Multiblock *mb = (SNES_Multiblock*) snes->data;
486c7543cceSMatthew G Knepley   Vec             X, Y, F;
487c7543cceSMatthew G Knepley   PetscReal       fnorm;
488c7543cceSMatthew G Knepley   PetscInt        maxits, i;
489c7543cceSMatthew G Knepley 
490c7543cceSMatthew G Knepley   PetscFunctionBegin;
4912c71b3e2SJacob Faibussowitsch   PetscCheckFalse(snes->xl || snes->xu || snes->ops->computevariablebounds,PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE, "SNES solver %s does not support bounds", ((PetscObject)snes)->type_name);
492c579b300SPatrick Farrell 
493c7543cceSMatthew G Knepley   snes->reason = SNES_CONVERGED_ITERATING;
494c7543cceSMatthew G Knepley 
495c7543cceSMatthew G Knepley   maxits = snes->max_its;        /* maximum number of iterations */
496c7543cceSMatthew G Knepley   X      = snes->vec_sol;        /* X^n */
497c7543cceSMatthew G Knepley   Y      = snes->vec_sol_update; /* \tilde X */
498c7543cceSMatthew G Knepley   F      = snes->vec_func;       /* residual vector */
499c7543cceSMatthew G Knepley 
5005f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetBlockSize(X, mb->bs));
5015f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetBlockSize(Y, mb->bs));
5025f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetBlockSize(F, mb->bs));
5035f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSAWsTakeAccess((PetscObject)snes));
504c7543cceSMatthew G Knepley   snes->iter = 0;
505c7543cceSMatthew G Knepley   snes->norm = 0.;
5065f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSAWsGrantAccess((PetscObject)snes));
507e4ed7901SPeter Brune 
508e4ed7901SPeter Brune   if (!snes->vec_func_init_set) {
5095f80ce2aSJacob Faibussowitsch     CHKERRQ(SNESComputeFunction(snes, X, F));
5101aa26658SKarl Rupp   } else snes->vec_func_init_set = PETSC_FALSE;
5111aa26658SKarl Rupp 
5125f80ce2aSJacob Faibussowitsch   CHKERRQ(VecNorm(F, NORM_2, &fnorm)); /* fnorm <- ||F||  */
513422a814eSBarry Smith   SNESCheckFunctionNorm(snes,fnorm);
5145f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSAWsTakeAccess((PetscObject)snes));
515c7543cceSMatthew G Knepley   snes->norm = fnorm;
5165f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSAWsGrantAccess((PetscObject)snes));
5175f80ce2aSJacob Faibussowitsch   CHKERRQ(SNESLogConvergenceHistory(snes,fnorm,0));
5185f80ce2aSJacob Faibussowitsch   CHKERRQ(SNESMonitor(snes,0,fnorm));
519c7543cceSMatthew G Knepley 
520c7543cceSMatthew G Knepley   /* test convergence */
5215f80ce2aSJacob Faibussowitsch   CHKERRQ((*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP));
522c7543cceSMatthew G Knepley   if (snes->reason) PetscFunctionReturn(0);
523c7543cceSMatthew G Knepley 
524c7543cceSMatthew G Knepley   for (i = 0; i < maxits; i++) {
525c7543cceSMatthew G Knepley     /* Call general purpose update function */
526c7543cceSMatthew G Knepley     if (snes->ops->update) {
5275f80ce2aSJacob Faibussowitsch       CHKERRQ((*snes->ops->update)(snes, snes->iter));
528c7543cceSMatthew G Knepley     }
529c7543cceSMatthew G Knepley     /* Compute X^{new} from subsolves */
530c7543cceSMatthew G Knepley     if (mb->type == PC_COMPOSITE_ADDITIVE) {
531c7543cceSMatthew G Knepley       BlockDesc blocks = mb->blocks;
532c7543cceSMatthew G Knepley 
533b665c654SMatthew G Knepley       if (mb->defaultblocks) {
534b665c654SMatthew G Knepley         /*TODO: Make an array of Vecs for this */
5355f80ce2aSJacob Faibussowitsch         /*CHKERRQ(VecStrideGatherAll(X, mb->x, INSERT_VALUES));*/
536c7543cceSMatthew G Knepley         while (blocks) {
5375f80ce2aSJacob Faibussowitsch           CHKERRQ(SNESSolve(blocks->snes, NULL, blocks->x));
538c7543cceSMatthew G Knepley           blocks = blocks->next;
539c7543cceSMatthew G Knepley         }
5405f80ce2aSJacob Faibussowitsch         /*CHKERRQ(VecStrideScatterAll(mb->x, X, INSERT_VALUES));*/
541c7543cceSMatthew G Knepley       } else {
542c7543cceSMatthew G Knepley         while (blocks) {
5435f80ce2aSJacob Faibussowitsch           CHKERRQ(VecScatterBegin(blocks->sctx, X, blocks->x, INSERT_VALUES, SCATTER_FORWARD));
5445f80ce2aSJacob Faibussowitsch           CHKERRQ(VecScatterEnd(blocks->sctx, X, blocks->x, INSERT_VALUES, SCATTER_FORWARD));
5455f80ce2aSJacob Faibussowitsch           CHKERRQ(SNESSolve(blocks->snes, NULL, blocks->x));
5465f80ce2aSJacob Faibussowitsch           CHKERRQ(VecScatterBegin(blocks->sctx, blocks->x, X, INSERT_VALUES, SCATTER_REVERSE));
5475f80ce2aSJacob Faibussowitsch           CHKERRQ(VecScatterEnd(blocks->sctx, blocks->x, X, INSERT_VALUES, SCATTER_REVERSE));
548c7543cceSMatthew G Knepley           blocks = blocks->next;
549c7543cceSMatthew G Knepley         }
550c7543cceSMatthew G Knepley       }
55198921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)snes), PETSC_ERR_SUP, "Unsupported or unknown composition", (int) mb->type);
552c7543cceSMatthew G Knepley     /* Compute F(X^{new}) */
5535f80ce2aSJacob Faibussowitsch     CHKERRQ(SNESComputeFunction(snes, X, F));
5545f80ce2aSJacob Faibussowitsch     CHKERRQ(VecNorm(F, NORM_2, &fnorm));
555422a814eSBarry Smith     SNESCheckFunctionNorm(snes,fnorm);
556c7543cceSMatthew G Knepley 
557e71169deSBarry Smith     if (snes->nfuncs >= snes->max_funcs && snes->max_funcs >=0) {
558c7543cceSMatthew G Knepley       snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
559c7543cceSMatthew G Knepley       break;
560c7543cceSMatthew G Knepley     }
561422a814eSBarry Smith 
562c7543cceSMatthew G Knepley     /* Monitor convergence */
5635f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectSAWsTakeAccess((PetscObject)snes));
564c7543cceSMatthew G Knepley     snes->iter = i+1;
565c7543cceSMatthew G Knepley     snes->norm = fnorm;
5665f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectSAWsGrantAccess((PetscObject)snes));
5675f80ce2aSJacob Faibussowitsch     CHKERRQ(SNESLogConvergenceHistory(snes,snes->norm,0));
5685f80ce2aSJacob Faibussowitsch     CHKERRQ(SNESMonitor(snes,snes->iter,snes->norm));
569c7543cceSMatthew G Knepley     /* Test for convergence */
5705f80ce2aSJacob Faibussowitsch     CHKERRQ((*snes->ops->converged)(snes,snes->iter,0.0,0.0,fnorm,&snes->reason,snes->cnvP));
571c7543cceSMatthew G Knepley     if (snes->reason) break;
572c7543cceSMatthew G Knepley   }
573c7543cceSMatthew G Knepley   if (i == maxits) {
5745f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscInfo(snes, "Maximum number of iterations has been reached: %D\n", maxits));
575c7543cceSMatthew G Knepley     if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
576c7543cceSMatthew G Knepley   }
577c7543cceSMatthew G Knepley   PetscFunctionReturn(0);
578c7543cceSMatthew G Knepley }
579c7543cceSMatthew G Knepley 
580c7543cceSMatthew G Knepley PetscErrorCode SNESMultiblockSetFields_Default(SNES snes, const char name[], PetscInt n, const PetscInt fields[])
581c7543cceSMatthew G Knepley {
582c7543cceSMatthew G Knepley   SNES_Multiblock *mb = (SNES_Multiblock*) snes->data;
583c7543cceSMatthew G Knepley   BlockDesc       newblock, next = mb->blocks;
584c7543cceSMatthew G Knepley   char            prefix[128];
585c7543cceSMatthew G Knepley   PetscInt        i;
586c7543cceSMatthew G Knepley 
587c7543cceSMatthew G Knepley   PetscFunctionBegin;
588c7543cceSMatthew G Knepley   if (mb->defined) {
5895f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscInfo(snes, "Ignoring new block \"%s\" because the blocks have already been defined\n", name));
590c7543cceSMatthew G Knepley     PetscFunctionReturn(0);
591c7543cceSMatthew G Knepley   }
592c7543cceSMatthew G Knepley   for (i = 0; i < n; ++i) {
5932c71b3e2SJacob Faibussowitsch     PetscCheckFalse(fields[i] >= mb->bs,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field %D requested but only %D exist", fields[i], mb->bs);
5942c71b3e2SJacob Faibussowitsch     PetscCheckFalse(fields[i] < 0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative field %D requested", fields[i]);
595c7543cceSMatthew G Knepley   }
5965f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscNew(&newblock));
597c7543cceSMatthew G Knepley   if (name) {
5985f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrallocpy(name, &newblock->name));
599c7543cceSMatthew G Knepley   } else {
600c7543cceSMatthew G Knepley     PetscInt len = floor(log10(mb->numBlocks))+1;
601c7543cceSMatthew G Knepley 
6025f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(len+1, &newblock->name));
6035f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSNPrintf(newblock->name, len, "%s", mb->numBlocks));
604c7543cceSMatthew G Knepley   }
605c7543cceSMatthew G Knepley   newblock->nfields = n;
6061aa26658SKarl Rupp 
6075f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(n, &newblock->fields));
6085f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscArraycpy(newblock->fields, fields, n));
6091aa26658SKarl Rupp 
6100298fd71SBarry Smith   newblock->next = NULL;
6111aa26658SKarl Rupp 
6125f80ce2aSJacob Faibussowitsch   CHKERRQ(SNESCreate(PetscObjectComm((PetscObject)snes), &newblock->snes));
6135f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectIncrementTabLevel((PetscObject) newblock->snes, (PetscObject) snes, 1));
6145f80ce2aSJacob Faibussowitsch   CHKERRQ(SNESSetType(newblock->snes, SNESNRICHARDSON));
6155f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogObjectParent((PetscObject) snes, (PetscObject) newblock->snes));
6165f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSNPrintf(prefix, sizeof(prefix), "%smultiblock_%s_", ((PetscObject) snes)->prefix ? ((PetscObject) snes)->prefix : "", newblock->name));
6175f80ce2aSJacob Faibussowitsch   CHKERRQ(SNESSetOptionsPrefix(newblock->snes, prefix));
618c7543cceSMatthew G Knepley 
619c7543cceSMatthew G Knepley   if (!next) {
620c7543cceSMatthew G Knepley     mb->blocks         = newblock;
6210298fd71SBarry Smith     newblock->previous = NULL;
622c7543cceSMatthew G Knepley   } else {
623c7543cceSMatthew G Knepley     while (next->next) {
624c7543cceSMatthew G Knepley       next = next->next;
625c7543cceSMatthew G Knepley     }
626c7543cceSMatthew G Knepley     next->next         = newblock;
627c7543cceSMatthew G Knepley     newblock->previous = next;
628c7543cceSMatthew G Knepley   }
629c7543cceSMatthew G Knepley   mb->numBlocks++;
630c7543cceSMatthew G Knepley   PetscFunctionReturn(0);
631c7543cceSMatthew G Knepley }
632c7543cceSMatthew G Knepley 
633c7543cceSMatthew G Knepley PetscErrorCode SNESMultiblockSetIS_Default(SNES snes, const char name[], IS is)
634c7543cceSMatthew G Knepley {
635c7543cceSMatthew G Knepley   SNES_Multiblock *mb = (SNES_Multiblock*) snes->data;
636c7543cceSMatthew G Knepley   BlockDesc       newblock, next = mb->blocks;
637c7543cceSMatthew G Knepley   char            prefix[128];
638c7543cceSMatthew G Knepley 
639c7543cceSMatthew G Knepley   PetscFunctionBegin;
640c7543cceSMatthew G Knepley   if (mb->defined) {
6415f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscInfo(snes, "Ignoring new block \"%s\" because the blocks have already been defined\n", name));
642c7543cceSMatthew G Knepley     PetscFunctionReturn(0);
643c7543cceSMatthew G Knepley   }
6445f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscNew(&newblock));
645c7543cceSMatthew G Knepley   if (name) {
6465f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrallocpy(name, &newblock->name));
647c7543cceSMatthew G Knepley   } else {
648c7543cceSMatthew G Knepley     PetscInt len = floor(log10(mb->numBlocks))+1;
649c7543cceSMatthew G Knepley 
6505f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(len+1, &newblock->name));
6515f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSNPrintf(newblock->name, len, "%s", mb->numBlocks));
652c7543cceSMatthew G Knepley   }
653c7543cceSMatthew G Knepley   newblock->is = is;
6541aa26658SKarl Rupp 
6555f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectReference((PetscObject) is));
6561aa26658SKarl Rupp 
6570298fd71SBarry Smith   newblock->next = NULL;
6581aa26658SKarl Rupp 
6595f80ce2aSJacob Faibussowitsch   CHKERRQ(SNESCreate(PetscObjectComm((PetscObject)snes), &newblock->snes));
6605f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectIncrementTabLevel((PetscObject) newblock->snes, (PetscObject) snes, 1));
6615f80ce2aSJacob Faibussowitsch   CHKERRQ(SNESSetType(newblock->snes, SNESNRICHARDSON));
6625f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogObjectParent((PetscObject) snes, (PetscObject) newblock->snes));
6635f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSNPrintf(prefix, sizeof(prefix), "%smultiblock_%s_", ((PetscObject) snes)->prefix ? ((PetscObject) snes)->prefix : "", newblock->name));
6645f80ce2aSJacob Faibussowitsch   CHKERRQ(SNESSetOptionsPrefix(newblock->snes, prefix));
665c7543cceSMatthew G Knepley 
666c7543cceSMatthew G Knepley   if (!next) {
667c7543cceSMatthew G Knepley     mb->blocks         = newblock;
6680298fd71SBarry Smith     newblock->previous = NULL;
669c7543cceSMatthew G Knepley   } else {
670c7543cceSMatthew G Knepley     while (next->next) {
671c7543cceSMatthew G Knepley       next = next->next;
672c7543cceSMatthew G Knepley     }
673c7543cceSMatthew G Knepley     next->next         = newblock;
674c7543cceSMatthew G Knepley     newblock->previous = next;
675c7543cceSMatthew G Knepley   }
676c7543cceSMatthew G Knepley   mb->numBlocks++;
677c7543cceSMatthew G Knepley   PetscFunctionReturn(0);
678c7543cceSMatthew G Knepley }
679c7543cceSMatthew G Knepley 
680c7543cceSMatthew G Knepley PetscErrorCode  SNESMultiblockSetBlockSize_Default(SNES snes, PetscInt bs)
681c7543cceSMatthew G Knepley {
682c7543cceSMatthew G Knepley   SNES_Multiblock *mb = (SNES_Multiblock*) snes->data;
683c7543cceSMatthew G Knepley 
684c7543cceSMatthew G Knepley   PetscFunctionBegin;
6852c71b3e2SJacob Faibussowitsch   PetscCheckFalse(bs < 1,PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Blocksize must be positive, you gave %D", bs);
6862c71b3e2SJacob Faibussowitsch   PetscCheckFalse(mb->bs > 0 && mb->bs != bs,PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONGSTATE, "Cannot change blocksize from %D to %D after it has been set", mb->bs, bs);
687c7543cceSMatthew G Knepley   mb->bs = bs;
688c7543cceSMatthew G Knepley   PetscFunctionReturn(0);
689c7543cceSMatthew G Knepley }
690c7543cceSMatthew G Knepley 
691c7543cceSMatthew G Knepley PetscErrorCode SNESMultiblockGetSubSNES_Default(SNES snes, PetscInt *n, SNES **subsnes)
692c7543cceSMatthew G Knepley {
693c7543cceSMatthew G Knepley   SNES_Multiblock *mb    = (SNES_Multiblock*) snes->data;
694c7543cceSMatthew G Knepley   BlockDesc       blocks = mb->blocks;
695c7543cceSMatthew G Knepley   PetscInt        cnt    = 0;
696c7543cceSMatthew G Knepley 
697c7543cceSMatthew G Knepley   PetscFunctionBegin;
6985f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(mb->numBlocks, subsnes));
699c7543cceSMatthew G Knepley   while (blocks) {
700c7543cceSMatthew G Knepley     (*subsnes)[cnt++] = blocks->snes;
701c7543cceSMatthew G Knepley     blocks            = blocks->next;
702c7543cceSMatthew G Knepley   }
7032c71b3e2SJacob Faibussowitsch   PetscCheckFalse(cnt != mb->numBlocks,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Corrupt SNESMULTIBLOCK object: number of blocks in linked list %D does not match number in object %D", cnt, mb->numBlocks);
7041aa26658SKarl Rupp 
7051aa26658SKarl Rupp   if (n) *n = mb->numBlocks;
706c7543cceSMatthew G Knepley   PetscFunctionReturn(0);
707c7543cceSMatthew G Knepley }
708c7543cceSMatthew G Knepley 
70987bd6022SMatthew G Knepley PetscErrorCode  SNESMultiblockSetType_Default(SNES snes, PCCompositeType type)
71087bd6022SMatthew G Knepley {
71187bd6022SMatthew G Knepley   SNES_Multiblock *mb = (SNES_Multiblock*) snes->data;
71287bd6022SMatthew G Knepley 
71387bd6022SMatthew G Knepley   PetscFunctionBegin;
71487bd6022SMatthew G Knepley   mb->type = type;
71587bd6022SMatthew G Knepley   if (type == PC_COMPOSITE_SCHUR) {
71687bd6022SMatthew G Knepley #if 1
71782f516ccSBarry Smith     SETERRQ(PetscObjectComm((PetscObject)snes), PETSC_ERR_SUP, "The Schur composite type is not yet supported");
71887bd6022SMatthew G Knepley #else
71987bd6022SMatthew G Knepley     snes->ops->solve = SNESSolve_Multiblock_Schur;
72087bd6022SMatthew G Knepley     snes->ops->view  = SNESView_Multiblock_Schur;
7211aa26658SKarl Rupp 
7225f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectComposeFunction((PetscObject) snes, "SNESMultiblockGetSubSNES_C", SNESMultiblockGetSubSNES_Schur));
7235f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectComposeFunction((PetscObject) snes, "SNESMultiblockSchurPrecondition_C", SNESMultiblockSchurPrecondition_Default));
72487bd6022SMatthew G Knepley #endif
72587bd6022SMatthew G Knepley   } else {
72687bd6022SMatthew G Knepley     snes->ops->solve = SNESSolve_Multiblock;
72787bd6022SMatthew G Knepley     snes->ops->view  = SNESView_Multiblock;
7281aa26658SKarl Rupp 
7295f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectComposeFunction((PetscObject) snes, "SNESMultiblockGetSubSNES_C", SNESMultiblockGetSubSNES_Default));
7305f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectComposeFunction((PetscObject) snes, "SNESMultiblockSchurPrecondition_C", 0));
73187bd6022SMatthew G Knepley   }
73287bd6022SMatthew G Knepley   PetscFunctionReturn(0);
73387bd6022SMatthew G Knepley }
73487bd6022SMatthew G Knepley 
735c7543cceSMatthew G Knepley /*@
736c7543cceSMatthew G Knepley   SNESMultiblockSetFields - Sets the fields for one particular block in the solver
737c7543cceSMatthew G Knepley 
738c7543cceSMatthew G Knepley   Logically Collective on SNES
739c7543cceSMatthew G Knepley 
740c7543cceSMatthew G Knepley   Input Parameters:
741c7543cceSMatthew G Knepley + snes   - the solver
7420298fd71SBarry Smith . name   - name of this block, if NULL the number of the block is used
743c7543cceSMatthew G Knepley . n      - the number of fields in this block
744c7543cceSMatthew G Knepley - fields - the fields in this block
745c7543cceSMatthew G Knepley 
746c7543cceSMatthew G Knepley   Level: intermediate
747c7543cceSMatthew G Knepley 
74895452b02SPatrick Sanan   Notes:
74995452b02SPatrick Sanan     Use SNESMultiblockSetIS() to set a completely general set of row indices as a block.
750c7543cceSMatthew G Knepley 
751c7543cceSMatthew G Knepley   The SNESMultiblockSetFields() is for defining blocks as a group of strided indices, or fields.
752c7543cceSMatthew G Knepley   For example, if the vector block size is three then one can define a block as field 0, or
753c7543cceSMatthew G Knepley   1 or 2, or field 0,1 or 0,2 or 1,2 which means
754c7543cceSMatthew G Knepley     0xx3xx6xx9xx12 ... x1xx4xx7xx ... xx2xx5xx8xx.. 01x34x67x... 0x1x3x5x7.. x12x45x78x....
755c7543cceSMatthew G Knepley   where the numbered entries indicate what is in the block.
756c7543cceSMatthew G Knepley 
757c7543cceSMatthew G Knepley   This function is called once per block (it creates a new block each time). Solve options
758c7543cceSMatthew G Knepley   for this block will be available under the prefix -multiblock_BLOCKNAME_.
759c7543cceSMatthew G Knepley 
760b665c654SMatthew G Knepley .seealso: SNESMultiblockGetSubSNES(), SNESMULTIBLOCK, SNESMultiblockSetBlockSize(), SNESMultiblockSetIS()
761c7543cceSMatthew G Knepley @*/
762c7543cceSMatthew G Knepley PetscErrorCode SNESMultiblockSetFields(SNES snes, const char name[], PetscInt n, const PetscInt *fields)
763c7543cceSMatthew G Knepley {
764c7543cceSMatthew G Knepley   PetscFunctionBegin;
765c7543cceSMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
766c7543cceSMatthew G Knepley   PetscValidCharPointer(name, 2);
7672c71b3e2SJacob Faibussowitsch   PetscCheckFalse(n < 1,PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Provided number of fields %D in split \"%s\" not positive", n, name);
768064a246eSJacob Faibussowitsch   PetscValidIntPointer(fields, 4);
7695f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscTryMethod(snes, "SNESMultiblockSetFields_C", (SNES, const char[], PetscInt, const PetscInt*), (snes, name, n, fields)));
770c7543cceSMatthew G Knepley   PetscFunctionReturn(0);
771c7543cceSMatthew G Knepley }
772c7543cceSMatthew G Knepley 
773c7543cceSMatthew G Knepley /*@
774c7543cceSMatthew G Knepley   SNESMultiblockSetIS - Sets the global row indices for the block
775c7543cceSMatthew G Knepley 
776c7543cceSMatthew G Knepley   Logically Collective on SNES
777c7543cceSMatthew G Knepley 
778c7543cceSMatthew G Knepley   Input Parameters:
779c7543cceSMatthew G Knepley + snes - the solver context
7800298fd71SBarry Smith . name - name of this block, if NULL the number of the block is used
781c7543cceSMatthew G Knepley - is   - the index set that defines the global row indices in this block
782c7543cceSMatthew G Knepley 
783c7543cceSMatthew G Knepley   Notes:
784c7543cceSMatthew G Knepley   Use SNESMultiblockSetFields(), for blocks defined by strides.
785c7543cceSMatthew G Knepley 
786c7543cceSMatthew G Knepley   This function is called once per block (it creates a new block each time). Solve options
787c7543cceSMatthew G Knepley   for this block will be available under the prefix -multiblock_BLOCKNAME_.
788c7543cceSMatthew G Knepley 
789c7543cceSMatthew G Knepley   Level: intermediate
790c7543cceSMatthew G Knepley 
791b665c654SMatthew G Knepley .seealso: SNESMultiblockGetSubSNES(), SNESMULTIBLOCK, SNESMultiblockSetBlockSize()
792c7543cceSMatthew G Knepley @*/
793c7543cceSMatthew G Knepley PetscErrorCode SNESMultiblockSetIS(SNES snes, const char name[], IS is)
794c7543cceSMatthew G Knepley {
795c7543cceSMatthew G Knepley   PetscFunctionBegin;
796c7543cceSMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
797c7543cceSMatthew G Knepley   PetscValidCharPointer(name, 2);
798c7543cceSMatthew G Knepley   PetscValidHeaderSpecific(is, IS_CLASSID, 3);
7995f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscTryMethod(snes, "SNESMultiblockSetIS_C", (SNES, const char[], IS), (snes, name, is)));
800c7543cceSMatthew G Knepley   PetscFunctionReturn(0);
801c7543cceSMatthew G Knepley }
802c7543cceSMatthew G Knepley 
803c7543cceSMatthew G Knepley /*@
804c7543cceSMatthew G Knepley   SNESMultiblockSetType - Sets the type of block combination.
805c7543cceSMatthew G Knepley 
806c7543cceSMatthew G Knepley   Collective on SNES
807c7543cceSMatthew G Knepley 
808c7543cceSMatthew G Knepley   Input Parameters:
809c7543cceSMatthew G Knepley + snes - the solver context
810c7543cceSMatthew G Knepley - type - PC_COMPOSITE_ADDITIVE, PC_COMPOSITE_MULTIPLICATIVE (default), PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE
811c7543cceSMatthew G Knepley 
812c7543cceSMatthew G Knepley   Options Database Key:
813c7543cceSMatthew G Knepley . -snes_multiblock_type <type: one of multiplicative, additive, symmetric_multiplicative> - Sets block combination type
814c7543cceSMatthew G Knepley 
815c7543cceSMatthew G Knepley   Level: Developer
816c7543cceSMatthew G Knepley 
817c7543cceSMatthew G Knepley .seealso: PCCompositeSetType()
818c7543cceSMatthew G Knepley @*/
819c7543cceSMatthew G Knepley PetscErrorCode SNESMultiblockSetType(SNES snes, PCCompositeType type)
820c7543cceSMatthew G Knepley {
821c7543cceSMatthew G Knepley   PetscFunctionBegin;
822c7543cceSMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
8235f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscTryMethod(snes, "SNESMultiblockSetType_C", (SNES, PCCompositeType), (snes, type)));
824c7543cceSMatthew G Knepley   PetscFunctionReturn(0);
825c7543cceSMatthew G Knepley }
826c7543cceSMatthew G Knepley 
827c7543cceSMatthew G Knepley /*@
828c7543cceSMatthew G Knepley   SNESMultiblockSetBlockSize - Sets the block size for structured mesh block division. If not set the matrix block size is used.
829c7543cceSMatthew G Knepley 
830c7543cceSMatthew G Knepley   Logically Collective on SNES
831c7543cceSMatthew G Knepley 
832c7543cceSMatthew G Knepley   Input Parameters:
833c7543cceSMatthew G Knepley + snes - the solver context
834c7543cceSMatthew G Knepley - bs   - the block size
835c7543cceSMatthew G Knepley 
836c7543cceSMatthew G Knepley   Level: intermediate
837c7543cceSMatthew G Knepley 
838b665c654SMatthew G Knepley .seealso: SNESMultiblockGetSubSNES(), SNESMULTIBLOCK, SNESMultiblockSetFields()
839c7543cceSMatthew G Knepley @*/
840c7543cceSMatthew G Knepley PetscErrorCode SNESMultiblockSetBlockSize(SNES snes, PetscInt bs)
841c7543cceSMatthew G Knepley {
842c7543cceSMatthew G Knepley   PetscFunctionBegin;
843c7543cceSMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
844c7543cceSMatthew G Knepley   PetscValidLogicalCollectiveInt(snes, bs, 2);
8455f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscTryMethod(snes, "SNESMultiblockSetBlockSize_C", (SNES, PetscInt), (snes,bs)));
846c7543cceSMatthew G Knepley   PetscFunctionReturn(0);
847c7543cceSMatthew G Knepley }
848c7543cceSMatthew G Knepley 
849c7543cceSMatthew G Knepley /*@C
850b665c654SMatthew G Knepley   SNESMultiblockGetSubSNES - Gets the SNES contexts for all blocks
851c7543cceSMatthew G Knepley 
852c7543cceSMatthew G Knepley   Collective on SNES
853c7543cceSMatthew G Knepley 
854c7543cceSMatthew G Knepley   Input Parameter:
855c7543cceSMatthew G Knepley . snes - the solver context
856c7543cceSMatthew G Knepley 
857c7543cceSMatthew G Knepley   Output Parameters:
858c7543cceSMatthew G Knepley + n       - the number of blocks
859c7543cceSMatthew G Knepley - subsnes - the array of SNES contexts
860c7543cceSMatthew G Knepley 
861c7543cceSMatthew G Knepley   Note:
862c7543cceSMatthew G Knepley   After SNESMultiblockGetSubSNES() the array of SNESs MUST be freed by the user
863c7543cceSMatthew G Knepley   (not each SNES, just the array that contains them).
864c7543cceSMatthew G Knepley 
865c7543cceSMatthew G Knepley   You must call SNESSetUp() before calling SNESMultiblockGetSubSNES().
866c7543cceSMatthew G Knepley 
867c7543cceSMatthew G Knepley   Level: advanced
868c7543cceSMatthew G Knepley 
869c7543cceSMatthew G Knepley .seealso: SNESMULTIBLOCK
870c7543cceSMatthew G Knepley @*/
871c7543cceSMatthew G Knepley PetscErrorCode SNESMultiblockGetSubSNES(SNES snes, PetscInt *n, SNES *subsnes[])
872c7543cceSMatthew G Knepley {
873c7543cceSMatthew G Knepley   PetscFunctionBegin;
874c7543cceSMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
875c7543cceSMatthew G Knepley   if (n) PetscValidIntPointer(n, 2);
8765f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscUseMethod(snes, "SNESMultiblockGetSubSNES_C", (SNES, PetscInt*, SNES **), (snes, n, subsnes)));
877c7543cceSMatthew G Knepley   PetscFunctionReturn(0);
878c7543cceSMatthew G Knepley }
879c7543cceSMatthew G Knepley 
880c7543cceSMatthew G Knepley /*MC
881c7543cceSMatthew G Knepley   SNESMULTIBLOCK - Multiblock nonlinear solver that can use overlapping or nonoverlapping blocks, organized
882c7543cceSMatthew G Knepley   additively (Jacobi) or multiplicatively (Gauss-Seidel).
883c7543cceSMatthew G Knepley 
884c7543cceSMatthew G Knepley   Level: beginner
885c7543cceSMatthew G Knepley 
88604d7464bSBarry Smith .seealso:  SNESCreate(), SNES, SNESSetType(), SNESNEWTONLS, SNESNEWTONTR, SNESNRICHARDSON
887c7543cceSMatthew G Knepley M*/
8888cc058d9SJed Brown PETSC_EXTERN PetscErrorCode SNESCreate_Multiblock(SNES snes)
889c7543cceSMatthew G Knepley {
890c7543cceSMatthew G Knepley   SNES_Multiblock *mb;
891c7543cceSMatthew G Knepley 
892c7543cceSMatthew G Knepley   PetscFunctionBegin;
893c7543cceSMatthew G Knepley   snes->ops->destroy        = SNESDestroy_Multiblock;
894c7543cceSMatthew G Knepley   snes->ops->setup          = SNESSetUp_Multiblock;
895c7543cceSMatthew G Knepley   snes->ops->setfromoptions = SNESSetFromOptions_Multiblock;
896c7543cceSMatthew G Knepley   snes->ops->view           = SNESView_Multiblock;
897c7543cceSMatthew G Knepley   snes->ops->solve          = SNESSolve_Multiblock;
898c7543cceSMatthew G Knepley   snes->ops->reset          = SNESReset_Multiblock;
899c7543cceSMatthew G Knepley 
9002c155ee1SBarry Smith   snes->usesksp = PETSC_FALSE;
901d8d34be6SBarry Smith   snes->usesnpc = PETSC_FALSE;
9022c155ee1SBarry Smith 
9034fc747eaSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_TRUE;
9044fc747eaSLawrence Mitchell 
9055f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscNewLog(snes,&mb));
906c7543cceSMatthew G Knepley   snes->data    = (void*) mb;
907c7543cceSMatthew G Knepley   mb->defined   = PETSC_FALSE;
908c7543cceSMatthew G Knepley   mb->numBlocks = 0;
909c7543cceSMatthew G Knepley   mb->bs        = -1;
910c7543cceSMatthew G Knepley   mb->type      = PC_COMPOSITE_MULTIPLICATIVE;
911c7543cceSMatthew G Knepley 
912c7543cceSMatthew G Knepley   /* We attach functions so that they can be called on another PC without crashing the program */
9135f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject) snes, "SNESMultiblockSetFields_C",    SNESMultiblockSetFields_Default));
9145f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject) snes, "SNESMultiblockSetIS_C",        SNESMultiblockSetIS_Default));
9155f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject) snes, "SNESMultiblockSetType_C",      SNESMultiblockSetType_Default));
9165f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject) snes, "SNESMultiblockSetBlockSize_C", SNESMultiblockSetBlockSize_Default));
9175f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject) snes, "SNESMultiblockGetSubSNES_C",   SNESMultiblockGetSubSNES_Default));
918c7543cceSMatthew G Knepley   PetscFunctionReturn(0);
919c7543cceSMatthew G Knepley }
920