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