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