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