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 26d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESReset_Multiblock(SNES snes) 27d71ae5a4SJacob Faibussowitsch { 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) { 339566063dSJacob Faibussowitsch PetscCall(SNESReset(blocks->snes)); 340c74a584SJed Brown #if 0 359566063dSJacob Faibussowitsch PetscCall(VecDestroy(&blocks->x)); 360c74a584SJed Brown #endif 379566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&blocks->sctx)); 389566063dSJacob Faibussowitsch PetscCall(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 */ 53d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESDestroy_Multiblock(SNES snes) 54d71ae5a4SJacob Faibussowitsch { 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; 599566063dSJacob Faibussowitsch PetscCall(SNESReset_Multiblock(snes)); 60c7543cceSMatthew G Knepley while (blocks) { 61c7543cceSMatthew G Knepley next = blocks->next; 629566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&blocks->snes)); 639566063dSJacob Faibussowitsch PetscCall(PetscFree(blocks->name)); 649566063dSJacob Faibussowitsch PetscCall(PetscFree(blocks->fields)); 659566063dSJacob Faibussowitsch PetscCall(PetscFree(blocks)); 66c7543cceSMatthew G Knepley blocks = next; 67c7543cceSMatthew G Knepley } 689566063dSJacob Faibussowitsch PetscCall(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 */ 73d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESMultiblockSetFieldsRuntime_Private(SNES snes) 74d71ae5a4SJacob Faibussowitsch { 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; 829566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mb->bs, &ifields)); 83c7543cceSMatthew G Knepley for (i = 0;; ++i) { 8463a3b9bcSJacob Faibussowitsch PetscCall(PetscSNPrintf(name, sizeof(name), "%" PetscInt_FMT, i)); 8563a3b9bcSJacob Faibussowitsch PetscCall(PetscSNPrintf(optionname, sizeof(optionname), "-snes_multiblock_%" PetscInt_FMT "_fields", i)); 86c7543cceSMatthew G Knepley nfields = mb->bs; 879566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetIntArray(NULL, ((PetscObject)snes)->prefix, optionname, ifields, &nfields, &flg)); 88c7543cceSMatthew G Knepley if (!flg) break; 8928b400f6SJacob Faibussowitsch PetscCheck(nfields, PETSC_COMM_SELF, PETSC_ERR_USER, "Cannot list zero fields"); 909566063dSJacob Faibussowitsch PetscCall(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 } 989566063dSJacob Faibussowitsch PetscCall(PetscFree(ifields)); 99c7543cceSMatthew G Knepley PetscFunctionReturn(0); 100c7543cceSMatthew G Knepley } 101c7543cceSMatthew G Knepley 102d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESMultiblockSetDefaults(SNES snes) 103d71ae5a4SJacob Faibussowitsch { 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 1139566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes->dm, DMCOMPOSITE, &dmcomposite)); 114c7543cceSMatthew G Knepley if (dmcomposite) { 115c7543cceSMatthew G Knepley PetscInt nDM; 116c7543cceSMatthew G Knepley IS *fields; 117c7543cceSMatthew G Knepley 1189566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Setting up physics based multiblock solver using the embedded DM\n")); 1199566063dSJacob Faibussowitsch PetscCall(DMCompositeGetNumberDM(snes->dm, &nDM)); 1209566063dSJacob Faibussowitsch PetscCall(DMCompositeGetGlobalISs(snes->dm, &fields)); 121c7543cceSMatthew G Knepley for (i = 0; i < nDM; ++i) { 122c7543cceSMatthew G Knepley char name[8]; 123c7543cceSMatthew G Knepley 12463a3b9bcSJacob Faibussowitsch PetscCall(PetscSNPrintf(name, sizeof(name), "%" PetscInt_FMT, i)); 1259566063dSJacob Faibussowitsch PetscCall(SNESMultiblockSetIS(snes, name, fields[i])); 1269566063dSJacob Faibussowitsch PetscCall(ISDestroy(&fields[i])); 127c7543cceSMatthew G Knepley } 1289566063dSJacob Faibussowitsch PetscCall(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) { 1369566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(snes->jacobian_pre, &mb->bs)); 1371aa26658SKarl Rupp } else mb->bs = 1; 138c7543cceSMatthew G Knepley } 139c7543cceSMatthew G Knepley 1409566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, ((PetscObject)snes)->prefix, "-snes_multiblock_default", &flg, NULL)); 1419566063dSJacob Faibussowitsch PetscCall(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 1469566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(snes->jacobian_pre, &nmin, &nmax)); 1479566063dSJacob Faibussowitsch PetscCall(MatFindZeroDiagonals(snes->jacobian_pre, &zerodiags)); 1489566063dSJacob Faibussowitsch PetscCall(ISComplement(zerodiags, nmin, nmax, &rest)); 1499566063dSJacob Faibussowitsch PetscCall(SNESMultiblockSetIS(snes, "0", rest)); 1509566063dSJacob Faibussowitsch PetscCall(SNESMultiblockSetIS(snes, "1", zerodiags)); 1519566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zerodiags)); 1529566063dSJacob Faibussowitsch PetscCall(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(). */ 1579566063dSJacob Faibussowitsch PetscCall(SNESMultiblockSetFieldsRuntime_Private(snes)); 1589566063dSJacob Faibussowitsch if (mb->defined) PetscCall(PetscInfo(snes, "Blocks defined using the options database\n")); 159c7543cceSMatthew G Knepley } 160c7543cceSMatthew G Knepley if (flg || !mb->defined) { 1619566063dSJacob Faibussowitsch PetscCall(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 16563a3b9bcSJacob Faibussowitsch PetscCall(PetscSNPrintf(name, sizeof(name), "%" PetscInt_FMT, i)); 1669566063dSJacob Faibussowitsch PetscCall(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 1779566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(snes->jacobian_pre, &nmin, &nmax)); 1789566063dSJacob Faibussowitsch PetscCall(ISComplement(blocks->is, nmin, nmax, &is2)); 1799566063dSJacob Faibussowitsch PetscCall(SNESMultiblockSetIS(snes, "1", is2)); 1809566063dSJacob Faibussowitsch PetscCall(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 } 18308401ef6SPierre Jolivet PetscCheck(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 */ 197d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUp_Multiblock(SNES snes) 198d71ae5a4SJacob Faibussowitsch { 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; 2049566063dSJacob Faibussowitsch PetscCall(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; 2159566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(snes->jacobian_pre, &rstart, &rend)); 2169566063dSJacob Faibussowitsch PetscCall(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) { 2209566063dSJacob Faibussowitsch PetscCall(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 2259566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nfields * nslots, &ii)); 226c7543cceSMatthew G Knepley for (j = 0; j < nslots; ++j) { 227ad540459SPierre Jolivet for (k = 0; k < nfields; ++k) ii[nfields * j + k] = rstart + bs * j + fields[k]; 228c7543cceSMatthew G Knepley } 2299566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)snes), nslots * nfields, ii, PETSC_OWN_POINTER, &blocks->is)); 230c7543cceSMatthew G Knepley } else { 2319566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)snes), nslots, rstart + blocks->fields[0], bs, &blocks->is)); 232c7543cceSMatthew G Knepley } 233c7543cceSMatthew G Knepley } 2349566063dSJacob Faibussowitsch PetscCall(ISSorted(blocks->is, &sorted)); 23528b400f6SJacob Faibussowitsch PetscCheck(sorted, PETSC_COMM_SELF, PETSC_ERR_USER, "Fields must be sorted when creating split"); 236c7543cceSMatthew G Knepley blocks = blocks->next; 237c7543cceSMatthew G Knepley } 238c7543cceSMatthew G Knepley } 239c7543cceSMatthew G Knepley 240c7543cceSMatthew G Knepley #if 0 241c7543cceSMatthew G Knepley /* Create matrices */ 242c7543cceSMatthew G Knepley ilink = jac->head; 243c7543cceSMatthew G Knepley if (!jac->pmat) { 2449566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nsplit,&jac->pmat)); 245c7543cceSMatthew G Knepley for (i=0; i<nsplit; i++) { 2469566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pc->pmat,ilink->is,ilink->is,MAT_INITIAL_MATRIX,&jac->pmat[i])); 247c7543cceSMatthew G Knepley ilink = ilink->next; 248c7543cceSMatthew G Knepley } 249c7543cceSMatthew G Knepley } else { 250c7543cceSMatthew G Knepley for (i=0; i<nsplit; i++) { 2519566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pc->pmat,ilink->is,ilink->is,MAT_REUSE_MATRIX,&jac->pmat[i])); 252c7543cceSMatthew G Knepley ilink = ilink->next; 253c7543cceSMatthew G Knepley } 254c7543cceSMatthew G Knepley } 255c7543cceSMatthew G Knepley if (jac->realdiagonal) { 256c7543cceSMatthew G Knepley ilink = jac->head; 257c7543cceSMatthew G Knepley if (!jac->mat) { 2589566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nsplit,&jac->mat)); 259c7543cceSMatthew G Knepley for (i=0; i<nsplit; i++) { 2609566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pc->mat,ilink->is,ilink->is,MAT_INITIAL_MATRIX,&jac->mat[i])); 261c7543cceSMatthew G Knepley ilink = ilink->next; 262c7543cceSMatthew G Knepley } 263c7543cceSMatthew G Knepley } else { 264c7543cceSMatthew G Knepley for (i=0; i<nsplit; i++) { 2659566063dSJacob Faibussowitsch if (jac->mat[i]) PetscCall(MatCreateSubMatrix(pc->mat,ilink->is,ilink->is,MAT_REUSE_MATRIX,&jac->mat[i])); 266c7543cceSMatthew G Knepley ilink = ilink->next; 267c7543cceSMatthew G Knepley } 268c7543cceSMatthew G Knepley } 2691aa26658SKarl Rupp } else jac->mat = jac->pmat; 270c7543cceSMatthew G Knepley #endif 271c7543cceSMatthew G Knepley 272c7543cceSMatthew G Knepley #if 0 273c7543cceSMatthew G Knepley if (jac->type != PC_COMPOSITE_ADDITIVE && jac->type != PC_COMPOSITE_SCHUR) { 274c7543cceSMatthew G Knepley /* extract the rows of the matrix associated with each field: used for efficient computation of residual inside algorithm */ 275c7543cceSMatthew G Knepley ilink = jac->head; 276c7543cceSMatthew G Knepley if (!jac->Afield) { 2779566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nsplit,&jac->Afield)); 278c7543cceSMatthew G Knepley for (i=0; i<nsplit; i++) { 2799566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pc->mat,ilink->is,NULL,MAT_INITIAL_MATRIX,&jac->Afield[i])); 280c7543cceSMatthew G Knepley ilink = ilink->next; 281c7543cceSMatthew G Knepley } 282c7543cceSMatthew G Knepley } else { 283c7543cceSMatthew G Knepley for (i=0; i<nsplit; i++) { 2849566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pc->mat,ilink->is,NULL,MAT_REUSE_MATRIX,&jac->Afield[i])); 285c7543cceSMatthew G Knepley ilink = ilink->next; 286c7543cceSMatthew G Knepley } 287c7543cceSMatthew G Knepley } 288c7543cceSMatthew G Knepley } 289c7543cceSMatthew G Knepley #endif 290c7543cceSMatthew G Knepley 291b665c654SMatthew G Knepley if (mb->type == PC_COMPOSITE_SCHUR) { 292c7543cceSMatthew G Knepley #if 0 293c7543cceSMatthew G Knepley IS ccis; 294c7543cceSMatthew G Knepley PetscInt rstart,rend; 29508401ef6SPierre Jolivet PetscCheck(nsplit == 2,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"To use Schur complement preconditioner you must have exactly 2 fields"); 296c7543cceSMatthew G Knepley 297c7543cceSMatthew G Knepley /* When extracting off-diagonal submatrices, we take complements from this range */ 2989566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRangeColumn(pc->mat,&rstart,&rend)); 299c7543cceSMatthew G Knepley 300c7543cceSMatthew G Knepley /* need to handle case when one is resetting up the preconditioner */ 301c7543cceSMatthew G Knepley if (jac->schur) { 302c7543cceSMatthew G Knepley ilink = jac->head; 3039566063dSJacob Faibussowitsch PetscCall(ISComplement(ilink->is,rstart,rend,&ccis)); 3049566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pc->mat,ilink->is,ccis,MAT_REUSE_MATRIX,&jac->B)); 3059566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ccis)); 306c7543cceSMatthew G Knepley ilink = ilink->next; 3079566063dSJacob Faibussowitsch PetscCall(ISComplement(ilink->is,rstart,rend,&ccis)); 3089566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pc->mat,ilink->is,ccis,MAT_REUSE_MATRIX,&jac->C)); 3099566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ccis)); 3109566063dSJacob Faibussowitsch PetscCall(MatSchurComplementUpdateSubMatrices(jac->schur,jac->mat[0],jac->pmat[0],jac->B,jac->C,jac->pmat[1])); 3119566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(jac->kspschur,jac->schur,FieldSplitSchurPre(jac),pc->flag)); 312c7543cceSMatthew G Knepley 313c7543cceSMatthew G Knepley } else { 314c7543cceSMatthew G Knepley KSP ksp; 315c7543cceSMatthew G Knepley char schurprefix[256]; 316c7543cceSMatthew G Knepley 317c7543cceSMatthew G Knepley /* extract the A01 and A10 matrices */ 318c7543cceSMatthew G Knepley ilink = jac->head; 3199566063dSJacob Faibussowitsch PetscCall(ISComplement(ilink->is,rstart,rend,&ccis)); 3209566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pc->mat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->B)); 3219566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ccis)); 322c7543cceSMatthew G Knepley ilink = ilink->next; 3239566063dSJacob Faibussowitsch PetscCall(ISComplement(ilink->is,rstart,rend,&ccis)); 3249566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pc->mat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->C)); 3259566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ccis)); 326c7543cceSMatthew G Knepley /* Use mat[0] (diagonal block of the real matrix) preconditioned by pmat[0] */ 3279566063dSJacob Faibussowitsch PetscCall(MatCreateSchurComplement(jac->mat[0],jac->pmat[0],jac->B,jac->C,jac->mat[1],&jac->schur)); 328c7543cceSMatthew G Knepley /* set tabbing and options prefix of KSP inside the MatSchur */ 3299566063dSJacob Faibussowitsch PetscCall(MatSchurComplementGetKSP(jac->schur,&ksp)); 3309566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)ksp,(PetscObject)pc,2)); 3319566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(schurprefix,sizeof(schurprefix),"%sfieldsplit_%s_",((PetscObject)pc)->prefix ? ((PetscObject)pc)->prefix : "",jac->head->splitname)); 3329566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(ksp,schurprefix)); 3339566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(jac->schur)); 334c7543cceSMatthew G Knepley 3359566063dSJacob Faibussowitsch PetscCall(KSPCreate(PetscObjectComm((PetscObject)pc),&jac->kspschur)); 3369566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)jac->kspschur,(PetscObject)pc,1)); 3379566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(jac->kspschur,jac->schur,FieldSplitSchurPre(jac))); 338c7543cceSMatthew G Knepley if (jac->schurpre == PC_FIELDSPLIT_SCHUR_PRE_SELF) { 339c7543cceSMatthew G Knepley PC pc; 3409566063dSJacob Faibussowitsch PetscCall(KSPGetPC(jac->kspschur,&pc)); 3419566063dSJacob Faibussowitsch PetscCall(PCSetType(pc,PCNONE)); 342c7543cceSMatthew G Knepley /* Note: This is bad if there exist preconditioners for MATSCHURCOMPLEMENT */ 343c7543cceSMatthew G Knepley } 3449566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(schurprefix,sizeof(schurprefix),"%sfieldsplit_%s_",((PetscObject)pc)->prefix ? ((PetscObject)pc)->prefix : "",ilink->splitname)); 3459566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(jac->kspschur,schurprefix)); 346c7543cceSMatthew G Knepley /* really want setfromoptions called in PCSetFromOptions_FieldSplit(), but it is not ready yet */ 3479566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(jac->kspschur)); 348c7543cceSMatthew G Knepley 3499566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(2,&jac->x,2,&jac->y)); 3509566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(jac->pmat[0],&jac->x[0],&jac->y[0])); 3519566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(jac->pmat[1],&jac->x[1],&jac->y[1])); 352c7543cceSMatthew G Knepley ilink = jac->head; 353c7543cceSMatthew G Knepley ilink->x = jac->x[0]; ilink->y = jac->y[0]; 354c7543cceSMatthew G Knepley ilink = ilink->next; 355c7543cceSMatthew G Knepley ilink->x = jac->x[1]; ilink->y = jac->y[1]; 356c7543cceSMatthew G Knepley } 357c7543cceSMatthew G Knepley #endif 358c7543cceSMatthew G Knepley } else { 359c7543cceSMatthew G Knepley /* Set up the individual SNESs */ 360c7543cceSMatthew G Knepley blocks = mb->blocks; 361c7543cceSMatthew G Knepley i = 0; 362c7543cceSMatthew G Knepley while (blocks) { 363b665c654SMatthew G Knepley /*TODO: Set these correctly */ 3649566063dSJacob Faibussowitsch /* PetscCall(SNESSetFunction(blocks->snes, blocks->x, func)); */ 3659566063dSJacob Faibussowitsch /* PetscCall(SNESSetJacobian(blocks->snes, blocks->x, jac)); */ 3669566063dSJacob Faibussowitsch PetscCall(VecDuplicate(blocks->snes->vec_sol, &blocks->x)); 367c7543cceSMatthew G Knepley /* really want setfromoptions called in SNESSetFromOptions_Multiblock(), but it is not ready yet */ 3689566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(blocks->snes)); 3699566063dSJacob Faibussowitsch PetscCall(SNESSetUp(blocks->snes)); 370c7543cceSMatthew G Knepley blocks = blocks->next; 371c7543cceSMatthew G Knepley i++; 372c7543cceSMatthew G Knepley } 373c7543cceSMatthew G Knepley } 374c7543cceSMatthew G Knepley 375c7543cceSMatthew G Knepley /* Compute scatter contexts needed by multiplicative versions and non-default splits */ 376c7543cceSMatthew G Knepley if (!mb->blocks->sctx) { 377c7543cceSMatthew G Knepley Vec xtmp; 378c7543cceSMatthew G Knepley 379c7543cceSMatthew G Knepley blocks = mb->blocks; 3809566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(snes->jacobian_pre, &xtmp, NULL)); 381c7543cceSMatthew G Knepley while (blocks) { 3829566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(xtmp, blocks->is, blocks->x, NULL, &blocks->sctx)); 383c7543cceSMatthew G Knepley blocks = blocks->next; 384c7543cceSMatthew G Knepley } 3859566063dSJacob Faibussowitsch PetscCall(VecDestroy(&xtmp)); 386c7543cceSMatthew G Knepley } 387c7543cceSMatthew G Knepley PetscFunctionReturn(0); 388c7543cceSMatthew G Knepley } 389c7543cceSMatthew G Knepley 390c7543cceSMatthew G Knepley /* 391c7543cceSMatthew G Knepley SNESSetFromOptions_Multiblock - Sets various parameters for the SNESMULTIBLOCK method. 392c7543cceSMatthew G Knepley 393c7543cceSMatthew G Knepley Input Parameter: 394c7543cceSMatthew G Knepley . snes - the SNES context 395c7543cceSMatthew G Knepley 396c7543cceSMatthew G Knepley Application Interface Routine: SNESSetFromOptions() 397c7543cceSMatthew G Knepley */ 398d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetFromOptions_Multiblock(SNES snes, PetscOptionItems *PetscOptionsObject) 399d71ae5a4SJacob Faibussowitsch { 400c7543cceSMatthew G Knepley SNES_Multiblock *mb = (SNES_Multiblock *)snes->data; 401c7543cceSMatthew G Knepley PCCompositeType ctype; 402c7543cceSMatthew G Knepley PetscInt bs; 403c7543cceSMatthew G Knepley PetscBool flg; 404c7543cceSMatthew G Knepley 405c7543cceSMatthew G Knepley PetscFunctionBegin; 406d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "SNES Multiblock options"); 4079566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_multiblock_block_size", "Blocksize that defines number of fields", "PCFieldSplitSetBlockSize", mb->bs, &bs, &flg)); 4089566063dSJacob Faibussowitsch if (flg) PetscCall(SNESMultiblockSetBlockSize(snes, bs)); 4099566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-snes_multiblock_type", "Type of composition", "PCFieldSplitSetType", PCCompositeTypes, (PetscEnum)mb->type, (PetscEnum *)&ctype, &flg)); 4101baa6e33SBarry Smith if (flg) PetscCall(SNESMultiblockSetType(snes, ctype)); 411c7543cceSMatthew G Knepley /* Only setup fields once */ 412b665c654SMatthew G Knepley if ((mb->bs > 0) && (mb->numBlocks == 0)) { 413c7543cceSMatthew G Knepley /* only allow user to set fields from command line if bs is already known, otherwise user can set them in SNESMultiblockSetDefaults() */ 4149566063dSJacob Faibussowitsch PetscCall(SNESMultiblockSetFieldsRuntime_Private(snes)); 4159566063dSJacob Faibussowitsch if (mb->defined) PetscCall(PetscInfo(snes, "Blocks defined using the options database\n")); 416c7543cceSMatthew G Knepley } 417d0609cedSBarry Smith PetscOptionsHeadEnd(); 418c7543cceSMatthew G Knepley PetscFunctionReturn(0); 419c7543cceSMatthew G Knepley } 420c7543cceSMatthew G Knepley 421c7543cceSMatthew G Knepley /* 422c7543cceSMatthew G Knepley SNESView_Multiblock - Prints info from the SNESMULTIBLOCK data structure. 423c7543cceSMatthew G Knepley 424c7543cceSMatthew G Knepley Input Parameters: 425c7543cceSMatthew G Knepley + SNES - the SNES context 426c7543cceSMatthew G Knepley - viewer - visualization context 427c7543cceSMatthew G Knepley 428c7543cceSMatthew G Knepley Application Interface Routine: SNESView() 429c7543cceSMatthew G Knepley */ 430d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESView_Multiblock(SNES snes, PetscViewer viewer) 431d71ae5a4SJacob Faibussowitsch { 432c7543cceSMatthew G Knepley SNES_Multiblock *mb = (SNES_Multiblock *)snes->data; 433c7543cceSMatthew G Knepley BlockDesc blocks = mb->blocks; 434c7543cceSMatthew G Knepley PetscBool iascii; 435c7543cceSMatthew G Knepley 436c7543cceSMatthew G Knepley PetscFunctionBegin; 4379566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 438c7543cceSMatthew G Knepley if (iascii) { 43963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Multiblock with %s composition: total blocks = %" PetscInt_FMT ", blocksize = %" PetscInt_FMT "\n", PCCompositeTypes[mb->type], mb->numBlocks, mb->bs)); 4409566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Solver info for each split is in the following SNES objects:\n")); 4419566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 442c7543cceSMatthew G Knepley while (blocks) { 443c7543cceSMatthew G Knepley if (blocks->fields) { 444c7543cceSMatthew G Knepley PetscInt j; 445c7543cceSMatthew G Knepley 4469566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Block %s Fields ", blocks->name)); 4479566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 448c7543cceSMatthew G Knepley for (j = 0; j < blocks->nfields; ++j) { 44948a46eb9SPierre Jolivet if (j > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ",")); 45063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, blocks->fields[j])); 451c7543cceSMatthew G Knepley } 4529566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 4539566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 454c7543cceSMatthew G Knepley } else { 4559566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Block %s Defined by IS\n", blocks->name)); 456c7543cceSMatthew G Knepley } 4579566063dSJacob Faibussowitsch PetscCall(SNESView(blocks->snes, viewer)); 458c7543cceSMatthew G Knepley blocks = blocks->next; 459c7543cceSMatthew G Knepley } 4609566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 461c7543cceSMatthew G Knepley } 462c7543cceSMatthew G Knepley PetscFunctionReturn(0); 463c7543cceSMatthew G Knepley } 464c7543cceSMatthew G Knepley 465c7543cceSMatthew G Knepley /* 466c7543cceSMatthew G Knepley SNESSolve_Multiblock - Solves a nonlinear system with the Multiblock method. 467c7543cceSMatthew G Knepley 468c7543cceSMatthew G Knepley Input Parameters: 469c7543cceSMatthew G Knepley . snes - the SNES context 470c7543cceSMatthew G Knepley 471c7543cceSMatthew G Knepley Output Parameter: 472c7543cceSMatthew G Knepley . outits - number of iterations until termination 473c7543cceSMatthew G Knepley 474c7543cceSMatthew G Knepley Application Interface Routine: SNESSolve() 475c7543cceSMatthew G Knepley */ 476d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSolve_Multiblock(SNES snes) 477d71ae5a4SJacob Faibussowitsch { 478c7543cceSMatthew G Knepley SNES_Multiblock *mb = (SNES_Multiblock *)snes->data; 479c7543cceSMatthew G Knepley Vec X, Y, F; 480c7543cceSMatthew G Knepley PetscReal fnorm; 481c7543cceSMatthew G Knepley PetscInt maxits, i; 482c7543cceSMatthew G Knepley 483c7543cceSMatthew G Knepley PetscFunctionBegin; 4840b121fc5SBarry Smith PetscCheck(!snes->xl && !snes->xu && !snes->ops->computevariablebounds, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONGSTATE, "SNES solver %s does not support bounds", ((PetscObject)snes)->type_name); 485c579b300SPatrick Farrell 486c7543cceSMatthew G Knepley snes->reason = SNES_CONVERGED_ITERATING; 487c7543cceSMatthew G Knepley 488c7543cceSMatthew G Knepley maxits = snes->max_its; /* maximum number of iterations */ 489c7543cceSMatthew G Knepley X = snes->vec_sol; /* X^n */ 490c7543cceSMatthew G Knepley Y = snes->vec_sol_update; /* \tilde X */ 491c7543cceSMatthew G Knepley F = snes->vec_func; /* residual vector */ 492c7543cceSMatthew G Knepley 4939566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(X, mb->bs)); 4949566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(Y, mb->bs)); 4959566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(F, mb->bs)); 4969566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes)); 497c7543cceSMatthew G Knepley snes->iter = 0; 498c7543cceSMatthew G Knepley snes->norm = 0.; 4999566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes)); 500e4ed7901SPeter Brune 501e4ed7901SPeter Brune if (!snes->vec_func_init_set) { 5029566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, X, F)); 5031aa26658SKarl Rupp } else snes->vec_func_init_set = PETSC_FALSE; 5041aa26658SKarl Rupp 5059566063dSJacob Faibussowitsch PetscCall(VecNorm(F, NORM_2, &fnorm)); /* fnorm <- ||F|| */ 506422a814eSBarry Smith SNESCheckFunctionNorm(snes, fnorm); 5079566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes)); 508c7543cceSMatthew G Knepley snes->norm = fnorm; 5099566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes)); 5109566063dSJacob Faibussowitsch PetscCall(SNESLogConvergenceHistory(snes, fnorm, 0)); 5119566063dSJacob Faibussowitsch PetscCall(SNESMonitor(snes, 0, fnorm)); 512c7543cceSMatthew G Knepley 513c7543cceSMatthew G Knepley /* test convergence */ 514dbbe0bcdSBarry Smith PetscUseTypeMethod(snes, converged, 0, 0.0, 0.0, fnorm, &snes->reason, snes->cnvP); 515c7543cceSMatthew G Knepley if (snes->reason) PetscFunctionReturn(0); 516c7543cceSMatthew G Knepley 517c7543cceSMatthew G Knepley for (i = 0; i < maxits; i++) { 518c7543cceSMatthew G Knepley /* Call general purpose update function */ 519dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, update, snes->iter); 520c7543cceSMatthew G Knepley /* Compute X^{new} from subsolves */ 521c7543cceSMatthew G Knepley if (mb->type == PC_COMPOSITE_ADDITIVE) { 522c7543cceSMatthew G Knepley BlockDesc blocks = mb->blocks; 523c7543cceSMatthew G Knepley 524b665c654SMatthew G Knepley if (mb->defaultblocks) { 525b665c654SMatthew G Knepley /*TODO: Make an array of Vecs for this */ 5269566063dSJacob Faibussowitsch /* PetscCall(VecStrideGatherAll(X, mb->x, INSERT_VALUES)); */ 527c7543cceSMatthew G Knepley while (blocks) { 5289566063dSJacob Faibussowitsch PetscCall(SNESSolve(blocks->snes, NULL, blocks->x)); 529c7543cceSMatthew G Knepley blocks = blocks->next; 530c7543cceSMatthew G Knepley } 5319566063dSJacob Faibussowitsch /* PetscCall(VecStrideScatterAll(mb->x, X, INSERT_VALUES)); */ 532c7543cceSMatthew G Knepley } else { 533c7543cceSMatthew G Knepley while (blocks) { 5349566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(blocks->sctx, X, blocks->x, INSERT_VALUES, SCATTER_FORWARD)); 5359566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(blocks->sctx, X, blocks->x, INSERT_VALUES, SCATTER_FORWARD)); 5369566063dSJacob Faibussowitsch PetscCall(SNESSolve(blocks->snes, NULL, blocks->x)); 5379566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(blocks->sctx, blocks->x, X, INSERT_VALUES, SCATTER_REVERSE)); 5389566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(blocks->sctx, blocks->x, X, INSERT_VALUES, SCATTER_REVERSE)); 539c7543cceSMatthew G Knepley blocks = blocks->next; 540c7543cceSMatthew G Knepley } 541c7543cceSMatthew G Knepley } 54263a3b9bcSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)snes), PETSC_ERR_SUP, "Unsupported or unknown composition %d", (int)mb->type); 543c7543cceSMatthew G Knepley /* Compute F(X^{new}) */ 5449566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, X, F)); 5459566063dSJacob Faibussowitsch PetscCall(VecNorm(F, NORM_2, &fnorm)); 546422a814eSBarry Smith SNESCheckFunctionNorm(snes, fnorm); 547c7543cceSMatthew G Knepley 548e71169deSBarry Smith if (snes->nfuncs >= snes->max_funcs && snes->max_funcs >= 0) { 549c7543cceSMatthew G Knepley snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 550c7543cceSMatthew G Knepley break; 551c7543cceSMatthew G Knepley } 552422a814eSBarry Smith 553c7543cceSMatthew G Knepley /* Monitor convergence */ 5549566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes)); 555c7543cceSMatthew G Knepley snes->iter = i + 1; 556c7543cceSMatthew G Knepley snes->norm = fnorm; 5579566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes)); 5589566063dSJacob Faibussowitsch PetscCall(SNESLogConvergenceHistory(snes, snes->norm, 0)); 5599566063dSJacob Faibussowitsch PetscCall(SNESMonitor(snes, snes->iter, snes->norm)); 560c7543cceSMatthew G Knepley /* Test for convergence */ 561dbbe0bcdSBarry Smith PetscUseTypeMethod(snes, converged, snes->iter, 0.0, 0.0, fnorm, &snes->reason, snes->cnvP); 562c7543cceSMatthew G Knepley if (snes->reason) break; 563c7543cceSMatthew G Knepley } 564c7543cceSMatthew G Knepley if (i == maxits) { 56563a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Maximum number of iterations has been reached: %" PetscInt_FMT "\n", maxits)); 566c7543cceSMatthew G Knepley if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 567c7543cceSMatthew G Knepley } 568c7543cceSMatthew G Knepley PetscFunctionReturn(0); 569c7543cceSMatthew G Knepley } 570c7543cceSMatthew G Knepley 571d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMultiblockSetFields_Default(SNES snes, const char name[], PetscInt n, const PetscInt fields[]) 572d71ae5a4SJacob Faibussowitsch { 573c7543cceSMatthew G Knepley SNES_Multiblock *mb = (SNES_Multiblock *)snes->data; 574c7543cceSMatthew G Knepley BlockDesc newblock, next = mb->blocks; 575c7543cceSMatthew G Knepley char prefix[128]; 576c7543cceSMatthew G Knepley PetscInt i; 577c7543cceSMatthew G Knepley 578c7543cceSMatthew G Knepley PetscFunctionBegin; 579c7543cceSMatthew G Knepley if (mb->defined) { 5809566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Ignoring new block \"%s\" because the blocks have already been defined\n", name)); 581c7543cceSMatthew G Knepley PetscFunctionReturn(0); 582c7543cceSMatthew G Knepley } 583c7543cceSMatthew G Knepley for (i = 0; i < n; ++i) { 58463a3b9bcSJacob Faibussowitsch PetscCheck(fields[i] < mb->bs, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field %" PetscInt_FMT " requested but only %" PetscInt_FMT " exist", fields[i], mb->bs); 58563a3b9bcSJacob Faibussowitsch PetscCheck(fields[i] >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative field %" PetscInt_FMT " requested", fields[i]); 586c7543cceSMatthew G Knepley } 5879566063dSJacob Faibussowitsch PetscCall(PetscNew(&newblock)); 588c7543cceSMatthew G Knepley if (name) { 5899566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(name, &newblock->name)); 590c7543cceSMatthew G Knepley } else { 591c7543cceSMatthew G Knepley PetscInt len = floor(log10(mb->numBlocks)) + 1; 592c7543cceSMatthew G Knepley 5939566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(len + 1, &newblock->name)); 59463a3b9bcSJacob Faibussowitsch PetscCall(PetscSNPrintf(newblock->name, len, "%" PetscInt_FMT, mb->numBlocks)); 595c7543cceSMatthew G Knepley } 596c7543cceSMatthew G Knepley newblock->nfields = n; 5971aa26658SKarl Rupp 5989566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &newblock->fields)); 5999566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(newblock->fields, fields, n)); 6001aa26658SKarl Rupp 6010298fd71SBarry Smith newblock->next = NULL; 6021aa26658SKarl Rupp 6039566063dSJacob Faibussowitsch PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &newblock->snes)); 6049566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)newblock->snes, (PetscObject)snes, 1)); 6059566063dSJacob Faibussowitsch PetscCall(SNESSetType(newblock->snes, SNESNRICHARDSON)); 6069566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(prefix, sizeof(prefix), "%smultiblock_%s_", ((PetscObject)snes)->prefix ? ((PetscObject)snes)->prefix : "", newblock->name)); 6079566063dSJacob Faibussowitsch PetscCall(SNESSetOptionsPrefix(newblock->snes, prefix)); 608c7543cceSMatthew G Knepley 609c7543cceSMatthew G Knepley if (!next) { 610c7543cceSMatthew G Knepley mb->blocks = newblock; 6110298fd71SBarry Smith newblock->previous = NULL; 612c7543cceSMatthew G Knepley } else { 613ad540459SPierre Jolivet while (next->next) next = next->next; 614c7543cceSMatthew G Knepley next->next = newblock; 615c7543cceSMatthew G Knepley newblock->previous = next; 616c7543cceSMatthew G Knepley } 617c7543cceSMatthew G Knepley mb->numBlocks++; 618c7543cceSMatthew G Knepley PetscFunctionReturn(0); 619c7543cceSMatthew G Knepley } 620c7543cceSMatthew G Knepley 621d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMultiblockSetIS_Default(SNES snes, const char name[], IS is) 622d71ae5a4SJacob Faibussowitsch { 623c7543cceSMatthew G Knepley SNES_Multiblock *mb = (SNES_Multiblock *)snes->data; 624c7543cceSMatthew G Knepley BlockDesc newblock, next = mb->blocks; 625c7543cceSMatthew G Knepley char prefix[128]; 626c7543cceSMatthew G Knepley 627c7543cceSMatthew G Knepley PetscFunctionBegin; 628c7543cceSMatthew G Knepley if (mb->defined) { 6299566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Ignoring new block \"%s\" because the blocks have already been defined\n", name)); 630c7543cceSMatthew G Knepley PetscFunctionReturn(0); 631c7543cceSMatthew G Knepley } 6329566063dSJacob Faibussowitsch PetscCall(PetscNew(&newblock)); 633c7543cceSMatthew G Knepley if (name) { 6349566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(name, &newblock->name)); 635c7543cceSMatthew G Knepley } else { 636c7543cceSMatthew G Knepley PetscInt len = floor(log10(mb->numBlocks)) + 1; 637c7543cceSMatthew G Knepley 6389566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(len + 1, &newblock->name)); 63963a3b9bcSJacob Faibussowitsch PetscCall(PetscSNPrintf(newblock->name, len, "%" PetscInt_FMT, mb->numBlocks)); 640c7543cceSMatthew G Knepley } 641c7543cceSMatthew G Knepley newblock->is = is; 6421aa26658SKarl Rupp 6439566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is)); 6441aa26658SKarl Rupp 6450298fd71SBarry Smith newblock->next = NULL; 6461aa26658SKarl Rupp 6479566063dSJacob Faibussowitsch PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &newblock->snes)); 6489566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)newblock->snes, (PetscObject)snes, 1)); 6499566063dSJacob Faibussowitsch PetscCall(SNESSetType(newblock->snes, SNESNRICHARDSON)); 6509566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(prefix, sizeof(prefix), "%smultiblock_%s_", ((PetscObject)snes)->prefix ? ((PetscObject)snes)->prefix : "", newblock->name)); 6519566063dSJacob Faibussowitsch PetscCall(SNESSetOptionsPrefix(newblock->snes, prefix)); 652c7543cceSMatthew G Knepley 653c7543cceSMatthew G Knepley if (!next) { 654c7543cceSMatthew G Knepley mb->blocks = newblock; 6550298fd71SBarry Smith newblock->previous = NULL; 656c7543cceSMatthew G Knepley } else { 657ad540459SPierre Jolivet while (next->next) next = next->next; 658c7543cceSMatthew G Knepley next->next = newblock; 659c7543cceSMatthew G Knepley newblock->previous = next; 660c7543cceSMatthew G Knepley } 661c7543cceSMatthew G Knepley mb->numBlocks++; 662c7543cceSMatthew G Knepley PetscFunctionReturn(0); 663c7543cceSMatthew G Knepley } 664c7543cceSMatthew G Knepley 665d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMultiblockSetBlockSize_Default(SNES snes, PetscInt bs) 666d71ae5a4SJacob Faibussowitsch { 667c7543cceSMatthew G Knepley SNES_Multiblock *mb = (SNES_Multiblock *)snes->data; 668c7543cceSMatthew G Knepley 669c7543cceSMatthew G Knepley PetscFunctionBegin; 67063a3b9bcSJacob Faibussowitsch PetscCheck(bs >= 1, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Blocksize must be positive, you gave %" PetscInt_FMT, bs); 6710b121fc5SBarry Smith PetscCheck(mb->bs <= 0 || mb->bs == bs, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONGSTATE, "Cannot change blocksize from %" PetscInt_FMT " to %" PetscInt_FMT " after it has been set", mb->bs, bs); 672c7543cceSMatthew G Knepley mb->bs = bs; 673c7543cceSMatthew G Knepley PetscFunctionReturn(0); 674c7543cceSMatthew G Knepley } 675c7543cceSMatthew G Knepley 676d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMultiblockGetSubSNES_Default(SNES snes, PetscInt *n, SNES **subsnes) 677d71ae5a4SJacob Faibussowitsch { 678c7543cceSMatthew G Knepley SNES_Multiblock *mb = (SNES_Multiblock *)snes->data; 679c7543cceSMatthew G Knepley BlockDesc blocks = mb->blocks; 680c7543cceSMatthew G Knepley PetscInt cnt = 0; 681c7543cceSMatthew G Knepley 682c7543cceSMatthew G Knepley PetscFunctionBegin; 6839566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mb->numBlocks, subsnes)); 684c7543cceSMatthew G Knepley while (blocks) { 685c7543cceSMatthew G Knepley (*subsnes)[cnt++] = blocks->snes; 686c7543cceSMatthew G Knepley blocks = blocks->next; 687c7543cceSMatthew G Knepley } 68863a3b9bcSJacob Faibussowitsch PetscCheck(cnt == mb->numBlocks, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Corrupt SNESMULTIBLOCK object: number of blocks in linked list %" PetscInt_FMT " does not match number in object %" PetscInt_FMT, cnt, mb->numBlocks); 6891aa26658SKarl Rupp 6901aa26658SKarl Rupp if (n) *n = mb->numBlocks; 691c7543cceSMatthew G Knepley PetscFunctionReturn(0); 692c7543cceSMatthew G Knepley } 693c7543cceSMatthew G Knepley 694d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMultiblockSetType_Default(SNES snes, PCCompositeType type) 695d71ae5a4SJacob Faibussowitsch { 69687bd6022SMatthew G Knepley SNES_Multiblock *mb = (SNES_Multiblock *)snes->data; 69787bd6022SMatthew G Knepley 69887bd6022SMatthew G Knepley PetscFunctionBegin; 69987bd6022SMatthew G Knepley mb->type = type; 70087bd6022SMatthew G Knepley if (type == PC_COMPOSITE_SCHUR) { 70187bd6022SMatthew G Knepley #if 1 70282f516ccSBarry Smith SETERRQ(PetscObjectComm((PetscObject)snes), PETSC_ERR_SUP, "The Schur composite type is not yet supported"); 70387bd6022SMatthew G Knepley #else 70487bd6022SMatthew G Knepley snes->ops->solve = SNESSolve_Multiblock_Schur; 70587bd6022SMatthew G Knepley snes->ops->view = SNESView_Multiblock_Schur; 7061aa26658SKarl Rupp 7079566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESMultiblockGetSubSNES_C", SNESMultiblockGetSubSNES_Schur)); 7089566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESMultiblockSchurPrecondition_C", SNESMultiblockSchurPrecondition_Default)); 70987bd6022SMatthew G Knepley #endif 71087bd6022SMatthew G Knepley } else { 71187bd6022SMatthew G Knepley snes->ops->solve = SNESSolve_Multiblock; 71287bd6022SMatthew G Knepley snes->ops->view = SNESView_Multiblock; 7131aa26658SKarl Rupp 7149566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESMultiblockGetSubSNES_C", SNESMultiblockGetSubSNES_Default)); 7159566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESMultiblockSchurPrecondition_C", 0)); 71687bd6022SMatthew G Knepley } 71787bd6022SMatthew G Knepley PetscFunctionReturn(0); 71887bd6022SMatthew G Knepley } 71987bd6022SMatthew G Knepley 720c7543cceSMatthew G Knepley /*@ 721f6dfbefdSBarry Smith SNESMultiblockSetFields - Sets the fields for one particular block in a `SNESMULTBLOCK` solver 722c7543cceSMatthew G Knepley 723*c3339decSBarry Smith Logically Collective 724c7543cceSMatthew G Knepley 725c7543cceSMatthew G Knepley Input Parameters: 726c7543cceSMatthew G Knepley + snes - the solver 7270298fd71SBarry Smith . name - name of this block, if NULL the number of the block is used 728c7543cceSMatthew G Knepley . n - the number of fields in this block 729c7543cceSMatthew G Knepley - fields - the fields in this block 730c7543cceSMatthew G Knepley 731c7543cceSMatthew G Knepley Level: intermediate 732c7543cceSMatthew G Knepley 73395452b02SPatrick Sanan Notes: 734f6dfbefdSBarry Smith Use `SNESMultiblockSetIS()` to set a completely general set of row indices as a block. 735c7543cceSMatthew G Knepley 736f6dfbefdSBarry Smith The `SNESMultiblockSetFields()` is for defining blocks as a group of strided indices, or fields. 737c7543cceSMatthew G Knepley For example, if the vector block size is three then one can define a block as field 0, or 738c7543cceSMatthew G Knepley 1 or 2, or field 0,1 or 0,2 or 1,2 which means 739c7543cceSMatthew G Knepley 0xx3xx6xx9xx12 ... x1xx4xx7xx ... xx2xx5xx8xx.. 01x34x67x... 0x1x3x5x7.. x12x45x78x.... 740c7543cceSMatthew G Knepley where the numbered entries indicate what is in the block. 741c7543cceSMatthew G Knepley 742c7543cceSMatthew G Knepley This function is called once per block (it creates a new block each time). Solve options 743c7543cceSMatthew G Knepley for this block will be available under the prefix -multiblock_BLOCKNAME_. 744c7543cceSMatthew G Knepley 745f6dfbefdSBarry Smith .seealso: `SNESMULTBLOCK`, `SNESMultiblockGetSubSNES()`, `SNESMULTIBLOCK`, `SNESMultiblockSetBlockSize()`, `SNESMultiblockSetIS()` 746c7543cceSMatthew G Knepley @*/ 747d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMultiblockSetFields(SNES snes, const char name[], PetscInt n, const PetscInt *fields) 748d71ae5a4SJacob Faibussowitsch { 749c7543cceSMatthew G Knepley PetscFunctionBegin; 750c7543cceSMatthew G Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 751c7543cceSMatthew G Knepley PetscValidCharPointer(name, 2); 75263a3b9bcSJacob Faibussowitsch PetscCheck(n >= 1, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Provided number of fields %" PetscInt_FMT " in split \"%s\" not positive", n, name); 753064a246eSJacob Faibussowitsch PetscValidIntPointer(fields, 4); 754cac4c232SBarry Smith PetscTryMethod(snes, "SNESMultiblockSetFields_C", (SNES, const char[], PetscInt, const PetscInt *), (snes, name, n, fields)); 755c7543cceSMatthew G Knepley PetscFunctionReturn(0); 756c7543cceSMatthew G Knepley } 757c7543cceSMatthew G Knepley 758c7543cceSMatthew G Knepley /*@ 759f6dfbefdSBarry Smith SNESMultiblockSetIS - Sets the global row indices for one particular block in a `SNESMULTBLOCK` solver 760c7543cceSMatthew G Knepley 761*c3339decSBarry Smith Logically Collective 762c7543cceSMatthew G Knepley 763c7543cceSMatthew G Knepley Input Parameters: 764c7543cceSMatthew G Knepley + snes - the solver context 7650298fd71SBarry Smith . name - name of this block, if NULL the number of the block is used 766c7543cceSMatthew G Knepley - is - the index set that defines the global row indices in this block 767c7543cceSMatthew G Knepley 768c7543cceSMatthew G Knepley Notes: 769f6dfbefdSBarry Smith Use `SNESMultiblockSetFields()`, for blocks defined by strides. 770c7543cceSMatthew G Knepley 771c7543cceSMatthew G Knepley This function is called once per block (it creates a new block each time). Solve options 772c7543cceSMatthew G Knepley for this block will be available under the prefix -multiblock_BLOCKNAME_. 773c7543cceSMatthew G Knepley 774c7543cceSMatthew G Knepley Level: intermediate 775c7543cceSMatthew G Knepley 776f6dfbefdSBarry Smith .seealso: `SNESMULTBLOCK`, `SNESMultiblockGetSubSNES()`, `SNESMULTIBLOCK`, `SNESMultiblockSetBlockSize()` 777c7543cceSMatthew G Knepley @*/ 778d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMultiblockSetIS(SNES snes, const char name[], IS is) 779d71ae5a4SJacob Faibussowitsch { 780c7543cceSMatthew G Knepley PetscFunctionBegin; 781c7543cceSMatthew G Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 782c7543cceSMatthew G Knepley PetscValidCharPointer(name, 2); 783c7543cceSMatthew G Knepley PetscValidHeaderSpecific(is, IS_CLASSID, 3); 784cac4c232SBarry Smith PetscTryMethod(snes, "SNESMultiblockSetIS_C", (SNES, const char[], IS), (snes, name, is)); 785c7543cceSMatthew G Knepley PetscFunctionReturn(0); 786c7543cceSMatthew G Knepley } 787c7543cceSMatthew G Knepley 788c7543cceSMatthew G Knepley /*@ 789f6dfbefdSBarry Smith SNESMultiblockSetType - Sets the type of block combination used for a `SNESMULTBLOCK` solver 790c7543cceSMatthew G Knepley 791*c3339decSBarry Smith Logically Collective 792c7543cceSMatthew G Knepley 793c7543cceSMatthew G Knepley Input Parameters: 794c7543cceSMatthew G Knepley + snes - the solver context 795f6dfbefdSBarry Smith - type - `PC_COMPOSITE_ADDITIVE`, `PC_COMPOSITE_MULTIPLICATIVE` (default), `PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE` 796c7543cceSMatthew G Knepley 797c7543cceSMatthew G Knepley Options Database Key: 798c7543cceSMatthew G Knepley . -snes_multiblock_type <type: one of multiplicative, additive, symmetric_multiplicative> - Sets block combination type 799c7543cceSMatthew G Knepley 800f6dfbefdSBarry Smith Level: advanced 801c7543cceSMatthew G Knepley 802f6dfbefdSBarry Smith .seealso: `SNESMULTBLOCK`, `PCCompositeSetType()`, `PC_COMPOSITE_ADDITIVE`, `PC_COMPOSITE_MULTIPLICATIVE`, `PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE` 803c7543cceSMatthew G Knepley @*/ 804d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMultiblockSetType(SNES snes, PCCompositeType type) 805d71ae5a4SJacob Faibussowitsch { 806c7543cceSMatthew G Knepley PetscFunctionBegin; 807c7543cceSMatthew G Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 808cac4c232SBarry Smith PetscTryMethod(snes, "SNESMultiblockSetType_C", (SNES, PCCompositeType), (snes, type)); 809c7543cceSMatthew G Knepley PetscFunctionReturn(0); 810c7543cceSMatthew G Knepley } 811c7543cceSMatthew G Knepley 812c7543cceSMatthew G Knepley /*@ 813f6dfbefdSBarry Smith SNESMultiblockSetBlockSize - Sets the block size for structured block division in a `SNESMULTBLOCK` solver. If not set the matrix block size is used. 814c7543cceSMatthew G Knepley 815*c3339decSBarry Smith Logically Collective 816c7543cceSMatthew G Knepley 817c7543cceSMatthew G Knepley Input Parameters: 818c7543cceSMatthew G Knepley + snes - the solver context 819c7543cceSMatthew G Knepley - bs - the block size 820c7543cceSMatthew G Knepley 821c7543cceSMatthew G Knepley Level: intermediate 822c7543cceSMatthew G Knepley 823f6dfbefdSBarry Smith .seealso: `SNESMULTBLOCK`, `SNESMultiblockGetSubSNES()`, `SNESMULTIBLOCK`, `SNESMultiblockSetFields()` 824c7543cceSMatthew G Knepley @*/ 825d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMultiblockSetBlockSize(SNES snes, PetscInt bs) 826d71ae5a4SJacob Faibussowitsch { 827c7543cceSMatthew G Knepley PetscFunctionBegin; 828c7543cceSMatthew G Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 829c7543cceSMatthew G Knepley PetscValidLogicalCollectiveInt(snes, bs, 2); 830cac4c232SBarry Smith PetscTryMethod(snes, "SNESMultiblockSetBlockSize_C", (SNES, PetscInt), (snes, bs)); 831c7543cceSMatthew G Knepley PetscFunctionReturn(0); 832c7543cceSMatthew G Knepley } 833c7543cceSMatthew G Knepley 834c7543cceSMatthew G Knepley /*@C 835f6dfbefdSBarry Smith SNESMultiblockGetSubSNES - Gets the `SNES` contexts for all blocks in a `SNESMULTBLOCK` solver. 836c7543cceSMatthew G Knepley 837f6dfbefdSBarry Smith Not Collective but each `SNES` obtained is parallel 838c7543cceSMatthew G Knepley 839c7543cceSMatthew G Knepley Input Parameter: 840c7543cceSMatthew G Knepley . snes - the solver context 841c7543cceSMatthew G Knepley 842c7543cceSMatthew G Knepley Output Parameters: 843c7543cceSMatthew G Knepley + n - the number of blocks 844f6dfbefdSBarry Smith - subsnes - the array of `SNES` contexts 845c7543cceSMatthew G Knepley 846c7543cceSMatthew G Knepley Note: 847f6dfbefdSBarry Smith After `SNESMultiblockGetSubSNES()` the array of `SNES`s MUST be freed by the user 848f6dfbefdSBarry Smith (not each `SNES`, just the array that contains them). 849c7543cceSMatthew G Knepley 850f6dfbefdSBarry Smith You must call `SNESSetUp()` before calling `SNESMultiblockGetSubSNES()`. 851c7543cceSMatthew G Knepley 852c7543cceSMatthew G Knepley Level: advanced 853c7543cceSMatthew G Knepley 854f6dfbefdSBarry Smith .seealso: `SNESMULTBLOCK`, `SNESMultiblockSetIS()`, `SNESMultiblockSetFields()` 855c7543cceSMatthew G Knepley @*/ 856d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMultiblockGetSubSNES(SNES snes, PetscInt *n, SNES *subsnes[]) 857d71ae5a4SJacob Faibussowitsch { 858c7543cceSMatthew G Knepley PetscFunctionBegin; 859c7543cceSMatthew G Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 860c7543cceSMatthew G Knepley if (n) PetscValidIntPointer(n, 2); 861cac4c232SBarry Smith PetscUseMethod(snes, "SNESMultiblockGetSubSNES_C", (SNES, PetscInt *, SNES **), (snes, n, subsnes)); 862c7543cceSMatthew G Knepley PetscFunctionReturn(0); 863c7543cceSMatthew G Knepley } 864c7543cceSMatthew G Knepley 865c7543cceSMatthew G Knepley /*MC 866c7543cceSMatthew G Knepley SNESMULTIBLOCK - Multiblock nonlinear solver that can use overlapping or nonoverlapping blocks, organized 867c7543cceSMatthew G Knepley additively (Jacobi) or multiplicatively (Gauss-Seidel). 868c7543cceSMatthew G Knepley 869c7543cceSMatthew G Knepley Level: beginner 870c7543cceSMatthew G Knepley 871f6dfbefdSBarry Smith .seealso: `SNESCreate()`, `SNES`, `SNESSetType()`, `SNESNEWTONLS`, `SNESNEWTONTR`, `SNESNRICHARDSON`, `SNESMultiblockSetType()`, 872f6dfbefdSBarry Smith `PC_COMPOSITE_ADDITIVE`, `PC_COMPOSITE_MULTIPLICATIVE`, `PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE` 873c7543cceSMatthew G Knepley M*/ 874d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode SNESCreate_Multiblock(SNES snes) 875d71ae5a4SJacob Faibussowitsch { 876c7543cceSMatthew G Knepley SNES_Multiblock *mb; 877c7543cceSMatthew G Knepley 878c7543cceSMatthew G Knepley PetscFunctionBegin; 879c7543cceSMatthew G Knepley snes->ops->destroy = SNESDestroy_Multiblock; 880c7543cceSMatthew G Knepley snes->ops->setup = SNESSetUp_Multiblock; 881c7543cceSMatthew G Knepley snes->ops->setfromoptions = SNESSetFromOptions_Multiblock; 882c7543cceSMatthew G Knepley snes->ops->view = SNESView_Multiblock; 883c7543cceSMatthew G Knepley snes->ops->solve = SNESSolve_Multiblock; 884c7543cceSMatthew G Knepley snes->ops->reset = SNESReset_Multiblock; 885c7543cceSMatthew G Knepley 8862c155ee1SBarry Smith snes->usesksp = PETSC_FALSE; 887d8d34be6SBarry Smith snes->usesnpc = PETSC_FALSE; 8882c155ee1SBarry Smith 8894fc747eaSLawrence Mitchell snes->alwayscomputesfinalresidual = PETSC_TRUE; 8904fc747eaSLawrence Mitchell 8914dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&mb)); 892c7543cceSMatthew G Knepley snes->data = (void *)mb; 893c7543cceSMatthew G Knepley mb->defined = PETSC_FALSE; 894c7543cceSMatthew G Knepley mb->numBlocks = 0; 895c7543cceSMatthew G Knepley mb->bs = -1; 896c7543cceSMatthew G Knepley mb->type = PC_COMPOSITE_MULTIPLICATIVE; 897c7543cceSMatthew G Knepley 898c7543cceSMatthew G Knepley /* We attach functions so that they can be called on another PC without crashing the program */ 8999566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESMultiblockSetFields_C", SNESMultiblockSetFields_Default)); 9009566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESMultiblockSetIS_C", SNESMultiblockSetIS_Default)); 9019566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESMultiblockSetType_C", SNESMultiblockSetType_Default)); 9029566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESMultiblockSetBlockSize_C", SNESMultiblockSetBlockSize_Default)); 9039566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESMultiblockGetSubSNES_C", SNESMultiblockGetSubSNES_Default)); 904c7543cceSMatthew G Knepley PetscFunctionReturn(0); 905c7543cceSMatthew G Knepley } 906