xref: /petsc/src/snes/impls/multiblock/multiblock.c (revision e4ed7901070ce1ca36eb7d68dd07557542e66e31)
1b45d2f2cSJed Brown #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 #undef __FUNCT__
27c7543cceSMatthew G Knepley #define __FUNCT__ "SNESReset_Multiblock"
28c7543cceSMatthew G Knepley PetscErrorCode SNESReset_Multiblock(SNES snes)
29c7543cceSMatthew G Knepley {
30c7543cceSMatthew G Knepley   SNES_Multiblock *mb     = (SNES_Multiblock *) snes->data;
31c7543cceSMatthew G Knepley   BlockDesc        blocks = mb->blocks, next;
32c7543cceSMatthew G Knepley   PetscErrorCode   ierr;
33c7543cceSMatthew G Knepley 
34c7543cceSMatthew G Knepley   PetscFunctionBegin;
35c7543cceSMatthew G Knepley   while (blocks) {
36c7543cceSMatthew G Knepley     ierr = SNESReset(blocks->snes);CHKERRQ(ierr);
370c74a584SJed Brown #if 0
380c74a584SJed Brown     ierr = VecDestroy(&blocks->x);CHKERRQ(ierr);
390c74a584SJed Brown #endif
40c7543cceSMatthew G Knepley     ierr = VecScatterDestroy(&blocks->sctx);CHKERRQ(ierr);
41c7543cceSMatthew G Knepley     ierr = ISDestroy(&blocks->is);CHKERRQ(ierr);
42c7543cceSMatthew G Knepley     next   = blocks->next;
43c7543cceSMatthew G Knepley     blocks = next;
44c7543cceSMatthew G Knepley   }
45c7543cceSMatthew G Knepley   PetscFunctionReturn(0);
46c7543cceSMatthew G Knepley }
47c7543cceSMatthew G Knepley 
48c7543cceSMatthew G Knepley /*
49c7543cceSMatthew G Knepley   SNESDestroy_Multiblock - Destroys the private SNES_Multiblock context that was created with SNESCreate_Multiblock().
50c7543cceSMatthew G Knepley 
51c7543cceSMatthew G Knepley   Input Parameter:
52c7543cceSMatthew G Knepley . snes - the SNES context
53c7543cceSMatthew G Knepley 
54c7543cceSMatthew G Knepley   Application Interface Routine: SNESDestroy()
55c7543cceSMatthew G Knepley */
56c7543cceSMatthew G Knepley #undef __FUNCT__
57c7543cceSMatthew G Knepley #define __FUNCT__ "SNESDestroy_Multiblock"
58c7543cceSMatthew G Knepley PetscErrorCode SNESDestroy_Multiblock(SNES snes)
59c7543cceSMatthew G Knepley {
60c7543cceSMatthew G Knepley   SNES_Multiblock *mb     = (SNES_Multiblock *) snes->data;
61c7543cceSMatthew G Knepley   BlockDesc        blocks = mb->blocks, next;
62c7543cceSMatthew G Knepley   PetscErrorCode   ierr;
63c7543cceSMatthew G Knepley 
64c7543cceSMatthew G Knepley   PetscFunctionBegin;
65c7543cceSMatthew G Knepley   ierr = SNESReset_Multiblock(snes);CHKERRQ(ierr);
66c7543cceSMatthew G Knepley   while (blocks) {
67c7543cceSMatthew G Knepley     next = blocks->next;
68c7543cceSMatthew G Knepley     ierr = SNESDestroy(&blocks->snes);CHKERRQ(ierr);
69c7543cceSMatthew G Knepley     ierr = PetscFree(blocks->name);CHKERRQ(ierr);
70c7543cceSMatthew G Knepley     ierr = PetscFree(blocks->fields);CHKERRQ(ierr);
71c7543cceSMatthew G Knepley     ierr = PetscFree(blocks);CHKERRQ(ierr);
72c7543cceSMatthew G Knepley     blocks = next;
73c7543cceSMatthew G Knepley   }
74c7543cceSMatthew G Knepley   ierr = PetscFree(snes->data);CHKERRQ(ierr);
75c7543cceSMatthew G Knepley   PetscFunctionReturn(0);
76c7543cceSMatthew G Knepley }
77c7543cceSMatthew G Knepley 
78c7543cceSMatthew G Knepley #undef __FUNCT__
79c7543cceSMatthew G Knepley #define __FUNCT__ "SNESMultiblockSetFieldsRuntime_Private"
80c7543cceSMatthew G Knepley /* Precondition: blocksize is set to a meaningful value */
81b665c654SMatthew G Knepley static PetscErrorCode SNESMultiblockSetFieldsRuntime_Private(SNES snes)
82c7543cceSMatthew G Knepley {
83c7543cceSMatthew G Knepley   SNES_Multiblock *mb = (SNES_Multiblock *) snes->data;
84c7543cceSMatthew G Knepley   PetscInt        *ifields;
85c7543cceSMatthew G Knepley   PetscInt         i, nfields;
86c7543cceSMatthew G Knepley   PetscBool        flg = PETSC_TRUE;
87c7543cceSMatthew G Knepley   char             optionname[128], name[8];
88c7543cceSMatthew G Knepley   PetscErrorCode   ierr;
89c7543cceSMatthew G Knepley 
90c7543cceSMatthew G Knepley   PetscFunctionBegin;
91c7543cceSMatthew G Knepley   ierr = PetscMalloc(mb->bs * sizeof(PetscInt), &ifields);CHKERRQ(ierr);
92c7543cceSMatthew G Knepley   for(i = 0; ; ++i) {
93c7543cceSMatthew G Knepley     ierr = PetscSNPrintf(name, sizeof name, "%D", i);CHKERRQ(ierr);
94c7543cceSMatthew G Knepley     ierr = PetscSNPrintf(optionname, sizeof optionname, "-snes_multiblock_%D_fields", i);CHKERRQ(ierr);
95c7543cceSMatthew G Knepley     nfields = mb->bs;
96c7543cceSMatthew G Knepley     ierr    = PetscOptionsGetIntArray(((PetscObject) snes)->prefix, optionname, ifields, &nfields, &flg);CHKERRQ(ierr);
97c7543cceSMatthew G Knepley     if (!flg) break;
98c7543cceSMatthew G Knepley     if (!nfields) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_USER, "Cannot list zero fields");
99b665c654SMatthew G Knepley     ierr = SNESMultiblockSetFields(snes, name, nfields, ifields);CHKERRQ(ierr);
100c7543cceSMatthew G Knepley   }
101c7543cceSMatthew G Knepley   if (i > 0) {
102c7543cceSMatthew G Knepley     /* Makes command-line setting of blocks take precedence over setting them in code.
103c7543cceSMatthew G Knepley        Otherwise subsequent calls to SNESMultiblockSetIS() or SNESMultiblockSetFields() would
104c7543cceSMatthew G Knepley        create new blocks, which would probably not be what the user wanted. */
105c7543cceSMatthew G Knepley     mb->defined = PETSC_TRUE;
106c7543cceSMatthew G Knepley   }
107c7543cceSMatthew G Knepley   ierr = PetscFree(ifields);CHKERRQ(ierr);
108c7543cceSMatthew G Knepley   PetscFunctionReturn(0);
109c7543cceSMatthew G Knepley }
110c7543cceSMatthew G Knepley 
111c7543cceSMatthew G Knepley #undef __FUNCT__
112c7543cceSMatthew G Knepley #define __FUNCT__ "SNESMultiblockSetDefaults"
113c7543cceSMatthew G Knepley static PetscErrorCode SNESMultiblockSetDefaults(SNES snes)
114c7543cceSMatthew G Knepley {
115c7543cceSMatthew G Knepley   SNES_Multiblock *mb = (SNES_Multiblock *) snes->data;
116c7543cceSMatthew G Knepley   BlockDesc        blocks = mb->blocks;
117c7543cceSMatthew G Knepley   PetscInt         i;
118c7543cceSMatthew G Knepley   PetscErrorCode   ierr;
119c7543cceSMatthew G Knepley 
120c7543cceSMatthew G Knepley   PetscFunctionBegin;
121c7543cceSMatthew G Knepley   if (!blocks) {
122c7543cceSMatthew G Knepley     if (snes->dm) {
123c7543cceSMatthew G Knepley       PetscBool dmcomposite;
124c7543cceSMatthew G Knepley 
125c7543cceSMatthew G Knepley       ierr = PetscTypeCompare((PetscObject) snes->dm, DMCOMPOSITE, &dmcomposite);CHKERRQ(ierr);
126c7543cceSMatthew G Knepley       if (dmcomposite) {
127c7543cceSMatthew G Knepley         PetscInt nDM;
128c7543cceSMatthew G Knepley         IS      *fields;
129c7543cceSMatthew G Knepley 
130b665c654SMatthew G Knepley         ierr = PetscInfo(snes,"Setting up physics based multiblock solver using the embedded DM\n");CHKERRQ(ierr);
131c7543cceSMatthew G Knepley         ierr = DMCompositeGetNumberDM(snes->dm, &nDM);CHKERRQ(ierr);
132c7543cceSMatthew G Knepley         ierr = DMCompositeGetGlobalISs(snes->dm, &fields);CHKERRQ(ierr);
133c7543cceSMatthew G Knepley         for(i = 0; i < nDM; ++i) {
134c7543cceSMatthew G Knepley           char name[8];
135c7543cceSMatthew G Knepley 
136c7543cceSMatthew G Knepley           ierr = PetscSNPrintf(name, sizeof name, "%D", i);CHKERRQ(ierr);
137c7543cceSMatthew G Knepley           ierr = SNESMultiblockSetIS(snes, name, fields[i]);CHKERRQ(ierr);
138c7543cceSMatthew G Knepley           ierr = ISDestroy(&fields[i]);CHKERRQ(ierr);
139c7543cceSMatthew G Knepley         }
140c7543cceSMatthew G Knepley         ierr = PetscFree(fields);CHKERRQ(ierr);
141c7543cceSMatthew G Knepley       }
142c7543cceSMatthew G Knepley     } else {
143c7543cceSMatthew G Knepley       PetscBool flg    = PETSC_FALSE;
144c7543cceSMatthew G Knepley       PetscBool stokes = PETSC_FALSE;
145c7543cceSMatthew G Knepley 
146c7543cceSMatthew G Knepley       if (mb->bs <= 0) {
147b665c654SMatthew G Knepley         if (snes->jacobian_pre) {
148b665c654SMatthew G Knepley           ierr = MatGetBlockSize(snes->jacobian_pre, &mb->bs);CHKERRQ(ierr);
149c7543cceSMatthew G Knepley         } else {
150c7543cceSMatthew G Knepley           mb->bs = 1;
151c7543cceSMatthew G Knepley         }
152c7543cceSMatthew G Knepley       }
153c7543cceSMatthew G Knepley 
154c7543cceSMatthew G Knepley       ierr = PetscOptionsGetBool(((PetscObject) snes)->prefix, "-snes_multiblock_default", &flg, PETSC_NULL);CHKERRQ(ierr);
155c7543cceSMatthew G Knepley       ierr = PetscOptionsGetBool(((PetscObject) snes)->prefix, "-snes_multiblock_detect_saddle_point", &stokes, PETSC_NULL);CHKERRQ(ierr);
156c7543cceSMatthew G Knepley       if (stokes) {
157c7543cceSMatthew G Knepley         IS       zerodiags, rest;
158c7543cceSMatthew G Knepley         PetscInt nmin, nmax;
159c7543cceSMatthew G Knepley 
160b665c654SMatthew G Knepley         ierr = MatGetOwnershipRange(snes->jacobian_pre, &nmin, &nmax);CHKERRQ(ierr);
161b665c654SMatthew G Knepley         ierr = MatFindZeroDiagonals(snes->jacobian_pre, &zerodiags);CHKERRQ(ierr);
162c7543cceSMatthew G Knepley         ierr = ISComplement(zerodiags, nmin, nmax, &rest);CHKERRQ(ierr);
163c7543cceSMatthew G Knepley         ierr = SNESMultiblockSetIS(snes, "0", rest);CHKERRQ(ierr);
164c7543cceSMatthew G Knepley         ierr = SNESMultiblockSetIS(snes, "1", zerodiags);CHKERRQ(ierr);
165c7543cceSMatthew G Knepley         ierr = ISDestroy(&zerodiags);CHKERRQ(ierr);
166c7543cceSMatthew G Knepley         ierr = ISDestroy(&rest);CHKERRQ(ierr);
167c7543cceSMatthew G Knepley       } else {
168c7543cceSMatthew G Knepley         if (!flg) {
169c7543cceSMatthew G Knepley           /* Allow user to set fields from command line, if bs was known at the time of SNESSetFromOptions_Multiblock()
170c7543cceSMatthew G Knepley            then it is set there. This is not ideal because we should only have options set in XXSetFromOptions(). */
171b665c654SMatthew G Knepley           ierr = SNESMultiblockSetFieldsRuntime_Private(snes);CHKERRQ(ierr);
172c7543cceSMatthew G Knepley           if (mb->defined) {ierr = PetscInfo(snes, "Blocks defined using the options database\n");CHKERRQ(ierr);}
173c7543cceSMatthew G Knepley         }
174c7543cceSMatthew G Knepley         if (flg || !mb->defined) {
175c7543cceSMatthew G Knepley           ierr = PetscInfo(snes, "Using default splitting of fields\n");CHKERRQ(ierr);
176c7543cceSMatthew G Knepley           for(i = 0; i < mb->bs; ++i) {
177c7543cceSMatthew G Knepley             char name[8];
178c7543cceSMatthew G Knepley 
179c7543cceSMatthew G Knepley             ierr = PetscSNPrintf(name, sizeof name, "%D", i);CHKERRQ(ierr);
180c7543cceSMatthew G Knepley             ierr = SNESMultiblockSetFields(snes, name, 1, &i);CHKERRQ(ierr);
181c7543cceSMatthew G Knepley           }
182c7543cceSMatthew G Knepley           mb->defaultblocks = PETSC_TRUE;
183c7543cceSMatthew G Knepley         }
184c7543cceSMatthew G Knepley       }
185c7543cceSMatthew G Knepley     }
186c7543cceSMatthew G Knepley   } else if (mb->numBlocks == 1) {
187c7543cceSMatthew G Knepley     if (blocks->is) {
188c7543cceSMatthew G Knepley       IS       is2;
189c7543cceSMatthew G Knepley       PetscInt nmin, nmax;
190c7543cceSMatthew G Knepley 
191b665c654SMatthew G Knepley       ierr = MatGetOwnershipRange(snes->jacobian_pre, &nmin, &nmax);CHKERRQ(ierr);
192c7543cceSMatthew G Knepley       ierr = ISComplement(blocks->is, nmin, nmax, &is2);CHKERRQ(ierr);
193c7543cceSMatthew G Knepley       ierr = SNESMultiblockSetIS(snes, "1", is2);CHKERRQ(ierr);
194c7543cceSMatthew G Knepley       ierr = ISDestroy(&is2);CHKERRQ(ierr);
195c7543cceSMatthew G Knepley     } else {
196c7543cceSMatthew G Knepley       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must provide at least two sets of fields to SNES multiblock");
197c7543cceSMatthew G Knepley     }
198c7543cceSMatthew G Knepley   }
199c7543cceSMatthew G Knepley   if (mb->numBlocks < 2) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unhandled case, must have at least two blocks");
200c7543cceSMatthew G Knepley   PetscFunctionReturn(0);
201c7543cceSMatthew G Knepley }
202c7543cceSMatthew G Knepley 
203c7543cceSMatthew G Knepley /*
204c7543cceSMatthew G Knepley    SNESSetUp_Multiblock - Sets up the internal data structures for the later use
205c7543cceSMatthew G Knepley    of the SNESMULTIBLOCK nonlinear solver.
206c7543cceSMatthew G Knepley 
207c7543cceSMatthew G Knepley    Input Parameters:
208c7543cceSMatthew G Knepley +  snes - the SNES context
209c7543cceSMatthew G Knepley -  x - the solution vector
210c7543cceSMatthew G Knepley 
211c7543cceSMatthew G Knepley    Application Interface Routine: SNESSetUp()
212c7543cceSMatthew G Knepley */
213c7543cceSMatthew G Knepley #undef __FUNCT__
214c7543cceSMatthew G Knepley #define __FUNCT__ "SNESSetUp_Multiblock"
215c7543cceSMatthew G Knepley PetscErrorCode SNESSetUp_Multiblock(SNES snes)
216c7543cceSMatthew G Knepley {
217c7543cceSMatthew G Knepley   SNES_Multiblock *mb = (SNES_Multiblock *) snes->data;
218c7543cceSMatthew G Knepley   BlockDesc        blocks;
219c7543cceSMatthew G Knepley   PetscInt         i, numBlocks;
220c7543cceSMatthew G Knepley   PetscErrorCode   ierr;
221c7543cceSMatthew G Knepley 
222c7543cceSMatthew G Knepley   PetscFunctionBegin;
223c7543cceSMatthew G Knepley   /* ierr = SNESDefaultGetWork(snes, 1);CHKERRQ(ierr); */
224b665c654SMatthew G Knepley   ierr = SNESMultiblockSetDefaults(snes);CHKERRQ(ierr);
225c7543cceSMatthew G Knepley   numBlocks = mb->numBlocks;
226b665c654SMatthew G Knepley   blocks    = mb->blocks;
227c7543cceSMatthew G Knepley 
228c7543cceSMatthew G Knepley   /* Create ISs */
229c7543cceSMatthew G Knepley   if (!mb->issetup) {
230c7543cceSMatthew G Knepley     PetscInt  ccsize, rstart, rend, nslots, bs;
231c7543cceSMatthew G Knepley     PetscBool sorted;
232c7543cceSMatthew G Knepley 
233c7543cceSMatthew G Knepley     mb->issetup = PETSC_TRUE;
234c7543cceSMatthew G Knepley     bs     = mb->bs;
235b665c654SMatthew G Knepley     ierr   = MatGetOwnershipRange(snes->jacobian_pre, &rstart, &rend);CHKERRQ(ierr);
236b665c654SMatthew G Knepley     ierr   = MatGetLocalSize(snes->jacobian_pre, PETSC_NULL, &ccsize);CHKERRQ(ierr);
237c7543cceSMatthew G Knepley     nslots = (rend - rstart)/bs;
238c7543cceSMatthew G Knepley     for(i = 0; i < numBlocks; ++i) {
239b665c654SMatthew G Knepley       if (mb->defaultblocks) {
240c7543cceSMatthew G Knepley         ierr = ISCreateStride(((PetscObject) snes)->comm, nslots, rstart+i, numBlocks, &blocks->is);CHKERRQ(ierr);
241c7543cceSMatthew G Knepley       } else if (!blocks->is) {
242c7543cceSMatthew G Knepley         if (blocks->nfields > 1) {
243c7543cceSMatthew G Knepley           PetscInt *ii, j, k, nfields = blocks->nfields, *fields = blocks->fields;
244c7543cceSMatthew G Knepley 
245c7543cceSMatthew G Knepley           ierr = PetscMalloc(nfields*nslots*sizeof(PetscInt), &ii);CHKERRQ(ierr);
246c7543cceSMatthew G Knepley           for(j = 0; j < nslots; ++j) {
247c7543cceSMatthew G Knepley             for(k = 0; k < nfields; ++k) {
248c7543cceSMatthew G Knepley               ii[nfields*j + k] = rstart + bs*j + fields[k];
249c7543cceSMatthew G Knepley             }
250c7543cceSMatthew G Knepley           }
251c7543cceSMatthew G Knepley           ierr = ISCreateGeneral(((PetscObject) snes)->comm, nslots*nfields, ii, PETSC_OWN_POINTER, &blocks->is);CHKERRQ(ierr);
252c7543cceSMatthew G Knepley         } else {
253c7543cceSMatthew G Knepley           ierr = ISCreateStride(((PetscObject) snes)->comm, nslots, rstart+blocks->fields[0], bs, &blocks->is);CHKERRQ(ierr);
254c7543cceSMatthew G Knepley         }
255c7543cceSMatthew G Knepley       }
256c7543cceSMatthew G Knepley       ierr = ISSorted(blocks->is, &sorted);CHKERRQ(ierr);
257c7543cceSMatthew G Knepley       if (!sorted) {SETERRQ(PETSC_COMM_SELF, PETSC_ERR_USER, "Fields must be sorted when creating split");}
258c7543cceSMatthew G Knepley       blocks = blocks->next;
259c7543cceSMatthew G Knepley     }
260c7543cceSMatthew G Knepley   }
261c7543cceSMatthew G Knepley 
262c7543cceSMatthew G Knepley #if 0
263c7543cceSMatthew G Knepley   /* Create matrices */
264c7543cceSMatthew G Knepley   ilink  = jac->head;
265c7543cceSMatthew G Knepley   if (!jac->pmat) {
266c7543cceSMatthew G Knepley     ierr = PetscMalloc(nsplit*sizeof(Mat),&jac->pmat);CHKERRQ(ierr);
267c7543cceSMatthew G Knepley     for (i=0; i<nsplit; i++) {
268c7543cceSMatthew G Knepley       ierr = MatGetSubMatrix(pc->pmat,ilink->is,ilink->is,MAT_INITIAL_MATRIX,&jac->pmat[i]);CHKERRQ(ierr);
269c7543cceSMatthew G Knepley       ilink = ilink->next;
270c7543cceSMatthew G Knepley     }
271c7543cceSMatthew G Knepley   } else {
272c7543cceSMatthew G Knepley     for (i=0; i<nsplit; i++) {
273c7543cceSMatthew G Knepley       ierr = MatGetSubMatrix(pc->pmat,ilink->is,ilink->is,MAT_REUSE_MATRIX,&jac->pmat[i]);CHKERRQ(ierr);
274c7543cceSMatthew G Knepley       ilink = ilink->next;
275c7543cceSMatthew G Knepley     }
276c7543cceSMatthew G Knepley   }
277c7543cceSMatthew G Knepley   if (jac->realdiagonal) {
278c7543cceSMatthew G Knepley     ilink = jac->head;
279c7543cceSMatthew G Knepley     if (!jac->mat) {
280c7543cceSMatthew G Knepley       ierr = PetscMalloc(nsplit*sizeof(Mat),&jac->mat);CHKERRQ(ierr);
281c7543cceSMatthew G Knepley       for (i=0; i<nsplit; i++) {
282c7543cceSMatthew G Knepley         ierr = MatGetSubMatrix(pc->mat,ilink->is,ilink->is,MAT_INITIAL_MATRIX,&jac->mat[i]);CHKERRQ(ierr);
283c7543cceSMatthew G Knepley         ilink = ilink->next;
284c7543cceSMatthew G Knepley       }
285c7543cceSMatthew G Knepley     } else {
286c7543cceSMatthew G Knepley       for (i=0; i<nsplit; i++) {
287c7543cceSMatthew G Knepley         if (jac->mat[i]) {ierr = MatGetSubMatrix(pc->mat,ilink->is,ilink->is,MAT_REUSE_MATRIX,&jac->mat[i]);CHKERRQ(ierr);}
288c7543cceSMatthew G Knepley         ilink = ilink->next;
289c7543cceSMatthew G Knepley       }
290c7543cceSMatthew G Knepley     }
291c7543cceSMatthew G Knepley   } else {
292c7543cceSMatthew G Knepley     jac->mat = jac->pmat;
293c7543cceSMatthew G Knepley   }
294c7543cceSMatthew G Knepley #endif
295c7543cceSMatthew G Knepley 
296c7543cceSMatthew G Knepley #if 0
297c7543cceSMatthew G Knepley   if (jac->type != PC_COMPOSITE_ADDITIVE  && jac->type != PC_COMPOSITE_SCHUR) {
298c7543cceSMatthew G Knepley     /* extract the rows of the matrix associated with each field: used for efficient computation of residual inside algorithm */
299c7543cceSMatthew G Knepley     ilink  = jac->head;
300c7543cceSMatthew G Knepley     if (!jac->Afield) {
301c7543cceSMatthew G Knepley       ierr = PetscMalloc(nsplit*sizeof(Mat),&jac->Afield);CHKERRQ(ierr);
302c7543cceSMatthew G Knepley       for (i=0; i<nsplit; i++) {
303c7543cceSMatthew G Knepley         ierr = MatGetSubMatrix(pc->mat,ilink->is,PETSC_NULL,MAT_INITIAL_MATRIX,&jac->Afield[i]);CHKERRQ(ierr);
304c7543cceSMatthew G Knepley         ilink = ilink->next;
305c7543cceSMatthew G Knepley       }
306c7543cceSMatthew G Knepley     } else {
307c7543cceSMatthew G Knepley       for (i=0; i<nsplit; i++) {
308c7543cceSMatthew G Knepley         ierr = MatGetSubMatrix(pc->mat,ilink->is,PETSC_NULL,MAT_REUSE_MATRIX,&jac->Afield[i]);CHKERRQ(ierr);
309c7543cceSMatthew G Knepley         ilink = ilink->next;
310c7543cceSMatthew G Knepley       }
311c7543cceSMatthew G Knepley     }
312c7543cceSMatthew G Knepley   }
313c7543cceSMatthew G Knepley #endif
314c7543cceSMatthew G Knepley 
315b665c654SMatthew G Knepley   if (mb->type == PC_COMPOSITE_SCHUR) {
316c7543cceSMatthew G Knepley #if 0
317c7543cceSMatthew G Knepley     IS       ccis;
318c7543cceSMatthew G Knepley     PetscInt rstart,rend;
319c7543cceSMatthew G Knepley     if (nsplit != 2) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_INCOMP,"To use Schur complement preconditioner you must have exactly 2 fields");
320c7543cceSMatthew G Knepley 
321c7543cceSMatthew G Knepley     /* When extracting off-diagonal submatrices, we take complements from this range */
322c7543cceSMatthew G Knepley     ierr  = MatGetOwnershipRangeColumn(pc->mat,&rstart,&rend);CHKERRQ(ierr);
323c7543cceSMatthew G Knepley 
324c7543cceSMatthew G Knepley     /* need to handle case when one is resetting up the preconditioner */
325c7543cceSMatthew G Knepley     if (jac->schur) {
326c7543cceSMatthew G Knepley       ilink = jac->head;
327c7543cceSMatthew G Knepley       ierr  = ISComplement(ilink->is,rstart,rend,&ccis);CHKERRQ(ierr);
328c7543cceSMatthew G Knepley       ierr  = MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_REUSE_MATRIX,&jac->B);CHKERRQ(ierr);
329c7543cceSMatthew G Knepley       ierr  = ISDestroy(&ccis);CHKERRQ(ierr);
330c7543cceSMatthew G Knepley       ilink = ilink->next;
331c7543cceSMatthew G Knepley       ierr  = ISComplement(ilink->is,rstart,rend,&ccis);CHKERRQ(ierr);
332c7543cceSMatthew G Knepley       ierr  = MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_REUSE_MATRIX,&jac->C);CHKERRQ(ierr);
333c7543cceSMatthew G Knepley       ierr  = ISDestroy(&ccis);CHKERRQ(ierr);
334c7543cceSMatthew G Knepley       ierr  = MatSchurComplementUpdate(jac->schur,jac->mat[0],jac->pmat[0],jac->B,jac->C,jac->pmat[1],pc->flag);CHKERRQ(ierr);
335c7543cceSMatthew G Knepley       ierr  = KSPSetOperators(jac->kspschur,jac->schur,FieldSplitSchurPre(jac),pc->flag);CHKERRQ(ierr);
336c7543cceSMatthew G Knepley 
337c7543cceSMatthew G Knepley      } else {
338c7543cceSMatthew G Knepley       KSP ksp;
339c7543cceSMatthew G Knepley       char schurprefix[256];
340c7543cceSMatthew G Knepley 
341c7543cceSMatthew G Knepley       /* extract the A01 and A10 matrices */
342c7543cceSMatthew G Knepley       ilink = jac->head;
343c7543cceSMatthew G Knepley       ierr  = ISComplement(ilink->is,rstart,rend,&ccis);CHKERRQ(ierr);
344c7543cceSMatthew G Knepley       ierr  = MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->B);CHKERRQ(ierr);
345c7543cceSMatthew G Knepley       ierr  = ISDestroy(&ccis);CHKERRQ(ierr);
346c7543cceSMatthew G Knepley       ilink = ilink->next;
347c7543cceSMatthew G Knepley       ierr  = ISComplement(ilink->is,rstart,rend,&ccis);CHKERRQ(ierr);
348c7543cceSMatthew G Knepley       ierr  = MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->C);CHKERRQ(ierr);
349c7543cceSMatthew G Knepley       ierr  = ISDestroy(&ccis);CHKERRQ(ierr);
350c7543cceSMatthew G Knepley       /* Use mat[0] (diagonal block of the real matrix) preconditioned by pmat[0] */
351c7543cceSMatthew G Knepley       ierr  = MatCreateSchurComplement(jac->mat[0],jac->pmat[0],jac->B,jac->C,jac->mat[1],&jac->schur);CHKERRQ(ierr);
352c7543cceSMatthew G Knepley       /* set tabbing and options prefix of KSP inside the MatSchur */
353c7543cceSMatthew G Knepley       ierr  = MatSchurComplementGetKSP(jac->schur,&ksp);CHKERRQ(ierr);
354c7543cceSMatthew G Knepley       ierr  = PetscObjectIncrementTabLevel((PetscObject)ksp,(PetscObject)pc,2);CHKERRQ(ierr);
355c7543cceSMatthew G Knepley       ierr  = PetscSNPrintf(schurprefix,sizeof schurprefix,"%sfieldsplit_%s_",((PetscObject)pc)->prefix?((PetscObject)pc)->prefix:"",jac->head->splitname);CHKERRQ(ierr);
356c7543cceSMatthew G Knepley       ierr  = KSPSetOptionsPrefix(ksp,schurprefix);CHKERRQ(ierr);
357c7543cceSMatthew G Knepley       ierr  = MatSetFromOptions(jac->schur);CHKERRQ(ierr);
358c7543cceSMatthew G Knepley 
359c7543cceSMatthew G Knepley       ierr  = KSPCreate(((PetscObject)pc)->comm,&jac->kspschur);CHKERRQ(ierr);
360c7543cceSMatthew G Knepley       ierr  = PetscLogObjectParent((PetscObject)pc,(PetscObject)jac->kspschur);CHKERRQ(ierr);
361c7543cceSMatthew G Knepley       ierr  = PetscObjectIncrementTabLevel((PetscObject)jac->kspschur,(PetscObject)pc,1);CHKERRQ(ierr);
362c7543cceSMatthew G Knepley       ierr  = KSPSetOperators(jac->kspschur,jac->schur,FieldSplitSchurPre(jac),DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
363c7543cceSMatthew G Knepley       if (jac->schurpre == PC_FIELDSPLIT_SCHUR_PRE_SELF) {
364c7543cceSMatthew G Knepley         PC pc;
365c7543cceSMatthew G Knepley         ierr = KSPGetPC(jac->kspschur,&pc);CHKERRQ(ierr);
366c7543cceSMatthew G Knepley         ierr = PCSetType(pc,PCNONE);CHKERRQ(ierr);
367c7543cceSMatthew G Knepley         /* Note: This is bad if there exist preconditioners for MATSCHURCOMPLEMENT */
368c7543cceSMatthew G Knepley       }
369c7543cceSMatthew G Knepley       ierr = PetscSNPrintf(schurprefix,sizeof schurprefix,"%sfieldsplit_%s_",((PetscObject)pc)->prefix?((PetscObject)pc)->prefix:"",ilink->splitname);CHKERRQ(ierr);
370c7543cceSMatthew G Knepley       ierr  = KSPSetOptionsPrefix(jac->kspschur,schurprefix);CHKERRQ(ierr);
371c7543cceSMatthew G Knepley       /* really want setfromoptions called in PCSetFromOptions_FieldSplit(), but it is not ready yet */
372c7543cceSMatthew G Knepley       ierr = KSPSetFromOptions(jac->kspschur);CHKERRQ(ierr);
373c7543cceSMatthew G Knepley 
374c7543cceSMatthew G Knepley       ierr = PetscMalloc2(2,Vec,&jac->x,2,Vec,&jac->y);CHKERRQ(ierr);
375c7543cceSMatthew G Knepley       ierr = MatGetVecs(jac->pmat[0],&jac->x[0],&jac->y[0]);CHKERRQ(ierr);
376c7543cceSMatthew G Knepley       ierr = MatGetVecs(jac->pmat[1],&jac->x[1],&jac->y[1]);CHKERRQ(ierr);
377c7543cceSMatthew G Knepley       ilink = jac->head;
378c7543cceSMatthew G Knepley       ilink->x = jac->x[0]; ilink->y = jac->y[0];
379c7543cceSMatthew G Knepley       ilink = ilink->next;
380c7543cceSMatthew G Knepley       ilink->x = jac->x[1]; ilink->y = jac->y[1];
381c7543cceSMatthew G Knepley     }
382c7543cceSMatthew G Knepley #endif
383c7543cceSMatthew G Knepley   } else {
384c7543cceSMatthew G Knepley     /* Set up the individual SNESs */
385c7543cceSMatthew G Knepley     blocks = mb->blocks;
386c7543cceSMatthew G Knepley     i      = 0;
387c7543cceSMatthew G Knepley     while (blocks) {
388b665c654SMatthew G Knepley       /*TODO: Set these correctly */
389b665c654SMatthew G Knepley       /*ierr = SNESSetFunction(blocks->snes, blocks->x, func);CHKERRQ(ierr);*/
390b665c654SMatthew G Knepley       /*ierr = SNESSetJacobian(blocks->snes, blocks->x, jac);CHKERRQ(ierr);*/
391b665c654SMatthew G Knepley       ierr = VecDuplicate(blocks->snes->vec_sol, &blocks->x);CHKERRQ(ierr);
392c7543cceSMatthew G Knepley       /* really want setfromoptions called in SNESSetFromOptions_Multiblock(), but it is not ready yet */
393c7543cceSMatthew G Knepley       ierr = SNESSetFromOptions(blocks->snes);CHKERRQ(ierr);
394c7543cceSMatthew G Knepley       ierr = SNESSetUp(blocks->snes);CHKERRQ(ierr);
395c7543cceSMatthew G Knepley       blocks = blocks->next;
396c7543cceSMatthew G Knepley       i++;
397c7543cceSMatthew G Knepley     }
398c7543cceSMatthew G Knepley   }
399c7543cceSMatthew G Knepley 
400c7543cceSMatthew G Knepley   /* Compute scatter contexts needed by multiplicative versions and non-default splits */
401c7543cceSMatthew G Knepley   if (!mb->blocks->sctx) {
402c7543cceSMatthew G Knepley     Vec xtmp;
403c7543cceSMatthew G Knepley 
404c7543cceSMatthew G Knepley     blocks = mb->blocks;
405b665c654SMatthew G Knepley     ierr = MatGetVecs(snes->jacobian_pre, &xtmp, PETSC_NULL);CHKERRQ(ierr);
406c7543cceSMatthew G Knepley     while(blocks) {
407c7543cceSMatthew G Knepley       ierr = VecScatterCreate(xtmp, blocks->is, blocks->x, PETSC_NULL, &blocks->sctx);CHKERRQ(ierr);
408c7543cceSMatthew G Knepley       blocks = blocks->next;
409c7543cceSMatthew G Knepley     }
410c7543cceSMatthew G Knepley     ierr = VecDestroy(&xtmp);CHKERRQ(ierr);
411c7543cceSMatthew G Knepley   }
412c7543cceSMatthew G Knepley   PetscFunctionReturn(0);
413c7543cceSMatthew G Knepley }
414c7543cceSMatthew G Knepley 
415c7543cceSMatthew G Knepley /*
416c7543cceSMatthew G Knepley   SNESSetFromOptions_Multiblock - Sets various parameters for the SNESMULTIBLOCK method.
417c7543cceSMatthew G Knepley 
418c7543cceSMatthew G Knepley   Input Parameter:
419c7543cceSMatthew G Knepley . snes - the SNES context
420c7543cceSMatthew G Knepley 
421c7543cceSMatthew G Knepley   Application Interface Routine: SNESSetFromOptions()
422c7543cceSMatthew G Knepley */
423c7543cceSMatthew G Knepley #undef __FUNCT__
424c7543cceSMatthew G Knepley #define __FUNCT__ "SNESSetFromOptions_Multiblock"
425c7543cceSMatthew G Knepley static PetscErrorCode SNESSetFromOptions_Multiblock(SNES snes)
426c7543cceSMatthew G Knepley {
427c7543cceSMatthew G Knepley   SNES_Multiblock *mb = (SNES_Multiblock *) snes->data;
428c7543cceSMatthew G Knepley   PCCompositeType  ctype;
429c7543cceSMatthew G Knepley   PetscInt         bs;
430c7543cceSMatthew G Knepley   PetscBool        flg;
431c7543cceSMatthew G Knepley   PetscErrorCode   ierr;
432c7543cceSMatthew G Knepley 
433c7543cceSMatthew G Knepley   PetscFunctionBegin;
434c7543cceSMatthew G Knepley   ierr = PetscOptionsHead("SNES Multiblock options");CHKERRQ(ierr);
435c7543cceSMatthew G Knepley   ierr = PetscOptionsInt("-snes_multiblock_block_size", "Blocksize that defines number of fields", "PCFieldSplitSetBlockSize", mb->bs, &bs, &flg);CHKERRQ(ierr);
436b665c654SMatthew G Knepley   if (flg) {ierr = SNESMultiblockSetBlockSize(snes, bs);CHKERRQ(ierr);}
437c7543cceSMatthew G Knepley   ierr = PetscOptionsEnum("-snes_multiblock_type", "Type of composition", "PCFieldSplitSetType", PCCompositeTypes, (PetscEnum) mb->type, (PetscEnum *) &ctype, &flg);CHKERRQ(ierr);
438c7543cceSMatthew G Knepley   if (flg) {
439b665c654SMatthew G Knepley     ierr = SNESMultiblockSetType(snes,ctype);CHKERRQ(ierr);
440c7543cceSMatthew G Knepley   }
441c7543cceSMatthew G Knepley   /* Only setup fields once */
442b665c654SMatthew G Knepley   if ((mb->bs > 0) && (mb->numBlocks == 0)) {
443c7543cceSMatthew G Knepley     /* only allow user to set fields from command line if bs is already known, otherwise user can set them in SNESMultiblockSetDefaults() */
444b665c654SMatthew G Knepley     ierr = SNESMultiblockSetFieldsRuntime_Private(snes);CHKERRQ(ierr);
445b665c654SMatthew G Knepley     if (mb->defined) {ierr = PetscInfo(snes, "Blocks defined using the options database\n");CHKERRQ(ierr);}
446c7543cceSMatthew G Knepley   }
447c7543cceSMatthew G Knepley   ierr = PetscOptionsTail();CHKERRQ(ierr);
448c7543cceSMatthew G Knepley   PetscFunctionReturn(0);
449c7543cceSMatthew G Knepley }
450c7543cceSMatthew G Knepley 
451c7543cceSMatthew G Knepley /*
452c7543cceSMatthew G Knepley   SNESView_Multiblock - Prints info from the SNESMULTIBLOCK data structure.
453c7543cceSMatthew G Knepley 
454c7543cceSMatthew G Knepley   Input Parameters:
455c7543cceSMatthew G Knepley + SNES - the SNES context
456c7543cceSMatthew G Knepley - viewer - visualization context
457c7543cceSMatthew G Knepley 
458c7543cceSMatthew G Knepley   Application Interface Routine: SNESView()
459c7543cceSMatthew G Knepley */
460c7543cceSMatthew G Knepley #undef __FUNCT__
461c7543cceSMatthew G Knepley #define __FUNCT__ "SNESView_Multiblock"
462c7543cceSMatthew G Knepley static PetscErrorCode SNESView_Multiblock(SNES snes, PetscViewer viewer)
463c7543cceSMatthew G Knepley {
464c7543cceSMatthew G Knepley   SNES_Multiblock *mb = (SNES_Multiblock *) snes->data;
465c7543cceSMatthew G Knepley   BlockDesc        blocks = mb->blocks;
466c7543cceSMatthew G Knepley   PetscBool        iascii;
467c7543cceSMatthew G Knepley   PetscErrorCode   ierr;
468c7543cceSMatthew G Knepley 
469c7543cceSMatthew G Knepley   PetscFunctionBegin;
470c7543cceSMatthew G Knepley   ierr = PetscTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
471c7543cceSMatthew G Knepley   if (iascii) {
472c7543cceSMatthew G Knepley     ierr = PetscViewerASCIIPrintf(viewer,"  Multiblock with %s composition: total blocks = %D, blocksize = %D\n", PCCompositeTypes[mb->type], mb->numBlocks, mb->bs);CHKERRQ(ierr);
473c7543cceSMatthew G Knepley     ierr = PetscViewerASCIIPrintf(viewer,"  Solver info for each split is in the following SNES objects:\n");CHKERRQ(ierr);
474c7543cceSMatthew G Knepley     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
475c7543cceSMatthew G Knepley     while (blocks) {
476c7543cceSMatthew G Knepley       if (blocks->fields) {
477c7543cceSMatthew G Knepley         PetscInt j;
478c7543cceSMatthew G Knepley 
479c7543cceSMatthew G Knepley 	ierr = PetscViewerASCIIPrintf(viewer, "Block %s Fields ", blocks->name);CHKERRQ(ierr);
480c7543cceSMatthew G Knepley 	ierr = PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);CHKERRQ(ierr);
481c7543cceSMatthew G Knepley 	for(j = 0; j < blocks->nfields; ++j) {
482c7543cceSMatthew G Knepley 	  if (j > 0) {
483c7543cceSMatthew G Knepley 	    ierr = PetscViewerASCIIPrintf(viewer, ",");CHKERRQ(ierr);
484c7543cceSMatthew G Knepley 	  }
485c7543cceSMatthew G Knepley 	  ierr = PetscViewerASCIIPrintf(viewer, " %D", blocks->fields[j]);CHKERRQ(ierr);
486c7543cceSMatthew G Knepley 	}
487c7543cceSMatthew G Knepley 	ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr);
488c7543cceSMatthew G Knepley         ierr = PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);CHKERRQ(ierr);
489c7543cceSMatthew G Knepley       } else {
490b665c654SMatthew G Knepley 	ierr = PetscViewerASCIIPrintf(viewer, "Block %s Defined by IS\n", blocks->name);CHKERRQ(ierr);
491c7543cceSMatthew G Knepley       }
492c7543cceSMatthew G Knepley       ierr = SNESView(blocks->snes, viewer);CHKERRQ(ierr);
493c7543cceSMatthew G Knepley       blocks = blocks->next;
494c7543cceSMatthew G Knepley     }
495c7543cceSMatthew G Knepley     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
496c7543cceSMatthew G Knepley   }
497c7543cceSMatthew G Knepley   PetscFunctionReturn(0);
498c7543cceSMatthew G Knepley }
499c7543cceSMatthew G Knepley 
500c7543cceSMatthew G Knepley /*
501c7543cceSMatthew G Knepley   SNESSolve_Multiblock - Solves a nonlinear system with the Multiblock method.
502c7543cceSMatthew G Knepley 
503c7543cceSMatthew G Knepley   Input Parameters:
504c7543cceSMatthew G Knepley . snes - the SNES context
505c7543cceSMatthew G Knepley 
506c7543cceSMatthew G Knepley   Output Parameter:
507c7543cceSMatthew G Knepley . outits - number of iterations until termination
508c7543cceSMatthew G Knepley 
509c7543cceSMatthew G Knepley   Application Interface Routine: SNESSolve()
510c7543cceSMatthew G Knepley */
511c7543cceSMatthew G Knepley #undef __FUNCT__
512c7543cceSMatthew G Knepley #define __FUNCT__ "SNESSolve_Multiblock"
513c7543cceSMatthew G Knepley PetscErrorCode SNESSolve_Multiblock(SNES snes)
514c7543cceSMatthew G Knepley {
515c7543cceSMatthew G Knepley   SNES_Multiblock *mb = (SNES_Multiblock *) snes->data;
516c7543cceSMatthew G Knepley   Vec              X, Y, F;
517c7543cceSMatthew G Knepley   PetscReal        fnorm;
518c7543cceSMatthew G Knepley   PetscInt         maxits, i;
519c7543cceSMatthew G Knepley   PetscErrorCode   ierr;
520c7543cceSMatthew G Knepley 
521c7543cceSMatthew G Knepley   PetscFunctionBegin;
522c7543cceSMatthew G Knepley   snes->reason = SNES_CONVERGED_ITERATING;
523c7543cceSMatthew G Knepley 
524c7543cceSMatthew G Knepley   maxits = snes->max_its;	 /* maximum number of iterations */
525c7543cceSMatthew G Knepley   X      = snes->vec_sol;	 /* X^n */
526c7543cceSMatthew G Knepley   Y      = snes->vec_sol_update; /* \tilde X */
527c7543cceSMatthew G Knepley   F      = snes->vec_func;       /* residual vector */
528c7543cceSMatthew G Knepley 
529c7543cceSMatthew G Knepley   ierr = VecSetBlockSize(X, mb->bs);CHKERRQ(ierr);
530c7543cceSMatthew G Knepley   ierr = VecSetBlockSize(Y, mb->bs);CHKERRQ(ierr);
531c7543cceSMatthew G Knepley   ierr = VecSetBlockSize(F, mb->bs);CHKERRQ(ierr);
532c7543cceSMatthew G Knepley   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
533c7543cceSMatthew G Knepley   snes->iter = 0;
534c7543cceSMatthew G Knepley   snes->norm = 0.;
535c7543cceSMatthew G Knepley   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
536*e4ed7901SPeter Brune 
537*e4ed7901SPeter Brune   if (!snes->vec_func_init_set){
538c7543cceSMatthew G Knepley     ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr);
539c7543cceSMatthew G Knepley     if (snes->domainerror) {
540c7543cceSMatthew G Knepley       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
541c7543cceSMatthew G Knepley       PetscFunctionReturn(0);
542c7543cceSMatthew G Knepley     }
543*e4ed7901SPeter Brune   } else {
544*e4ed7901SPeter Brune     snes->vec_func_init_set = PETSC_FALSE;
545*e4ed7901SPeter Brune   }
546*e4ed7901SPeter Brune   if (!snes->norm_init_set) {
547c7543cceSMatthew G Knepley     ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); /* fnorm <- ||F||  */
548c7543cceSMatthew G Knepley     if (PetscIsInfOrNanReal(fnorm)) {SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Infinite or not-a-number generated in norm");}
549*e4ed7901SPeter Brune   } else {
550*e4ed7901SPeter Brune     fnorm = snes->norm_init;
551*e4ed7901SPeter Brune     snes->norm_init_set = PETSC_FALSE;
552*e4ed7901SPeter Brune   }
553c7543cceSMatthew G Knepley   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
554c7543cceSMatthew G Knepley   snes->norm = fnorm;
555c7543cceSMatthew G Knepley   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
556c7543cceSMatthew G Knepley   SNESLogConvHistory(snes,fnorm,0);
557c7543cceSMatthew G Knepley   ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr);
558c7543cceSMatthew G Knepley 
559c7543cceSMatthew G Knepley   /* set parameter for default relative tolerance convergence test */
560c7543cceSMatthew G Knepley   snes->ttol = fnorm*snes->rtol;
561c7543cceSMatthew G Knepley   /* test convergence */
562c7543cceSMatthew G Knepley   ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
563c7543cceSMatthew G Knepley   if (snes->reason) PetscFunctionReturn(0);
564c7543cceSMatthew G Knepley 
565c7543cceSMatthew G Knepley   for(i = 0; i < maxits; i++) {
566c7543cceSMatthew G Knepley     /* Call general purpose update function */
567c7543cceSMatthew G Knepley     if (snes->ops->update) {
568c7543cceSMatthew G Knepley       ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
569c7543cceSMatthew G Knepley     }
570c7543cceSMatthew G Knepley     /* Compute X^{new} from subsolves */
571c7543cceSMatthew G Knepley     if (mb->type == PC_COMPOSITE_ADDITIVE) {
572c7543cceSMatthew G Knepley       BlockDesc blocks = mb->blocks;
573c7543cceSMatthew G Knepley 
574b665c654SMatthew G Knepley       if (mb->defaultblocks) {
575b665c654SMatthew G Knepley         /*TODO: Make an array of Vecs for this */
576b665c654SMatthew G Knepley         /*ierr = VecStrideGatherAll(X, mb->x, INSERT_VALUES);CHKERRQ(ierr);*/
577c7543cceSMatthew G Knepley         while (blocks) {
578c7543cceSMatthew G Knepley           ierr = SNESSolve(blocks->snes, PETSC_NULL, blocks->x);CHKERRQ(ierr);
579c7543cceSMatthew G Knepley           blocks = blocks->next;
580c7543cceSMatthew G Knepley         }
581b665c654SMatthew G Knepley         /*ierr = VecStrideScatterAll(mb->x, X, INSERT_VALUES);CHKERRQ(ierr);*/
582c7543cceSMatthew G Knepley       } else {
583c7543cceSMatthew G Knepley         while (blocks) {
584c7543cceSMatthew G Knepley           ierr = VecScatterBegin(blocks->sctx, X, blocks->x, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr);
585c7543cceSMatthew G Knepley           ierr = VecScatterEnd(blocks->sctx, X, blocks->x, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr);
586c7543cceSMatthew G Knepley           ierr = SNESSolve(blocks->snes, PETSC_NULL, blocks->x);CHKERRQ(ierr);
587c7543cceSMatthew G Knepley           ierr = VecScatterBegin(blocks->sctx, blocks->x, X, INSERT_VALUES, SCATTER_REVERSE);CHKERRQ(ierr);
588c7543cceSMatthew G Knepley           ierr = VecScatterEnd(blocks->sctx, blocks->x, X, INSERT_VALUES, SCATTER_REVERSE);CHKERRQ(ierr);
589c7543cceSMatthew G Knepley           blocks = blocks->next;
590c7543cceSMatthew G Knepley         }
591c7543cceSMatthew G Knepley       }
592c7543cceSMatthew G Knepley     } else {
593c7543cceSMatthew G Knepley       SETERRQ1(((PetscObject) snes)->comm, PETSC_ERR_SUP, "Unsupported or unknown composition", (int) mb->type);
594c7543cceSMatthew G Knepley     }
595c7543cceSMatthew G Knepley     CHKMEMQ;
596c7543cceSMatthew G Knepley     /* Compute F(X^{new}) */
597c7543cceSMatthew G Knepley     ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr);
598c7543cceSMatthew G Knepley     ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr);
599c7543cceSMatthew G Knepley     if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"Infinite or not-a-number generated norm");
600c7543cceSMatthew G Knepley 
601c7543cceSMatthew G Knepley     if (snes->nfuncs >= snes->max_funcs) {
602c7543cceSMatthew G Knepley       snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
603c7543cceSMatthew G Knepley       break;
604c7543cceSMatthew G Knepley     }
605c7543cceSMatthew G Knepley     if (snes->domainerror) {
606c7543cceSMatthew G Knepley       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
607c7543cceSMatthew G Knepley       PetscFunctionReturn(0);
608c7543cceSMatthew G Knepley     }
609c7543cceSMatthew G Knepley     /* Monitor convergence */
610c7543cceSMatthew G Knepley     ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
611c7543cceSMatthew G Knepley     snes->iter = i+1;
612c7543cceSMatthew G Knepley     snes->norm = fnorm;
613c7543cceSMatthew G Knepley     ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
614c7543cceSMatthew G Knepley     SNESLogConvHistory(snes,snes->norm,0);
615c7543cceSMatthew G Knepley     ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
616c7543cceSMatthew G Knepley     /* Test for convergence */
617c7543cceSMatthew G Knepley     ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
618c7543cceSMatthew G Knepley     if (snes->reason) break;
619c7543cceSMatthew G Knepley   }
620c7543cceSMatthew G Knepley   if (i == maxits) {
621c7543cceSMatthew G Knepley     ierr = PetscInfo1(snes, "Maximum number of iterations has been reached: %D\n", maxits);CHKERRQ(ierr);
622c7543cceSMatthew G Knepley     if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
623c7543cceSMatthew G Knepley   }
624c7543cceSMatthew G Knepley   PetscFunctionReturn(0);
625c7543cceSMatthew G Knepley }
626c7543cceSMatthew G Knepley 
627c7543cceSMatthew G Knepley EXTERN_C_BEGIN
628c7543cceSMatthew G Knepley #undef __FUNCT__
629c7543cceSMatthew G Knepley #define __FUNCT__ "SNESMultiblockSetFields_Default"
630c7543cceSMatthew G Knepley PetscErrorCode SNESMultiblockSetFields_Default(SNES snes, const char name[], PetscInt n, const PetscInt fields[])
631c7543cceSMatthew G Knepley {
632c7543cceSMatthew G Knepley   SNES_Multiblock *mb = (SNES_Multiblock *) snes->data;
633c7543cceSMatthew G Knepley   BlockDesc        newblock, next = mb->blocks;
634c7543cceSMatthew G Knepley   char             prefix[128];
635c7543cceSMatthew G Knepley   PetscInt         i;
636c7543cceSMatthew G Knepley   PetscErrorCode   ierr;
637c7543cceSMatthew G Knepley 
638c7543cceSMatthew G Knepley   PetscFunctionBegin;
639c7543cceSMatthew G Knepley   if (mb->defined) {
640c7543cceSMatthew G Knepley     ierr = PetscInfo1(snes, "Ignoring new block \"%s\" because the blocks have already been defined\n", name);CHKERRQ(ierr);
641c7543cceSMatthew G Knepley     PetscFunctionReturn(0);
642c7543cceSMatthew G Knepley   }
643c7543cceSMatthew G Knepley   for(i = 0; i < n; ++i) {
644c7543cceSMatthew G Knepley     if (fields[i] >= mb->bs) {SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field %D requested but only %D exist", fields[i], mb->bs);}
645c7543cceSMatthew G Knepley     if (fields[i] < 0)       {SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative field %D requested", fields[i]);}
646c7543cceSMatthew G Knepley   }
647c7543cceSMatthew G Knepley   ierr = PetscNew(struct _BlockDesc, &newblock);CHKERRQ(ierr);
648c7543cceSMatthew G Knepley   if (name) {
649c7543cceSMatthew G Knepley     ierr = PetscStrallocpy(name, &newblock->name);CHKERRQ(ierr);
650c7543cceSMatthew G Knepley   } else {
651c7543cceSMatthew G Knepley     PetscInt len = floor(log10(mb->numBlocks))+1;
652c7543cceSMatthew G Knepley 
653c7543cceSMatthew G Knepley     ierr = PetscMalloc((len+1)*sizeof(char), &newblock->name);CHKERRQ(ierr);
654c7543cceSMatthew G Knepley     ierr = PetscSNPrintf(newblock->name, len, "%s", mb->numBlocks);CHKERRQ(ierr);
655c7543cceSMatthew G Knepley   }
656c7543cceSMatthew G Knepley   newblock->nfields = n;
657c7543cceSMatthew G Knepley   ierr = PetscMalloc(n*sizeof(PetscInt), &newblock->fields);CHKERRQ(ierr);
658c7543cceSMatthew G Knepley   ierr = PetscMemcpy(newblock->fields, fields, n*sizeof(PetscInt));CHKERRQ(ierr);
659c7543cceSMatthew G Knepley   newblock->next    = PETSC_NULL;
660c7543cceSMatthew G Knepley   ierr = SNESCreate(((PetscObject) snes)->comm, &newblock->snes);CHKERRQ(ierr);
661c7543cceSMatthew G Knepley   ierr = PetscObjectIncrementTabLevel((PetscObject) newblock->snes, (PetscObject) snes, 1);CHKERRQ(ierr);
662d5c3842bSBarry Smith   ierr = SNESSetType(newblock->snes, SNESNRICHARDSON);CHKERRQ(ierr);
663c7543cceSMatthew G Knepley   ierr = PetscLogObjectParent((PetscObject) snes, (PetscObject) newblock->snes);CHKERRQ(ierr);
664c7543cceSMatthew G Knepley   ierr = PetscSNPrintf(prefix, sizeof prefix, "%smultiblock_%s_", ((PetscObject) snes)->prefix ? ((PetscObject) snes)->prefix : "", newblock->name);CHKERRQ(ierr);
665c7543cceSMatthew G Knepley   ierr = SNESSetOptionsPrefix(newblock->snes, prefix);CHKERRQ(ierr);
666c7543cceSMatthew G Knepley 
667c7543cceSMatthew G Knepley   if (!next) {
668c7543cceSMatthew G Knepley     mb->blocks         = newblock;
669c7543cceSMatthew G Knepley     newblock->previous = PETSC_NULL;
670c7543cceSMatthew G Knepley   } else {
671c7543cceSMatthew G Knepley     while (next->next) {
672c7543cceSMatthew G Knepley       next = next->next;
673c7543cceSMatthew G Knepley     }
674c7543cceSMatthew G Knepley     next->next         = newblock;
675c7543cceSMatthew G Knepley     newblock->previous = next;
676c7543cceSMatthew G Knepley   }
677c7543cceSMatthew G Knepley   mb->numBlocks++;
678c7543cceSMatthew G Knepley   PetscFunctionReturn(0);
679c7543cceSMatthew G Knepley }
680c7543cceSMatthew G Knepley EXTERN_C_END
681c7543cceSMatthew G Knepley 
682c7543cceSMatthew G Knepley EXTERN_C_BEGIN
683c7543cceSMatthew G Knepley #undef __FUNCT__
684c7543cceSMatthew G Knepley #define __FUNCT__ "SNESMultiblockSetIS_Default"
685c7543cceSMatthew G Knepley PetscErrorCode SNESMultiblockSetIS_Default(SNES snes, const char name[], IS is)
686c7543cceSMatthew G Knepley {
687c7543cceSMatthew G Knepley   SNES_Multiblock *mb = (SNES_Multiblock *) snes->data;
688c7543cceSMatthew G Knepley   BlockDesc        newblock, next = mb->blocks;
689c7543cceSMatthew G Knepley   char             prefix[128];
690c7543cceSMatthew G Knepley   PetscErrorCode   ierr;
691c7543cceSMatthew G Knepley 
692c7543cceSMatthew G Knepley   PetscFunctionBegin;
693c7543cceSMatthew G Knepley   if (mb->defined) {
694c7543cceSMatthew G Knepley     ierr = PetscInfo1(snes, "Ignoring new block \"%s\" because the blocks have already been defined\n", name);CHKERRQ(ierr);
695c7543cceSMatthew G Knepley     PetscFunctionReturn(0);
696c7543cceSMatthew G Knepley   }
697c7543cceSMatthew G Knepley   ierr = PetscNew(struct _BlockDesc, &newblock);CHKERRQ(ierr);
698c7543cceSMatthew G Knepley   if (name) {
699c7543cceSMatthew G Knepley     ierr = PetscStrallocpy(name, &newblock->name);CHKERRQ(ierr);
700c7543cceSMatthew G Knepley   } else {
701c7543cceSMatthew G Knepley     PetscInt len = floor(log10(mb->numBlocks))+1;
702c7543cceSMatthew G Knepley 
703c7543cceSMatthew G Knepley     ierr = PetscMalloc((len+1)*sizeof(char), &newblock->name);CHKERRQ(ierr);
704c7543cceSMatthew G Knepley     ierr = PetscSNPrintf(newblock->name, len, "%s", mb->numBlocks);CHKERRQ(ierr);
705c7543cceSMatthew G Knepley   }
706c7543cceSMatthew G Knepley   newblock->is   = is;
707c7543cceSMatthew G Knepley   ierr = PetscObjectReference((PetscObject) is);CHKERRQ(ierr);
708c7543cceSMatthew G Knepley   newblock->next = PETSC_NULL;
709c7543cceSMatthew G Knepley   ierr = SNESCreate(((PetscObject) snes)->comm, &newblock->snes);CHKERRQ(ierr);
710c7543cceSMatthew G Knepley   ierr = PetscObjectIncrementTabLevel((PetscObject) newblock->snes, (PetscObject) snes, 1);CHKERRQ(ierr);
711d5c3842bSBarry Smith   ierr = SNESSetType(newblock->snes, SNESNRICHARDSON);CHKERRQ(ierr);
712c7543cceSMatthew G Knepley   ierr = PetscLogObjectParent((PetscObject) snes, (PetscObject) newblock->snes);CHKERRQ(ierr);
713c7543cceSMatthew G Knepley   ierr = PetscSNPrintf(prefix, sizeof prefix, "%smultiblock_%s_", ((PetscObject) snes)->prefix ? ((PetscObject) snes)->prefix : "", newblock->name);CHKERRQ(ierr);
714c7543cceSMatthew G Knepley   ierr = SNESSetOptionsPrefix(newblock->snes, prefix);CHKERRQ(ierr);
715c7543cceSMatthew G Knepley 
716c7543cceSMatthew G Knepley   if (!next) {
717c7543cceSMatthew G Knepley     mb->blocks         = newblock;
718c7543cceSMatthew G Knepley     newblock->previous = PETSC_NULL;
719c7543cceSMatthew G Knepley   } else {
720c7543cceSMatthew G Knepley     while (next->next) {
721c7543cceSMatthew G Knepley       next = next->next;
722c7543cceSMatthew G Knepley     }
723c7543cceSMatthew G Knepley     next->next         = newblock;
724c7543cceSMatthew G Knepley     newblock->previous = next;
725c7543cceSMatthew G Knepley   }
726c7543cceSMatthew G Knepley   mb->numBlocks++;
727c7543cceSMatthew G Knepley   PetscFunctionReturn(0);
728c7543cceSMatthew G Knepley }
729c7543cceSMatthew G Knepley EXTERN_C_END
730c7543cceSMatthew G Knepley 
731c7543cceSMatthew G Knepley EXTERN_C_BEGIN
732c7543cceSMatthew G Knepley #undef __FUNCT__
733c7543cceSMatthew G Knepley #define __FUNCT__ "SNESMultiblockSetBlockSize_Default"
734c7543cceSMatthew G Knepley PetscErrorCode  SNESMultiblockSetBlockSize_Default(SNES snes, PetscInt bs)
735c7543cceSMatthew G Knepley {
736c7543cceSMatthew G Knepley   SNES_Multiblock *mb = (SNES_Multiblock *) snes->data;
737c7543cceSMatthew G Knepley 
738c7543cceSMatthew G Knepley   PetscFunctionBegin;
739c7543cceSMatthew G Knepley   if (bs < 1) {SETERRQ1(((PetscObject) snes)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Blocksize must be positive, you gave %D", bs);}
740c7543cceSMatthew G Knepley   if (mb->bs > 0 && mb->bs != bs) {SETERRQ2(((PetscObject) snes)->comm, PETSC_ERR_ARG_WRONGSTATE, "Cannot change blocksize from %D to %D after it has been set", mb->bs, bs);}
741c7543cceSMatthew G Knepley   mb->bs = bs;
742c7543cceSMatthew G Knepley   PetscFunctionReturn(0);
743c7543cceSMatthew G Knepley }
744c7543cceSMatthew G Knepley EXTERN_C_END
745c7543cceSMatthew G Knepley 
746c7543cceSMatthew G Knepley EXTERN_C_BEGIN
747c7543cceSMatthew G Knepley #undef __FUNCT__
748c7543cceSMatthew G Knepley #define __FUNCT__ "SNESMultiblockGetSubSNES_Default"
749c7543cceSMatthew G Knepley PetscErrorCode SNESMultiblockGetSubSNES_Default(SNES snes, PetscInt *n, SNES **subsnes)
750c7543cceSMatthew G Knepley {
751c7543cceSMatthew G Knepley   SNES_Multiblock *mb     = (SNES_Multiblock *) snes->data;
752c7543cceSMatthew G Knepley   BlockDesc        blocks = mb->blocks;
753c7543cceSMatthew G Knepley   PetscInt         cnt    = 0;
754c7543cceSMatthew G Knepley   PetscErrorCode   ierr;
755c7543cceSMatthew G Knepley 
756c7543cceSMatthew G Knepley   PetscFunctionBegin;
757c7543cceSMatthew G Knepley   ierr = PetscMalloc(mb->numBlocks * sizeof(SNES), subsnes);CHKERRQ(ierr);
758c7543cceSMatthew G Knepley   while (blocks) {
759c7543cceSMatthew G Knepley     (*subsnes)[cnt++] = blocks->snes;
760c7543cceSMatthew G Knepley     blocks = blocks->next;
761c7543cceSMatthew G Knepley   }
762c7543cceSMatthew G Knepley   if (cnt != mb->numBlocks) {
763c7543cceSMatthew G Knepley     SETERRQ2(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);
764c7543cceSMatthew G Knepley   }
765c7543cceSMatthew G Knepley   if (n) {*n = mb->numBlocks;}
766c7543cceSMatthew G Knepley   PetscFunctionReturn(0);
767c7543cceSMatthew G Knepley }
768c7543cceSMatthew G Knepley EXTERN_C_END
769c7543cceSMatthew G Knepley 
77087bd6022SMatthew G Knepley EXTERN_C_BEGIN
77187bd6022SMatthew G Knepley #undef __FUNCT__
77287bd6022SMatthew G Knepley #define __FUNCT__ "SNESMultiblockSetType_Default"
77387bd6022SMatthew G Knepley PetscErrorCode  SNESMultiblockSetType_Default(SNES snes, PCCompositeType type)
77487bd6022SMatthew G Knepley {
77587bd6022SMatthew G Knepley   SNES_Multiblock *mb = (SNES_Multiblock *) snes->data;
77687bd6022SMatthew G Knepley   PetscErrorCode   ierr;
77787bd6022SMatthew G Knepley 
77887bd6022SMatthew G Knepley   PetscFunctionBegin;
77987bd6022SMatthew G Knepley   mb->type = type;
78087bd6022SMatthew G Knepley   if (type == PC_COMPOSITE_SCHUR) {
78187bd6022SMatthew G Knepley #if 1
78287bd6022SMatthew G Knepley     SETERRQ(((PetscObject) snes)->comm, PETSC_ERR_SUP, "The Schur composite type is not yet supported");
78387bd6022SMatthew G Knepley #else
78487bd6022SMatthew G Knepley     snes->ops->solve = SNESSolve_Multiblock_Schur;
78587bd6022SMatthew G Knepley     snes->ops->view  = SNESView_Multiblock_Schur;
78687bd6022SMatthew G Knepley     ierr = PetscObjectComposeFunctionDynamic((PetscObject) snes, "SNESMultiblockGetSubSNES_C", "SNESMultiblockGetSubSNES_Schur", SNESMultiblockGetSubSNES_Schur);CHKERRQ(ierr);
78787bd6022SMatthew G Knepley     ierr = PetscObjectComposeFunctionDynamic((PetscObject) snes, "SNESMultiblockSchurPrecondition_C", "SNESMultiblockSchurPrecondition_Default", SNESMultiblockSchurPrecondition_Default);CHKERRQ(ierr);
78887bd6022SMatthew G Knepley #endif
78987bd6022SMatthew G Knepley   } else {
79087bd6022SMatthew G Knepley     snes->ops->solve = SNESSolve_Multiblock;
79187bd6022SMatthew G Knepley     snes->ops->view  = SNESView_Multiblock;
79287bd6022SMatthew G Knepley     ierr = PetscObjectComposeFunctionDynamic((PetscObject) snes, "SNESMultiblockGetSubSNES_C", "SNESMultiblockGetSubSNES_Default", SNESMultiblockGetSubSNES_Default);CHKERRQ(ierr);
79387bd6022SMatthew G Knepley     ierr = PetscObjectComposeFunctionDynamic((PetscObject) snes, "SNESMultiblockSchurPrecondition_C", "", 0);CHKERRQ(ierr);
79487bd6022SMatthew G Knepley   }
79587bd6022SMatthew G Knepley   PetscFunctionReturn(0);
79687bd6022SMatthew G Knepley }
79787bd6022SMatthew G Knepley EXTERN_C_END
79887bd6022SMatthew G Knepley 
799c7543cceSMatthew G Knepley #undef __FUNCT__
800c7543cceSMatthew G Knepley #define __FUNCT__ "SNESMultiblockSetFields"
801c7543cceSMatthew G Knepley /*@
802c7543cceSMatthew G Knepley   SNESMultiblockSetFields - Sets the fields for one particular block in the solver
803c7543cceSMatthew G Knepley 
804c7543cceSMatthew G Knepley   Logically Collective on SNES
805c7543cceSMatthew G Knepley 
806c7543cceSMatthew G Knepley   Input Parameters:
807c7543cceSMatthew G Knepley + snes   - the solver
808c7543cceSMatthew G Knepley . name   - name of this block, if PETSC_NULL the number of the block is used
809c7543cceSMatthew G Knepley . n      - the number of fields in this block
810c7543cceSMatthew G Knepley - fields - the fields in this block
811c7543cceSMatthew G Knepley 
812c7543cceSMatthew G Knepley   Level: intermediate
813c7543cceSMatthew G Knepley 
814c7543cceSMatthew G Knepley   Notes: Use SNESMultiblockSetIS() to set a completely general set of row indices as a block.
815c7543cceSMatthew G Knepley 
816c7543cceSMatthew G Knepley   The SNESMultiblockSetFields() is for defining blocks as a group of strided indices, or fields.
817c7543cceSMatthew G Knepley   For example, if the vector block size is three then one can define a block as field 0, or
818c7543cceSMatthew G Knepley   1 or 2, or field 0,1 or 0,2 or 1,2 which means
819c7543cceSMatthew G Knepley     0xx3xx6xx9xx12 ... x1xx4xx7xx ... xx2xx5xx8xx.. 01x34x67x... 0x1x3x5x7.. x12x45x78x....
820c7543cceSMatthew G Knepley   where the numbered entries indicate what is in the block.
821c7543cceSMatthew G Knepley 
822c7543cceSMatthew G Knepley   This function is called once per block (it creates a new block each time). Solve options
823c7543cceSMatthew G Knepley   for this block will be available under the prefix -multiblock_BLOCKNAME_.
824c7543cceSMatthew G Knepley 
825b665c654SMatthew G Knepley .seealso: SNESMultiblockGetSubSNES(), SNESMULTIBLOCK, SNESMultiblockSetBlockSize(), SNESMultiblockSetIS()
826c7543cceSMatthew G Knepley @*/
827c7543cceSMatthew G Knepley PetscErrorCode SNESMultiblockSetFields(SNES snes, const char name[], PetscInt n, const PetscInt *fields)
828c7543cceSMatthew G Knepley {
829c7543cceSMatthew G Knepley   PetscErrorCode ierr;
830c7543cceSMatthew G Knepley 
831c7543cceSMatthew G Knepley   PetscFunctionBegin;
832c7543cceSMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
833c7543cceSMatthew G Knepley   PetscValidCharPointer(name, 2);
834c7543cceSMatthew G Knepley   if (n < 1) SETERRQ2(((PetscObject) snes)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Provided number of fields %D in split \"%s\" not positive", n, name);
835c7543cceSMatthew G Knepley   PetscValidIntPointer(fields, 3);
836c7543cceSMatthew G Knepley   ierr = PetscTryMethod(snes, "SNESMultiblockSetFields_C", (SNES, const char[], PetscInt, const PetscInt *), (snes, name, n, fields));CHKERRQ(ierr);
837c7543cceSMatthew G Knepley   PetscFunctionReturn(0);
838c7543cceSMatthew G Knepley }
839c7543cceSMatthew G Knepley 
840c7543cceSMatthew G Knepley #undef __FUNCT__
841c7543cceSMatthew G Knepley #define __FUNCT__ "SNESMultiblockSetIS"
842c7543cceSMatthew G Knepley /*@
843c7543cceSMatthew G Knepley   SNESMultiblockSetIS - Sets the global row indices for the block
844c7543cceSMatthew G Knepley 
845c7543cceSMatthew G Knepley   Logically Collective on SNES
846c7543cceSMatthew G Knepley 
847c7543cceSMatthew G Knepley   Input Parameters:
848c7543cceSMatthew G Knepley + snes - the solver context
849c7543cceSMatthew G Knepley . name - name of this block, if PETSC_NULL the number of the block is used
850c7543cceSMatthew G Knepley - is   - the index set that defines the global row indices in this block
851c7543cceSMatthew G Knepley 
852c7543cceSMatthew G Knepley   Notes:
853c7543cceSMatthew G Knepley   Use SNESMultiblockSetFields(), for blocks defined by strides.
854c7543cceSMatthew G Knepley 
855c7543cceSMatthew G Knepley   This function is called once per block (it creates a new block each time). Solve options
856c7543cceSMatthew G Knepley   for this block will be available under the prefix -multiblock_BLOCKNAME_.
857c7543cceSMatthew G Knepley 
858c7543cceSMatthew G Knepley   Level: intermediate
859c7543cceSMatthew G Knepley 
860b665c654SMatthew G Knepley .seealso: SNESMultiblockGetSubSNES(), SNESMULTIBLOCK, SNESMultiblockSetBlockSize()
861c7543cceSMatthew G Knepley @*/
862c7543cceSMatthew G Knepley PetscErrorCode SNESMultiblockSetIS(SNES snes, const char name[], IS is)
863c7543cceSMatthew G Knepley {
864c7543cceSMatthew G Knepley   PetscErrorCode ierr;
865c7543cceSMatthew G Knepley 
866c7543cceSMatthew G Knepley   PetscFunctionBegin;
867c7543cceSMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
868c7543cceSMatthew G Knepley   PetscValidCharPointer(name, 2);
869c7543cceSMatthew G Knepley   PetscValidHeaderSpecific(is, IS_CLASSID, 3);
870c7543cceSMatthew G Knepley   ierr = PetscTryMethod(snes, "SNESMultiblockSetIS_C", (SNES, const char[], IS), (snes, name, is));CHKERRQ(ierr);
871c7543cceSMatthew G Knepley   PetscFunctionReturn(0);
872c7543cceSMatthew G Knepley }
873c7543cceSMatthew G Knepley 
874c7543cceSMatthew G Knepley #undef __FUNCT__
875c7543cceSMatthew G Knepley #define __FUNCT__ "SNESMultiblockSetType"
876c7543cceSMatthew G Knepley /*@
877c7543cceSMatthew G Knepley   SNESMultiblockSetType - Sets the type of block combination.
878c7543cceSMatthew G Knepley 
879c7543cceSMatthew G Knepley   Collective on SNES
880c7543cceSMatthew G Knepley 
881c7543cceSMatthew G Knepley   Input Parameters:
882c7543cceSMatthew G Knepley + snes - the solver context
883c7543cceSMatthew G Knepley - type - PC_COMPOSITE_ADDITIVE, PC_COMPOSITE_MULTIPLICATIVE (default), PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE
884c7543cceSMatthew G Knepley 
885c7543cceSMatthew G Knepley   Options Database Key:
886c7543cceSMatthew G Knepley . -snes_multiblock_type <type: one of multiplicative, additive, symmetric_multiplicative> - Sets block combination type
887c7543cceSMatthew G Knepley 
888c7543cceSMatthew G Knepley   Level: Developer
889c7543cceSMatthew G Knepley 
890c7543cceSMatthew G Knepley .keywords: SNES, set, type, composite preconditioner, additive, multiplicative
891c7543cceSMatthew G Knepley .seealso: PCCompositeSetType()
892c7543cceSMatthew G Knepley @*/
893c7543cceSMatthew G Knepley PetscErrorCode SNESMultiblockSetType(SNES snes, PCCompositeType type)
894c7543cceSMatthew G Knepley {
895c7543cceSMatthew G Knepley   PetscErrorCode ierr;
896c7543cceSMatthew G Knepley 
897c7543cceSMatthew G Knepley   PetscFunctionBegin;
898c7543cceSMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
899c7543cceSMatthew G Knepley   ierr = PetscTryMethod(snes, "SNESMultiblockSetType_C", (SNES, PCCompositeType), (snes, type));CHKERRQ(ierr);
900c7543cceSMatthew G Knepley   PetscFunctionReturn(0);
901c7543cceSMatthew G Knepley }
902c7543cceSMatthew G Knepley 
903c7543cceSMatthew G Knepley #undef __FUNCT__
904c7543cceSMatthew G Knepley #define __FUNCT__ "SNESMultiblockSetBlockSize"
905c7543cceSMatthew G Knepley /*@
906c7543cceSMatthew G Knepley   SNESMultiblockSetBlockSize - Sets the block size for structured mesh block division. If not set the matrix block size is used.
907c7543cceSMatthew G Knepley 
908c7543cceSMatthew G Knepley   Logically Collective on SNES
909c7543cceSMatthew G Knepley 
910c7543cceSMatthew G Knepley   Input Parameters:
911c7543cceSMatthew G Knepley + snes - the solver context
912c7543cceSMatthew G Knepley - bs   - the block size
913c7543cceSMatthew G Knepley 
914c7543cceSMatthew G Knepley   Level: intermediate
915c7543cceSMatthew G Knepley 
916b665c654SMatthew G Knepley .seealso: SNESMultiblockGetSubSNES(), SNESMULTIBLOCK, SNESMultiblockSetFields()
917c7543cceSMatthew G Knepley @*/
918c7543cceSMatthew G Knepley PetscErrorCode SNESMultiblockSetBlockSize(SNES snes, PetscInt bs)
919c7543cceSMatthew G Knepley {
920c7543cceSMatthew G Knepley   PetscErrorCode ierr;
921c7543cceSMatthew G Knepley 
922c7543cceSMatthew G Knepley   PetscFunctionBegin;
923c7543cceSMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
924c7543cceSMatthew G Knepley   PetscValidLogicalCollectiveInt(snes, bs, 2);
925c7543cceSMatthew G Knepley   ierr = PetscTryMethod(snes, "SNESMultiblockSetBlockSize_C", (SNES, PetscInt), (snes,bs));CHKERRQ(ierr);
926c7543cceSMatthew G Knepley   PetscFunctionReturn(0);
927c7543cceSMatthew G Knepley }
928c7543cceSMatthew G Knepley 
929c7543cceSMatthew G Knepley #undef __FUNCT__
930c7543cceSMatthew G Knepley #define __FUNCT__ "SNESMultiblockGetSubSNES"
931c7543cceSMatthew G Knepley /*@C
932b665c654SMatthew G Knepley   SNESMultiblockGetSubSNES - Gets the SNES contexts for all blocks
933c7543cceSMatthew G Knepley 
934c7543cceSMatthew G Knepley   Collective on SNES
935c7543cceSMatthew G Knepley 
936c7543cceSMatthew G Knepley   Input Parameter:
937c7543cceSMatthew G Knepley . snes - the solver context
938c7543cceSMatthew G Knepley 
939c7543cceSMatthew G Knepley   Output Parameters:
940c7543cceSMatthew G Knepley + n       - the number of blocks
941c7543cceSMatthew G Knepley - subsnes - the array of SNES contexts
942c7543cceSMatthew G Knepley 
943c7543cceSMatthew G Knepley   Note:
944c7543cceSMatthew G Knepley   After SNESMultiblockGetSubSNES() the array of SNESs MUST be freed by the user
945c7543cceSMatthew G Knepley   (not each SNES, just the array that contains them).
946c7543cceSMatthew G Knepley 
947c7543cceSMatthew G Knepley   You must call SNESSetUp() before calling SNESMultiblockGetSubSNES().
948c7543cceSMatthew G Knepley 
949c7543cceSMatthew G Knepley   Level: advanced
950c7543cceSMatthew G Knepley 
951c7543cceSMatthew G Knepley .seealso: SNESMULTIBLOCK
952c7543cceSMatthew G Knepley @*/
953c7543cceSMatthew G Knepley PetscErrorCode SNESMultiblockGetSubSNES(SNES snes, PetscInt *n, SNES *subsnes[])
954c7543cceSMatthew G Knepley {
955c7543cceSMatthew G Knepley   PetscErrorCode ierr;
956c7543cceSMatthew G Knepley 
957c7543cceSMatthew G Knepley   PetscFunctionBegin;
958c7543cceSMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
959c7543cceSMatthew G Knepley   if (n) PetscValidIntPointer(n, 2);
960b665c654SMatthew G Knepley   ierr = PetscUseMethod(snes, "SNESMultiblockGetSubSNES_C", (SNES, PetscInt*, SNES **), (snes, n, subsnes));CHKERRQ(ierr);
961c7543cceSMatthew G Knepley   PetscFunctionReturn(0);
962c7543cceSMatthew G Knepley }
963c7543cceSMatthew G Knepley 
964c7543cceSMatthew G Knepley /*MC
965c7543cceSMatthew G Knepley   SNESMULTIBLOCK - Multiblock nonlinear solver that can use overlapping or nonoverlapping blocks, organized
966c7543cceSMatthew G Knepley   additively (Jacobi) or multiplicatively (Gauss-Seidel).
967c7543cceSMatthew G Knepley 
968c7543cceSMatthew G Knepley   Level: beginner
969c7543cceSMatthew G Knepley 
970d5c3842bSBarry Smith .seealso:  SNESCreate(), SNES, SNESSetType(), SNESLS, SNESTR, SNESNRICHARDSON
971c7543cceSMatthew G Knepley M*/
972c7543cceSMatthew G Knepley EXTERN_C_BEGIN
973c7543cceSMatthew G Knepley #undef __FUNCT__
974c7543cceSMatthew G Knepley #define __FUNCT__ "SNESCreate_Multiblock"
975c7543cceSMatthew G Knepley PetscErrorCode  SNESCreate_Multiblock(SNES snes)
976c7543cceSMatthew G Knepley {
977c7543cceSMatthew G Knepley   SNES_Multiblock *mb;
978c7543cceSMatthew G Knepley   PetscErrorCode   ierr;
979c7543cceSMatthew G Knepley 
980c7543cceSMatthew G Knepley   PetscFunctionBegin;
981c7543cceSMatthew G Knepley   snes->ops->destroy	    = SNESDestroy_Multiblock;
982c7543cceSMatthew G Knepley   snes->ops->setup	    = SNESSetUp_Multiblock;
983c7543cceSMatthew G Knepley   snes->ops->setfromoptions = SNESSetFromOptions_Multiblock;
984c7543cceSMatthew G Knepley   snes->ops->view           = SNESView_Multiblock;
985c7543cceSMatthew G Knepley   snes->ops->solve	    = SNESSolve_Multiblock;
986c7543cceSMatthew G Knepley   snes->ops->reset          = SNESReset_Multiblock;
987c7543cceSMatthew G Knepley 
9882c155ee1SBarry Smith   snes->usesksp             = PETSC_FALSE;
9892c155ee1SBarry Smith 
990c7543cceSMatthew G Knepley   ierr = PetscNewLog(snes, SNES_Multiblock, &mb);CHKERRQ(ierr);
991c7543cceSMatthew G Knepley   snes->data = (void*) mb;
992c7543cceSMatthew G Knepley   mb->defined   = PETSC_FALSE;
993c7543cceSMatthew G Knepley   mb->numBlocks = 0;
994c7543cceSMatthew G Knepley   mb->bs        = -1;
995c7543cceSMatthew G Knepley   mb->type      = PC_COMPOSITE_MULTIPLICATIVE;
996c7543cceSMatthew G Knepley 
997c7543cceSMatthew G Knepley   /* We attach functions so that they can be called on another PC without crashing the program */
998c7543cceSMatthew G Knepley   ierr = PetscObjectComposeFunctionDynamic((PetscObject) snes, "SNESMultiblockSetFields_C",    "SNESMultiblockSetFields_Default",    SNESMultiblockSetFields_Default);CHKERRQ(ierr);
999c7543cceSMatthew G Knepley   ierr = PetscObjectComposeFunctionDynamic((PetscObject) snes, "SNESMultiblockSetIS_C",        "SNESMultiblockSetIS_Default",        SNESMultiblockSetIS_Default);CHKERRQ(ierr);
1000c7543cceSMatthew G Knepley   ierr = PetscObjectComposeFunctionDynamic((PetscObject) snes, "SNESMultiblockSetType_C",      "SNESMultiblockSetType_Default",      SNESMultiblockSetType_Default);CHKERRQ(ierr);
1001c7543cceSMatthew G Knepley   ierr = PetscObjectComposeFunctionDynamic((PetscObject) snes, "SNESMultiblockSetBlockSize_C", "SNESMultiblockSetBlockSize_Default", SNESMultiblockSetBlockSize_Default);CHKERRQ(ierr);
1002c7543cceSMatthew G Knepley   ierr = PetscObjectComposeFunctionDynamic((PetscObject) snes, "SNESMultiblockGetSubSNES_C",   "SNESMultiblockGetSubSNES_Default",   SNESMultiblockGetSubSNES_Default);CHKERRQ(ierr);
1003c7543cceSMatthew G Knepley   PetscFunctionReturn(0);
1004c7543cceSMatthew G Knepley }
1005c7543cceSMatthew G Knepley EXTERN_C_END
1006