/* Creates the default smoother type. This is SNESNRICHARDSON on each fine level and SNESNEWTONLS on the coarse level. */ PetscErrorCode SNESFASCycleCreateSmoother_Private(SNES snes, SNES *smooth) { SNES_FAS *fas; const char *optionsprefix; char tprefix[128]; PetscErrorCode ierr; SNES nsmooth; PetscFunctionBegin; PetscValidHeaderSpecific(snes,SNES_CLASSID,1); fas = (SNES_FAS*)snes->data; ierr = SNESGetOptionsPrefix(fas->fine, &optionsprefix);CHKERRQ(ierr); /* create the default smoother */ ierr = SNESCreate(PetscObjectComm((PetscObject)snes), &nsmooth);CHKERRQ(ierr); if (fas->level == 0) { sprintf(tprefix,"fas_coarse_"); ierr = SNESAppendOptionsPrefix(nsmooth, optionsprefix);CHKERRQ(ierr); ierr = SNESAppendOptionsPrefix(nsmooth, tprefix);CHKERRQ(ierr); ierr = SNESSetType(nsmooth, SNESNEWTONLS);CHKERRQ(ierr); ierr = SNESSetTolerances(nsmooth, nsmooth->abstol, nsmooth->rtol, nsmooth->stol, nsmooth->max_its, nsmooth->max_funcs);CHKERRQ(ierr); } else { sprintf(tprefix,"fas_levels_%d_",(int)fas->level); ierr = SNESAppendOptionsPrefix(nsmooth, optionsprefix);CHKERRQ(ierr); ierr = SNESAppendOptionsPrefix(nsmooth, tprefix);CHKERRQ(ierr); ierr = SNESSetType(nsmooth, SNESNRICHARDSON);CHKERRQ(ierr); ierr = SNESSetTolerances(nsmooth, 0.0, 0.0, 0.0, fas->max_down_it, nsmooth->max_funcs);CHKERRQ(ierr); } ierr = PetscObjectIncrementTabLevel((PetscObject)nsmooth, (PetscObject)snes, 1);CHKERRQ(ierr); ierr = PetscLogObjectParent((PetscObject)snes,(PetscObject)nsmooth);CHKERRQ(ierr); ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)nsmooth);CHKERRQ(ierr); *smooth = nsmooth; PetscFunctionReturn(0); }
PetscErrorCode SNESVISetVariableBounds_VI(SNES snes,Vec xl,Vec xu) { PetscErrorCode ierr; const PetscScalar *xxl,*xxu; PetscInt i,n, cnt = 0; PetscFunctionBegin; ierr = SNESGetFunction(snes,&snes->vec_func,NULL,NULL);CHKERRQ(ierr); if (!snes->vec_func) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call SNESSetFunction() or SNESSetDM() first"); { PetscInt xlN,xuN,N; ierr = VecGetSize(xl,&xlN);CHKERRQ(ierr); ierr = VecGetSize(xu,&xuN);CHKERRQ(ierr); ierr = VecGetSize(snes->vec_func,&N);CHKERRQ(ierr); if (xlN != N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Incompatible vector lengths lower bound = %D solution vector = %D",xlN,N); if (xuN != N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Incompatible vector lengths: upper bound = %D solution vector = %D",xuN,N); } ierr = SNESSetType(snes,SNESVINEWTONRSLS);CHKERRQ(ierr); ierr = PetscObjectReference((PetscObject)xl);CHKERRQ(ierr); ierr = PetscObjectReference((PetscObject)xu);CHKERRQ(ierr); ierr = VecDestroy(&snes->xl);CHKERRQ(ierr); ierr = VecDestroy(&snes->xu);CHKERRQ(ierr); snes->xl = xl; snes->xu = xu; ierr = VecGetLocalSize(xl,&n);CHKERRQ(ierr); ierr = VecGetArrayRead(xl,&xxl);CHKERRQ(ierr); ierr = VecGetArrayRead(xu,&xxu);CHKERRQ(ierr); for (i=0; i<n; i++) cnt += ((xxl[i] != SNES_VI_NINF) || (xxu[i] != SNES_VI_INF)); ierr = MPI_Allreduce(&cnt,&snes->ntruebounds,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)snes));CHKERRQ(ierr); ierr = VecRestoreArrayRead(xl,&xxl);CHKERRQ(ierr); ierr = VecRestoreArrayRead(xu,&xxu);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@C SNESVISetComputeVariableBounds - Sets a function that is called to compute the variable bounds Input parameter + snes - the SNES context - compute - computes the bounds Level: advanced .seealso: SNESVISetVariableBounds() @*/ PetscErrorCode SNESVISetComputeVariableBounds(SNES snes, PetscErrorCode (*compute)(SNES,Vec,Vec)) { PetscErrorCode ierr,(*f)(SNES,PetscErrorCode (*)(SNES,Vec,Vec)); PetscFunctionBegin; PetscValidHeaderSpecific(snes,SNES_CLASSID,1); ierr = PetscObjectQueryFunction((PetscObject)snes,"SNESVISetComputeVariableBounds_C",&f);CHKERRQ(ierr); if (!f) {ierr = SNESSetType(snes,SNESVINEWTONRSLS);CHKERRQ(ierr);} ierr = PetscUseMethod(snes,"SNESVISetComputeVariableBounds_C",(SNES,PetscErrorCode (*)(SNES,Vec,Vec)),(snes,compute));CHKERRQ(ierr); PetscFunctionReturn(0); }
EXTERN_C_BEGIN #undef __FUNCT__ #define __FUNCT__ "SNESMultiblockSetFields_Default" PetscErrorCode SNESMultiblockSetFields_Default(SNES snes, const char name[], PetscInt n, const PetscInt fields[]) { SNES_Multiblock *mb = (SNES_Multiblock *) snes->data; BlockDesc newblock, next = mb->blocks; char prefix[128]; PetscInt i; PetscErrorCode ierr; PetscFunctionBegin; if (mb->defined) { ierr = PetscInfo1(snes, "Ignoring new block \"%s\" because the blocks have already been defined\n", name);CHKERRQ(ierr); PetscFunctionReturn(0); } for (i = 0; i < n; ++i) { if (fields[i] >= mb->bs) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field %D requested but only %D exist", fields[i], mb->bs); if (fields[i] < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative field %D requested", fields[i]); } ierr = PetscNew(struct _BlockDesc, &newblock);CHKERRQ(ierr); if (name) { ierr = PetscStrallocpy(name, &newblock->name);CHKERRQ(ierr); } else { PetscInt len = floor(log10(mb->numBlocks))+1; ierr = PetscMalloc((len+1)*sizeof(char), &newblock->name);CHKERRQ(ierr); ierr = PetscSNPrintf(newblock->name, len, "%s", mb->numBlocks);CHKERRQ(ierr); } newblock->nfields = n; ierr = PetscMalloc(n*sizeof(PetscInt), &newblock->fields);CHKERRQ(ierr); ierr = PetscMemcpy(newblock->fields, fields, n*sizeof(PetscInt));CHKERRQ(ierr); newblock->next = PETSC_NULL; ierr = SNESCreate(((PetscObject) snes)->comm, &newblock->snes);CHKERRQ(ierr); ierr = PetscObjectIncrementTabLevel((PetscObject) newblock->snes, (PetscObject) snes, 1);CHKERRQ(ierr); ierr = SNESSetType(newblock->snes, SNESNRICHARDSON);CHKERRQ(ierr); ierr = PetscLogObjectParent((PetscObject) snes, (PetscObject) newblock->snes);CHKERRQ(ierr); ierr = PetscSNPrintf(prefix, sizeof(prefix), "%smultiblock_%s_", ((PetscObject) snes)->prefix ? ((PetscObject) snes)->prefix : "", newblock->name);CHKERRQ(ierr); ierr = SNESSetOptionsPrefix(newblock->snes, prefix);CHKERRQ(ierr); if (!next) { mb->blocks = newblock; newblock->previous = PETSC_NULL; } else { while (next->next) { next = next->next; } next->next = newblock; newblock->previous = next; } mb->numBlocks++; PetscFunctionReturn(0); }
/*MC SNESASPIN - Helper SNES type for Additive-Schwarz Preconditioned Inexact Newton Options Database: + -npc_snes_ - options prefix of the nonlinear subdomain solver (must be of type NASM) . -npc_sub_snes_ - options prefix of the subdomain nonlinear solves . -npc_sub_ksp_ - options prefix of the subdomain Krylov solver - -npc_sub_pc_ - options prefix of the subdomain preconditioner Notes: This routine sets up an instance of NETWONLS with nonlinear left preconditioning. It differs from other similar functionality in SNES as it creates a linear shell matrix that corresponds to the product: \sum_{i=0}^{N_b}J_b({X^b_{converged}})^{-1}J(X + \sum_{i=0}^{N_b}(X^b_{converged} - X^b)) which is the ASPIN preconditioned matrix. Similar solvers may be constructed by having matrix-free differencing of nonlinear solves per linear iteration, but this is far more efficient when subdomain sparse-direct preconditioner factorizations are reused on each application of J_b^{-1}. Level: intermediate .seealso: SNESCreate(), SNES, SNESSetType(), SNESNEWTONLS, SNESNASM, SNESGetNPC(), SNESGetNPCSide() M*/ PETSC_EXTERN PetscErrorCode SNESCreate_ASPIN(SNES snes) { PetscErrorCode ierr; SNES npc; KSP ksp; PC pc; Mat aspinmat; MPI_Comm comm; Vec F; PetscInt n; SNESLineSearch linesearch; PetscFunctionBegin; /* set up the solver */ ierr = SNESSetType(snes,SNESNEWTONLS);CHKERRQ(ierr); ierr = SNESSetNPCSide(snes,PC_LEFT);CHKERRQ(ierr); ierr = SNESSetFunctionType(snes,SNES_FUNCTION_PRECONDITIONED);CHKERRQ(ierr); ierr = SNESGetNPC(snes,&npc);CHKERRQ(ierr); ierr = SNESSetType(npc,SNESNASM);CHKERRQ(ierr); ierr = SNESNASMSetType(npc,PC_ASM_BASIC);CHKERRQ(ierr); ierr = SNESNASMSetComputeFinalJacobian(npc,PETSC_TRUE);CHKERRQ(ierr); ierr = SNESGetKSP(snes,&ksp);CHKERRQ(ierr); ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); ierr = PCSetType(pc,PCNONE);CHKERRQ(ierr); ierr = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr); ierr = SNESGetLineSearch(snes,&linesearch);CHKERRQ(ierr); ierr = SNESLineSearchSetType(linesearch,SNESLINESEARCHBT);CHKERRQ(ierr); /* set up the shell matrix */ ierr = SNESGetFunction(snes,&F,NULL,NULL);CHKERRQ(ierr); ierr = VecGetLocalSize(F,&n);CHKERRQ(ierr); ierr = MatCreateShell(comm,n,n,PETSC_DECIDE,PETSC_DECIDE,snes,&aspinmat);CHKERRQ(ierr); ierr = MatSetType(aspinmat,MATSHELL);CHKERRQ(ierr); ierr = MatShellSetOperation(aspinmat,MATOP_MULT,(void(*)(void))MatMultASPIN);CHKERRQ(ierr); ierr = SNESSetJacobian(snes,aspinmat,NULL,NULL,NULL);CHKERRQ(ierr); ierr = MatDestroy(&aspinmat);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@ SNESVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu. Input Parameters: . snes - the SNES context. . xl - lower bound. . xu - upper bound. Notes: If this routine is not called then the lower and upper bounds are set to SNES_VI_INF and SNES_VI_NINF respectively during SNESSetUp(). Level: advanced @*/ PetscErrorCode SNESVISetVariableBounds(SNES snes, Vec xl, Vec xu) { PetscErrorCode ierr,(*f)(SNES,Vec,Vec); PetscFunctionBegin; PetscValidHeaderSpecific(snes,SNES_CLASSID,1); PetscValidHeaderSpecific(xl,VEC_CLASSID,2); PetscValidHeaderSpecific(xu,VEC_CLASSID,3); ierr = PetscObjectQueryFunction((PetscObject)snes,"SNESVISetVariableBounds_C",&f);CHKERRQ(ierr); if (!f) {ierr = SNESSetType(snes,SNESVINEWTONRSLS);CHKERRQ(ierr);} ierr = PetscUseMethod(snes,"SNESVISetVariableBounds_C",(SNES,Vec,Vec),(snes,xl,xu));CHKERRQ(ierr); snes->usersetbounds = PETSC_TRUE; PetscFunctionReturn(0); }
void Solve_Distance(UserCtx *user, int iter) { SNES snes_distance; KSP ksp; PC pc; Vec r; Mat J; double norm; int bi=0; VecDuplicate(LevelSet, &r); SNESCreate(PETSC_COMM_WORLD,&snes_distance); SNESSetFunction(snes_distance,r,FormFunction_Distance,(void *)&user[bi]); MatCreateSNESMF(snes_distance, &J); SNESSetJacobian(snes_distance,J,J,MatMFFDComputeJacobian,(void *)&user[bi]); SNESSetType(snes_distance, SNESTR); //SNESTR,SNESLS double tol=1.e-2; SNESSetMaxLinearSolveFailures(snes_distance,10000); SNESSetMaxNonlinearStepFailures(snes_distance,10000); SNESKSPSetUseEW(snes_distance, PETSC_TRUE); SNESKSPSetParametersEW(snes_distance,3,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT); SNESSetTolerances(snes_distance,PETSC_DEFAULT,tol,PETSC_DEFAULT,5,50000); // snes iter SNESGetKSP(snes_distance, &ksp); KSPSetType(ksp, KSPGMRES); //KSPGMRESSetPreAllocateVectors(ksp); KSPGetPC(ksp,&pc); PCSetType(pc,PCNONE); //int maxits=10; int maxits=4; // ksp iter double rtol=tol, atol=PETSC_DEFAULT, dtol=PETSC_DEFAULT; KSPSetTolerances(ksp,rtol,atol,dtol,maxits); extern PetscErrorCode MySNESMonitor(SNES snes,PetscInt n,PetscReal rnorm,void *dummy); SNESMonitorSet(snes_distance,MySNESMonitor,PETSC_NULL,PETSC_NULL); SNESSolve(snes_distance, PETSC_NULL, LevelSet); SNESGetFunctionNorm(snes_distance, &norm); //PetscPrintf(PETSC_COMM_WORLD, "\nDistance SNES residual norm=%.5e\n\n", norm); VecDestroy(r); MatDestroy(J); SNESDestroy(snes_distance); };
EXTERN_C_END EXTERN_C_BEGIN #undef __FUNCT__ #define __FUNCT__ "SNESMultiblockSetIS_Default" PetscErrorCode SNESMultiblockSetIS_Default(SNES snes, const char name[], IS is) { SNES_Multiblock *mb = (SNES_Multiblock *) snes->data; BlockDesc newblock, next = mb->blocks; char prefix[128]; PetscErrorCode ierr; PetscFunctionBegin; if (mb->defined) { ierr = PetscInfo1(snes, "Ignoring new block \"%s\" because the blocks have already been defined\n", name);CHKERRQ(ierr); PetscFunctionReturn(0); } ierr = PetscNew(struct _BlockDesc, &newblock);CHKERRQ(ierr); if (name) { ierr = PetscStrallocpy(name, &newblock->name);CHKERRQ(ierr); } else { PetscInt len = floor(log10(mb->numBlocks))+1; ierr = PetscMalloc((len+1)*sizeof(char), &newblock->name);CHKERRQ(ierr); ierr = PetscSNPrintf(newblock->name, len, "%s", mb->numBlocks);CHKERRQ(ierr); } newblock->is = is; ierr = PetscObjectReference((PetscObject) is);CHKERRQ(ierr); newblock->next = PETSC_NULL; ierr = SNESCreate(((PetscObject) snes)->comm, &newblock->snes);CHKERRQ(ierr); ierr = PetscObjectIncrementTabLevel((PetscObject) newblock->snes, (PetscObject) snes, 1);CHKERRQ(ierr); ierr = SNESSetType(newblock->snes, SNESNRICHARDSON);CHKERRQ(ierr); ierr = PetscLogObjectParent((PetscObject) snes, (PetscObject) newblock->snes);CHKERRQ(ierr); ierr = PetscSNPrintf(prefix, sizeof(prefix), "%smultiblock_%s_", ((PetscObject) snes)->prefix ? ((PetscObject) snes)->prefix : "", newblock->name);CHKERRQ(ierr); ierr = SNESSetOptionsPrefix(newblock->snes, prefix);CHKERRQ(ierr); if (!next) { mb->blocks = newblock; newblock->previous = PETSC_NULL; } else { while (next->next) { next = next->next; } next->next = newblock; newblock->previous = next; } mb->numBlocks++; PetscFunctionReturn(0); }
/*@C SNESFASSetLevels - Sets the number of levels to use with FAS. Must be called before any other FAS routine. Input Parameters: + snes - the snes context . levels - the number of levels - comms - optional communicators for each level; this is to allow solving the coarser problems on smaller sets of processors. Use NULL_OBJECT for default in Fortran. Level: intermediate Notes: If the number of levels is one then the multigrid uses the -fas_levels prefix for setting the level options rather than the -fas_coarse prefix. .keywords: FAS, MG, set, levels, multigrid .seealso: SNESFASGetLevels() @*/ PetscErrorCode SNESFASSetLevels(SNES snes, PetscInt levels, MPI_Comm * comms) { PetscErrorCode ierr; PetscInt i; const char *optionsprefix; char tprefix[128]; SNES_FAS *fas = (SNES_FAS*)snes->data; SNES prevsnes; MPI_Comm comm; PetscFunctionBegin; ierr = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr); if (levels == fas->levels) { if (!comms) PetscFunctionReturn(0); } /* user has changed the number of levels; reset */ ierr = SNESReset(snes);CHKERRQ(ierr); /* destroy any coarser levels if necessary */ if (fas->next) SNESDestroy(&fas->next);CHKERRQ(ierr); fas->next = NULL; fas->previous = NULL; prevsnes = snes; /* setup the finest level */ ierr = SNESGetOptionsPrefix(snes, &optionsprefix);CHKERRQ(ierr); for (i = levels - 1; i >= 0; i--) { if (comms) comm = comms[i]; fas->level = i; fas->levels = levels; fas->fine = snes; fas->next = NULL; if (i > 0) { ierr = SNESCreate(comm, &fas->next);CHKERRQ(ierr); ierr = SNESGetOptionsPrefix(fas->fine, &optionsprefix);CHKERRQ(ierr); sprintf(tprefix,"fas_levels_%d_cycle_",(int)fas->level); ierr = SNESAppendOptionsPrefix(fas->next,optionsprefix);CHKERRQ(ierr); ierr = SNESAppendOptionsPrefix(fas->next,tprefix);CHKERRQ(ierr); ierr = SNESSetType(fas->next, SNESFAS);CHKERRQ(ierr); ierr = SNESSetTolerances(fas->next, fas->next->abstol, fas->next->rtol, fas->next->stol, fas->n_cycles, fas->next->max_funcs);CHKERRQ(ierr); ierr = PetscObjectIncrementTabLevel((PetscObject)fas->next, (PetscObject)snes, levels - i);CHKERRQ(ierr); ((SNES_FAS*)fas->next->data)->previous = prevsnes; prevsnes = fas->next; fas = (SNES_FAS*)prevsnes->data; } } PetscFunctionReturn(0); }
static PetscErrorCode SNESCompositeAddSNES_Composite(SNES snes,SNESType type) { SNES_Composite *jac; SNES_CompositeLink next,ilink; PetscErrorCode ierr; PetscInt cnt = 0; const char *prefix; char newprefix[20]; DM dm; PetscFunctionBegin; ierr = PetscNewLog(snes,&ilink);CHKERRQ(ierr); ilink->next = 0; ierr = SNESCreate(PetscObjectComm((PetscObject)snes),&ilink->snes);CHKERRQ(ierr); ierr = PetscLogObjectParent((PetscObject)snes,(PetscObject)ilink->snes);CHKERRQ(ierr); ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); ierr = SNESSetDM(ilink->snes,dm);CHKERRQ(ierr); ierr = SNESSetTolerances(ilink->snes,ilink->snes->abstol,ilink->snes->rtol,ilink->snes->stol,1,ilink->snes->max_funcs);CHKERRQ(ierr); ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)snes,(PetscObject)ilink->snes);CHKERRQ(ierr); jac = (SNES_Composite*)snes->data; next = jac->head; if (!next) { jac->head = ilink; ilink->previous = NULL; } else { cnt++; while (next->next) { next = next->next; cnt++; } next->next = ilink; ilink->previous = next; } ierr = SNESGetOptionsPrefix(snes,&prefix);CHKERRQ(ierr); ierr = SNESSetOptionsPrefix(ilink->snes,prefix);CHKERRQ(ierr); sprintf(newprefix,"sub_%d_",(int)cnt); ierr = SNESAppendOptionsPrefix(ilink->snes,newprefix);CHKERRQ(ierr); ierr = PetscObjectIncrementTabLevel((PetscObject)ilink->snes,(PetscObject)snes,1);CHKERRQ(ierr); ierr = SNESSetType(ilink->snes,type);CHKERRQ(ierr); ierr = SNESSetNormSchedule(ilink->snes, SNES_NORM_FINAL_ONLY);CHKERRQ(ierr); ilink->dmp = 1.0; jac->nsnes++; PetscFunctionReturn(0); }
/*@ SNESFASSetContinuation - Sets the FAS cycle to default to exact Newton solves on the upsweep Logically Collective on SNES Input Parameters: + snes - the multigrid context - n - the number of smoothing steps Options Database Key: . -snes_fas_continuation - sets continuation to true Level: advanced Notes: This sets the prefix on the upsweep smoothers to -fas_continuation .keywords: FAS, MG, smoother, continuation .seealso: SNESFAS @*/ PetscErrorCode SNESFASSetContinuation(SNES snes,PetscBool continuation) { const char *optionsprefix; char tprefix[128]; SNES_FAS *fas = (SNES_FAS*)snes->data; PetscErrorCode ierr = 0; PetscFunctionBegin; ierr = SNESGetOptionsPrefix(fas->fine, &optionsprefix);CHKERRQ(ierr); if (!fas->smoothu) { ierr = SNESFASCycleCreateSmoother_Private(snes, &fas->smoothu);CHKERRQ(ierr); } sprintf(tprefix,"fas_levels_continuation_"); ierr = SNESSetOptionsPrefix(fas->smoothu, optionsprefix);CHKERRQ(ierr); ierr = SNESAppendOptionsPrefix(fas->smoothu, tprefix);CHKERRQ(ierr); ierr = SNESSetType(fas->smoothu,SNESNEWTONLS);CHKERRQ(ierr); ierr = SNESSetTolerances(fas->smoothu,fas->fine->abstol,fas->fine->rtol,fas->fine->stol,50,100);CHKERRQ(ierr); fas->continuation = continuation; if (fas->next) { ierr = SNESFASSetContinuation(fas->next,continuation);CHKERRQ(ierr); } PetscFunctionReturn(0); }
PETSC_EXTERN PetscErrorCode TSCreate_Pseudo(TS ts) { TS_Pseudo *pseudo; PetscErrorCode ierr; SNES snes; SNESType stype; PetscFunctionBegin; ts->ops->reset = TSReset_Pseudo; ts->ops->destroy = TSDestroy_Pseudo; ts->ops->view = TSView_Pseudo; ts->ops->setup = TSSetUp_Pseudo; ts->ops->step = TSStep_Pseudo; ts->ops->setfromoptions = TSSetFromOptions_Pseudo; ts->ops->snesfunction = SNESTSFormFunction_Pseudo; ts->ops->snesjacobian = SNESTSFormJacobian_Pseudo; ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr); ierr = SNESGetType(snes,&stype);CHKERRQ(ierr); if (!stype) {ierr = SNESSetType(snes,SNESKSPONLY);CHKERRQ(ierr);} ierr = PetscNewLog(ts,&pseudo);CHKERRQ(ierr); ts->data = (void*)pseudo; pseudo->dt_increment = 1.1; pseudo->increment_dt_from_initial_dt = PETSC_FALSE; pseudo->dt = TSPseudoTimeStepDefault; pseudo->fnorm = -1; ierr = PetscObjectComposeFunction((PetscObject)ts,"TSPseudoSetVerifyTimeStep_C",TSPseudoSetVerifyTimeStep_Pseudo);CHKERRQ(ierr); ierr = PetscObjectComposeFunction((PetscObject)ts,"TSPseudoSetTimeStepIncrement_C",TSPseudoSetTimeStepIncrement_Pseudo);CHKERRQ(ierr); ierr = PetscObjectComposeFunction((PetscObject)ts,"TSPseudoSetMaxTimeStep_C",TSPseudoSetMaxTimeStep_Pseudo);CHKERRQ(ierr); ierr = PetscObjectComposeFunction((PetscObject)ts,"TSPseudoIncrementDtFromInitialDt_C",TSPseudoIncrementDtFromInitialDt_Pseudo);CHKERRQ(ierr); ierr = PetscObjectComposeFunction((PetscObject)ts,"TSPseudoSetTimeStep_C",TSPseudoSetTimeStep_Pseudo);CHKERRQ(ierr); PetscFunctionReturn(0); }
int main(int argc,char **argv) { PetscErrorCode ierr; SNES snes; Vec u, r; /* solution, residual vector */ PetscInt Mx,My,its; SNESConvergedReason reason; DM da; ObsCtx user; PetscReal dx,dy,error1,errorinf; PetscBool feasible = PETSC_FALSE,fdflg = PETSC_FALSE; PetscInitialize(&argc,&argv,(char *)0,help); ierr = DMDACreate2d(PETSC_COMM_WORLD, DMDA_BOUNDARY_NONE, DMDA_BOUNDARY_NONE, DMDA_STENCIL_STAR, /* nonlinear diffusion but diffusivity depends on soln W not grad W */ -11,-11, /* default to 10x10 grid but override with -da_grid_x, -da_grid_y (or -da_refine) */ PETSC_DECIDE,PETSC_DECIDE, /* num of procs in each dim */ 1, /* dof = 1 */ 1, /* s = 1 (stencil extends out one cell) */ PETSC_NULL,PETSC_NULL, /* no specify proc decomposition */ &da);CHKERRQ(ierr); ierr = DMCreateGlobalVector(da,&u);CHKERRQ(ierr); ierr = VecDuplicate(u,&r);CHKERRQ(ierr); ierr = VecDuplicate(u,&(user.uexact));CHKERRQ(ierr); ierr = VecDuplicate(u,&(user.psi));CHKERRQ(ierr); ierr = PetscOptionsBegin(PETSC_COMM_WORLD,"","options to obstacle problem","");CHKERRQ(ierr); ierr = PetscOptionsBool("-fd","use coloring to compute Jacobian by finite differences",PETSC_NULL,fdflg,&fdflg,PETSC_NULL);CHKERRQ(ierr); ierr = PetscOptionsBool("-feasible","use feasible initial guess",PETSC_NULL,feasible,&feasible,PETSC_NULL);CHKERRQ(ierr); ierr = PetscOptionsEnd();CHKERRQ(ierr); ierr = DMDASetUniformCoordinates(da,-2.0,2.0,-2.0,2.0,0.0,1.0);CHKERRQ(ierr); ierr = DMSetApplicationContext(da,&user);CHKERRQ(ierr); ierr = FormPsiAndInitialGuess(da,u,feasible);CHKERRQ(ierr); ierr = SNESCreate(PETSC_COMM_WORLD,&snes);CHKERRQ(ierr); ierr = SNESSetDM(snes,da);CHKERRQ(ierr); ierr = SNESSetApplicationContext(snes,&user);CHKERRQ(ierr); ierr = SNESSetType(snes,SNESVINEWTONRSLS);CHKERRQ(ierr); ierr = SNESVISetComputeVariableBounds(snes,&FormBounds);CHKERRQ(ierr); ierr = DMDASNESSetFunctionLocal(da,INSERT_VALUES,(PetscErrorCode (*)(DMDALocalInfo*,void*,void*,void*))FormFunctionLocal,&user);CHKERRQ(ierr); if (!fdflg) { ierr = DMDASNESSetJacobianLocal(da,(PetscErrorCode (*)(DMDALocalInfo*,void*,Mat,Mat,MatStructure*,void*))FormJacobianLocal,&user);CHKERRQ(ierr); } ierr = SNESSetFromOptions(snes);CHKERRQ(ierr); /* report on setup */ ierr = DMDAGetInfo(da,PETSC_IGNORE,&Mx,&My, PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE, PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE, PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE);CHKERRQ(ierr); dx = 4.0 / (PetscReal)(Mx-1); dy = 4.0 / (PetscReal)(My-1); ierr = PetscPrintf(PETSC_COMM_WORLD, "setup done: square side length = %.3f\n" " grid Mx,My = %D,%D\n" " spacing dx,dy = %.3f,%.3f\n", 4.0, Mx, My, (double)dx, (double)dy);CHKERRQ(ierr); /* solve nonlinear system */ ierr = SNESSolve(snes,PETSC_NULL,u);CHKERRQ(ierr); ierr = SNESGetIterationNumber(snes,&its);CHKERRQ(ierr); ierr = SNESGetConvergedReason(snes,&reason);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"number of Newton iterations = %D; result = %s\n", its,SNESConvergedReasons[reason]);CHKERRQ(ierr); /* compare to exact */ ierr = VecWAXPY(r,-1.0,user.uexact,u);CHKERRQ(ierr); /* r = W - Wexact */ ierr = VecNorm(r,NORM_1,&error1);CHKERRQ(ierr); error1 /= (PetscReal)Mx * (PetscReal)My; ierr = VecNorm(r,NORM_INFINITY,&errorinf);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"errors: av |u-uexact| = %.3e\n |u-uexact|_inf = %.3e\n",error1,errorinf);CHKERRQ(ierr); /* Free work space. */ ierr = VecDestroy(&u);CHKERRQ(ierr); ierr = VecDestroy(&r);CHKERRQ(ierr); ierr = VecDestroy(&(user.psi));CHKERRQ(ierr); ierr = VecDestroy(&(user.uexact));CHKERRQ(ierr); ierr = SNESDestroy(&snes);CHKERRQ(ierr); ierr = DMDestroy(&da);CHKERRQ(ierr); ierr = PetscFinalize();CHKERRQ(ierr); return 0; }
int main(int argc,char **argv) { PetscErrorCode ierr; SNES snes; Vec u, r; /* solution, residual vector */ PetscInt its; SNESConvergedReason reason; DM da; ObsCtx user; PetscReal error1,errorinf; PetscBool feasible = PETSC_FALSE,fdflg = PETSC_FALSE; DMDALocalInfo info; PetscInitialize(&argc,&argv,NULL,help); //CREATE ierr = DMDACreate2d(PETSC_COMM_WORLD, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DMDA_STENCIL_STAR, 11,11, // override with -da_grid_x,_y or -da_refine PETSC_DECIDE,PETSC_DECIDE, // num of procs in each dim 1,1,NULL,NULL, // dof = 1 and stencil width = 1 &da);CHKERRQ(ierr); ierr = DMSetFromOptions(da); CHKERRQ(ierr); ierr = DMSetUp(da); CHKERRQ(ierr); ierr = DMDASetUniformCoordinates(da,-2.0,2.0,-2.0,2.0,-1.0,-1.0);CHKERRQ(ierr); ierr = DMSetApplicationContext(da,&user);CHKERRQ(ierr); ierr = DMDAGetLocalInfo(da,&info); CHKERRQ(ierr); user.dx = 4.0 / (PetscReal)(info.mx-1); user.dy = 4.0 / (PetscReal)(info.my-1); ierr = DMCreateGlobalVector(da,&u);CHKERRQ(ierr); ierr = VecDuplicate(u,&r);CHKERRQ(ierr); ierr = VecDuplicate(u,&(user.g));CHKERRQ(ierr); ierr = VecDuplicate(u,&(user.psi));CHKERRQ(ierr); ierr = PetscOptionsBegin(PETSC_COMM_WORLD,"","options to obstacle problem","");CHKERRQ(ierr); ierr = PetscOptionsBool("-fd","use coloring to compute Jacobian by finite differences", NULL,fdflg,&fdflg,NULL);CHKERRQ(ierr); ierr = PetscOptionsBool("-feasible","use feasible initial guess", NULL,feasible,&feasible,NULL);CHKERRQ(ierr); ierr = PetscOptionsEnd();CHKERRQ(ierr); //ENDCREATE //SETUPSNES ierr = FormPsiAndInitialGuess(da,u,feasible,&user);CHKERRQ(ierr); ierr = SNESCreate(PETSC_COMM_WORLD,&snes);CHKERRQ(ierr); ierr = SNESSetDM(snes,da);CHKERRQ(ierr); ierr = SNESSetApplicationContext(snes,&user);CHKERRQ(ierr); ierr = SNESSetType(snes,SNESVINEWTONRSLS);CHKERRQ(ierr); ierr = SNESVISetComputeVariableBounds(snes,&FormBounds);CHKERRQ(ierr); ierr = DMDASNESSetFunctionLocal(da,INSERT_VALUES, (PetscErrorCode (*)(DMDALocalInfo*,void*,void*,void*))FormFunctionLocal, &user);CHKERRQ(ierr); if (!fdflg) { ierr = DMDASNESSetJacobianLocal(da, (PetscErrorCode (*)(DMDALocalInfo*,void*,Mat,Mat,void*))FormJacobianLocal, &user);CHKERRQ(ierr); } ierr = SNESSetFromOptions(snes);CHKERRQ(ierr); //ENDSETUPSNES /* report on setup */ ierr = PetscPrintf(PETSC_COMM_WORLD, "setup done: square side length = %.3f\n" " grid Mx,My = %D,%D\n" " spacing dx,dy = %.3f,%.3f\n", 4.0, info.mx, info.my, user.dx, user.dy);CHKERRQ(ierr); //SOLVE /* solve nonlinear system */ ierr = SNESSolve(snes,NULL,u);CHKERRQ(ierr); ierr = SNESGetIterationNumber(snes,&its);CHKERRQ(ierr); ierr = SNESGetConvergedReason(snes,&reason);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"number of Newton iterations = %D; result = %s\n", its,SNESConvergedReasons[reason]);CHKERRQ(ierr); /* compare to exact */ ierr = VecWAXPY(r,-1.0,user.g,u);CHKERRQ(ierr); /* r = u - g = u - uexact */ ierr = VecNorm(r,NORM_1,&error1);CHKERRQ(ierr); error1 /= (PetscReal)info.mx * (PetscReal)info.my; ierr = VecNorm(r,NORM_INFINITY,&errorinf);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD, "errors: av |u-uexact| = %.3e\n" " |u-uexact|_inf = %.3e\n", (double)error1,(double)errorinf);CHKERRQ(ierr); //ENDSOLVE /* Free work space. */ ierr = VecDestroy(&u);CHKERRQ(ierr); ierr = VecDestroy(&r);CHKERRQ(ierr); ierr = VecDestroy(&(user.psi));CHKERRQ(ierr); ierr = VecDestroy(&(user.g));CHKERRQ(ierr); ierr = SNESDestroy(&snes);CHKERRQ(ierr); ierr = DMDestroy(&da);CHKERRQ(ierr); ierr = PetscFinalize();CHKERRQ(ierr); return 0; }
static PetscErrorCode TSStep_EIMEX(TS ts) { TS_EIMEX *ext = (TS_EIMEX*)ts->data; const PetscInt ns = ext->nstages; Vec *T=ext->T, Y=ext->Y; SNES snes; PetscInt i,j; PetscBool accept = PETSC_FALSE; PetscErrorCode ierr; PetscReal alpha,local_error; PetscFunctionBegin; ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr); ierr = SNESSetType(snes,"ksponly"); CHKERRQ(ierr); ext->status = TS_STEP_INCOMPLETE; ierr = VecCopy(ts->vec_sol,ext->VecSolPrev);CHKERRQ(ierr); /* Apply n_j steps of the base method to obtain solutions of T(j,1),1<=j<=s */ for(j=0; j<ns; j++){ ierr = TSStage_EIMEX(ts,j);CHKERRQ(ierr); ierr = VecCopy(Y,T[j]); CHKERRQ(ierr); } for(i=1;i<ns;i++){ for(j=i;j<ns;j++){ alpha = -(PetscReal)ext->N[j]/ext->N[j-i]; ierr = VecAXPBYPCZ(T[Map(j,i,ns)],alpha,1.0,0,T[Map(j,i-1,ns)],T[Map(j-1,i-1,ns)]);/* T[j][i]=alpha*T[j][i-1]+T[j-1][i-1] */CHKERRQ(ierr); alpha = 1.0/(1.0 + alpha); ierr = VecScale(T[Map(j,i,ns)],alpha);CHKERRQ(ierr); } } ierr = TSEvaluateStep(ts,ns,ts->vec_sol,NULL);CHKERRQ(ierr);/*update ts solution */ if(ext->ord_adapt && ext->nstages < ext->max_rows){ accept = PETSC_FALSE; while(!accept && ext->nstages < ext->max_rows){ ierr = TSErrorWeightedNorm(ts,ts->vec_sol,T[Map(ext->nstages-1,ext->nstages-2,ext->nstages)],ts->adapt->wnormtype,&local_error);CHKERRQ(ierr); accept = (local_error < 1.0)? PETSC_TRUE : PETSC_FALSE; if(!accept){/* add one more stage*/ ierr = TSStage_EIMEX(ts,ext->nstages);CHKERRQ(ierr); ext->nstages++; ext->row_ind++; ext->col_ind++; /*T table need to be recycled*/ ierr = VecDuplicateVecs(ts->vec_sol,(1+ext->nstages)*ext->nstages/2,&ext->T);CHKERRQ(ierr); for(i=0; i<ext->nstages-1; i++){ for(j=0; j<=i; j++){ ierr = VecCopy(T[Map(i,j,ext->nstages-1)],ext->T[Map(i,j,ext->nstages)]);CHKERRQ(ierr); } } ierr = VecDestroyVecs(ext->nstages*(ext->nstages-1)/2,&T);CHKERRQ(ierr); T = ext->T; /*reset the pointer*/ /*recycling finished, store the new solution*/ ierr = VecCopy(Y,T[ext->nstages-1]); CHKERRQ(ierr); /*extrapolation for the newly added stage*/ for(i=1;i<ext->nstages;i++){ alpha = -(PetscReal)ext->N[ext->nstages-1]/ext->N[ext->nstages-1-i]; ierr = VecAXPBYPCZ(T[Map(ext->nstages-1,i,ext->nstages)],alpha,1.0,0,T[Map(ext->nstages-1,i-1,ext->nstages)],T[Map(ext->nstages-1-1,i-1,ext->nstages)]);/*T[ext->nstages-1][i]=alpha*T[ext->nstages-1][i-1]+T[ext->nstages-1-1][i-1]*/CHKERRQ(ierr); alpha = 1.0/(1.0 + alpha); ierr = VecScale(T[Map(ext->nstages-1,i,ext->nstages)],alpha);CHKERRQ(ierr); } /*update ts solution */ ierr = TSEvaluateStep(ts,ext->nstages,ts->vec_sol,NULL);CHKERRQ(ierr); }/*end if !accept*/ }/*end while*/ if(ext->nstages == ext->max_rows){ ierr = PetscInfo(ts,"Max number of rows has been used\n");CHKERRQ(ierr); } }/*end if ext->ord_adapt*/ ts->ptime += ts->time_step; ext->status = TS_STEP_COMPLETE; if (ext->status != TS_STEP_COMPLETE && !ts->reason) ts->reason = TS_DIVERGED_STEP_REJECTED; PetscFunctionReturn(0); }
int main(int argc,char **argv) { PetscErrorCode ierr; ObsCtx user; SNES snes; DM da; Vec u; /* solution */ DMDALocalInfo info; PetscReal error1,errorinf; PetscInitialize(&argc,&argv,(char*)0,help); ierr = DMDACreate2d(PETSC_COMM_WORLD, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DMDA_STENCIL_STAR, -11,-11, /* default to 10x10 grid */ PETSC_DECIDE,PETSC_DECIDE, /* number of processors in each dimension */ 1, /* dof = 1 */ 1, /* s = 1; stencil extends out one cell */ NULL,NULL, /* do not specify processor decomposition */ &da);CHKERRQ(ierr); ierr = DMCreateGlobalVector(da,&u);CHKERRQ(ierr); ierr = VecDuplicate(u,&(user.uexact));CHKERRQ(ierr); ierr = VecDuplicate(u,&(user.psi));CHKERRQ(ierr); ierr = DMDASetUniformCoordinates(da,-2.0,2.0,-2.0,2.0,0.0,1.0);CHKERRQ(ierr); ierr = DMSetApplicationContext(da,&user);CHKERRQ(ierr); ierr = FormPsiAndExactSoln(da);CHKERRQ(ierr); ierr = VecSet(u,0.0);CHKERRQ(ierr); ierr = SNESCreate(PETSC_COMM_WORLD,&snes);CHKERRQ(ierr); ierr = SNESSetDM(snes,da);CHKERRQ(ierr); ierr = SNESSetApplicationContext(snes,&user);CHKERRQ(ierr); ierr = SNESSetType(snes,SNESVINEWTONRSLS);CHKERRQ(ierr); ierr = SNESVISetComputeVariableBounds(snes,&FormBounds);CHKERRQ(ierr); ierr = DMDASNESSetFunctionLocal(da,INSERT_VALUES,(PetscErrorCode (*)(DMDALocalInfo*,void*,void*,void*))FormFunctionLocal,&user);CHKERRQ(ierr); ierr = DMDASNESSetJacobianLocal(da,(PetscErrorCode (*)(DMDALocalInfo*,void*,Mat,Mat,void*))FormJacobianLocal,&user);CHKERRQ(ierr); ierr = SNESSetFromOptions(snes);CHKERRQ(ierr); /* report on setup */ ierr = DMDAGetLocalInfo(da,&info); CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"setup done: grid Mx,My = %D,%D with spacing dx,dy = %.4f,%.4f\n", info.mx,info.my,4.0/(PetscReal)(info.mx-1),4.0/(PetscReal)(info.my-1));CHKERRQ(ierr); /* solve nonlinear system */ ierr = SNESSolve(snes,NULL,u);CHKERRQ(ierr); /* compare to exact */ ierr = VecAXPY(u,-1.0,user.uexact);CHKERRQ(ierr); /* u <- u - uexact */ ierr = VecNorm(u,NORM_1,&error1);CHKERRQ(ierr); error1 /= (PetscReal)info.mx * (PetscReal)info.my; ierr = VecNorm(u,NORM_INFINITY,&errorinf);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"errors: av |u-uexact| = %.3e |u-uexact|_inf = %.3e\n",error1,errorinf);CHKERRQ(ierr); /* Free work space. */ ierr = VecDestroy(&u);CHKERRQ(ierr); ierr = VecDestroy(&(user.psi));CHKERRQ(ierr); ierr = VecDestroy(&(user.uexact));CHKERRQ(ierr); ierr = SNESDestroy(&snes);CHKERRQ(ierr); ierr = DMDestroy(&da);CHKERRQ(ierr); ierr = PetscFinalize();CHKERRQ(ierr); return 0; }
void VentilationProblem::SolveFromPressureWithSnes() { assert( !mFluxGivenAtInflow ); // It's not a direct solve if (mTerminalInteractionMatrix == NULL) { SetupIterativeSolver(); } SNES snes; SNESCreate(PETSC_COMM_SELF, &snes); // Set the residual creation function (direct solve flux->pressure followed by pressure matching) SNESSetFunction(snes, mTerminalPressureChangeVector /*residual*/ , &ComputeSnesResidual, this); // The approximate Jacobian has been precomputed so we are going to wing it SNESSetJacobian(snes, mTerminalInteractionMatrix, mTerminalInteractionMatrix, /*&ComputeSnesJacobian*/ NULL, this); #if (PETSC_VERSION_MAJOR == 3) //PETSc 3.x SNESSetLagJacobian(snes, -1 /*Never rebuild Jacobian*/); #else SNESSetType(snes, SNESLS); #endif #if (PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR >= 4) //PETSc 3.4 or later SNESSetType(snes, SNESNEWTONLS); #else SNESSetType(snes, SNESLS); #endif // Set the relative tolerance on the residual // Also set the absolute tolerance - useful for when the solver is started from the correct answer SNESSetTolerances(snes, 1.0e-16/*abs_tol*/, 1e-15/*r_tol*/, PETSC_DEFAULT/*step_tol*/, PETSC_DEFAULT, PETSC_DEFAULT); #if (PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR == 3) //PETSc 3.3 SNESLineSearch linesearch; SNESGetSNESLineSearch(snes, &linesearch); SNESLineSearchSetType(linesearch, "bt"); //Use backtracking search as default #elif (PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR >= 4) //PETSc 3.4 or later SNESLineSearch linesearch; SNESGetLineSearch(snes, &linesearch); SNESLineSearchSetType(linesearch, "bt"); //Use backtracking search as default #endif SNESSetFromOptions(snes); #if (PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR >= 5) // Seems to want the preconditioner to be explicitly set to none now // Copied this from the similar PETSc example at: // http://www.mcs.anl.gov/petsc/petsc-current/src/snes/examples/tutorials/ex1.c // Which got it to work... KSP ksp; SNESGetKSP(snes,&ksp); PC pc; KSPGetPC(ksp,&pc); PCSetType(pc,PCNONE); #endif #if (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 2) //PETSc 2.2 SNESSolve(snes, mTerminalFluxChangeVector); #else SNESSolve(snes, PETSC_NULL, mTerminalFluxChangeVector); #endif ///\todo #2300 If used with time-stepping we should maintain a permanent SNES object SNESDestroy(PETSC_DESTROY_PARAM(snes)); }
int main(int argc,char **argv) { PetscErrorCode ierr; DM da, da_after; SNES snes; Vec u_initial, u; PoissonCtx user; SNESConvergedReason reason; int snesits; double lflops,flops; DMDALocalInfo info; PetscInitialize(&argc,&argv,NULL,help); ierr = PetscOptionsBegin(PETSC_COMM_WORLD,"el_", "elasto-plastic torsion solver options",""); CHKERRQ(ierr); ierr = PetscOptionsReal("-C","f(x,y)=2C is source term", "elasto.c",C,&C,NULL); CHKERRQ(ierr); ierr = PetscOptionsEnd(); CHKERRQ(ierr); ierr = DMDACreate2d(PETSC_COMM_WORLD, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DMDA_STENCIL_STAR, 3,3, // override with -da_grid_x,_y PETSC_DECIDE,PETSC_DECIDE, // num of procs in each dim 1,1,NULL,NULL, // dof = 1 and stencil width = 1 &da);CHKERRQ(ierr); ierr = DMSetFromOptions(da); CHKERRQ(ierr); ierr = DMSetUp(da); CHKERRQ(ierr); ierr = DMDASetUniformCoordinates(da,0.0,1.0,0.0,1.0,-1.0,-1.0);CHKERRQ(ierr); user.cx = 1.0; user.cy = 1.0; user.cz = 1.0; user.g_bdry = &zero; user.f_rhs = &f_fcn; user.addctx = NULL; ierr = DMSetApplicationContext(da,&user);CHKERRQ(ierr); ierr = SNESCreate(PETSC_COMM_WORLD,&snes);CHKERRQ(ierr); ierr = SNESSetDM(snes,da);CHKERRQ(ierr); ierr = SNESSetApplicationContext(snes,&user);CHKERRQ(ierr); ierr = SNESSetType(snes,SNESVINEWTONRSLS);CHKERRQ(ierr); ierr = SNESVISetComputeVariableBounds(snes,&FormBounds);CHKERRQ(ierr); // reuse residual and jacobian from ch6/ ierr = DMDASNESSetFunctionLocal(da,INSERT_VALUES, (DMDASNESFunction)Poisson2DFunctionLocal,&user); CHKERRQ(ierr); ierr = DMDASNESSetJacobianLocal(da, (DMDASNESJacobian)Poisson2DJacobianLocal,&user); CHKERRQ(ierr); ierr = SNESSetFromOptions(snes);CHKERRQ(ierr); // initial iterate is zero ierr = DMCreateGlobalVector(da,&u_initial);CHKERRQ(ierr); ierr = VecSet(u_initial,0.0); CHKERRQ(ierr); /* solve; then get solution and DM after solution*/ ierr = SNESSolve(snes,NULL,u_initial);CHKERRQ(ierr); ierr = VecDestroy(&u_initial); CHKERRQ(ierr); ierr = DMDestroy(&da); CHKERRQ(ierr); ierr = SNESGetDM(snes,&da_after); CHKERRQ(ierr); ierr = SNESGetSolution(snes,&u); CHKERRQ(ierr); /* do not destroy u */ /* performance measures */ ierr = SNESGetConvergedReason(snes,&reason); CHKERRQ(ierr); if (reason <= 0) { ierr = PetscPrintf(PETSC_COMM_WORLD, "WARNING: SNES not converged ... use -snes_converged_reason to check\n"); CHKERRQ(ierr); } ierr = SNESGetIterationNumber(snes,&snesits); CHKERRQ(ierr); ierr = PetscGetFlops(&lflops); CHKERRQ(ierr); ierr = MPI_Allreduce(&lflops,&flops,1,MPI_DOUBLE,MPI_SUM,PETSC_COMM_WORLD); CHKERRQ(ierr); ierr = DMDAGetLocalInfo(da_after,&info); CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD, "done on %4d x %4d grid; total flops = %.3e; SNES iterations %d\n", info.mx,info.my,flops,snesits); CHKERRQ(ierr); SNESDestroy(&snes); return PetscFinalize(); }
int main(int argc,char **argv) { SNES snes; /* nonlinear solver */ SNES psnes; /* nonlinear Gauss-Seidel approximate solver */ Vec x,b; /* solution vector */ PetscInt its; /* iterations for convergence */ PetscErrorCode ierr; DM da; PetscBool use_ngs = PETSC_FALSE; /* use the nonlinear Gauss-Seidel approximate solver */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Initialize program - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ PetscInitialize(&argc,&argv,(char *)0,help); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create nonlinear solver context - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = SNESCreate(PETSC_COMM_WORLD,&snes);CHKERRQ(ierr); ierr = PetscOptionsGetBool(PETSC_NULL,"-use_ngs",&use_ngs,0);CHKERRQ(ierr); if (use_ngs) { ierr = SNESGetPC(snes,&psnes);CHKERRQ(ierr); ierr = SNESSetType(psnes,SNESSHELL);CHKERRQ(ierr); ierr = SNESShellSetSolve(psnes,NonlinearGS);CHKERRQ(ierr); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create distributed array (DMDA) to manage parallel grid and vectors - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = DMDACreate2d(PETSC_COMM_WORLD, DMDA_BOUNDARY_NONE, DMDA_BOUNDARY_NONE,DMDA_STENCIL_STAR,-4,-4,PETSC_DECIDE,PETSC_DECIDE,1,1,PETSC_NULL,PETSC_NULL,&da);CHKERRQ(ierr); ierr = DMDASetUniformCoordinates(da, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0);CHKERRQ(ierr); ierr = SNESSetDM(snes,da);CHKERRQ(ierr); if (use_ngs) { ierr = SNESShellSetContext(psnes,da);CHKERRQ(ierr); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Extract global vectors from DMDA; then duplicate for remaining vectors that are the same types - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = DMCreateGlobalVector(da,&x);CHKERRQ(ierr); ierr = DMCreateGlobalVector(da,&b);CHKERRQ(ierr); ierr = VecSetRandom(b,PETSC_NULL);CHKERRQ(ierr); ierr = SNESSetFunction(snes,PETSC_NULL,MyComputeFunction,PETSC_NULL);CHKERRQ(ierr); ierr = SNESSetJacobian(snes,PETSC_NULL,PETSC_NULL,MyComputeJacobian,PETSC_NULL);CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Customize nonlinear solver; set runtime options - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = SNESSetFromOptions(snes);CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Solve nonlinear system - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = SNESSolve(snes,b,x);CHKERRQ(ierr); ierr = SNESGetIterationNumber(snes,&its);CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Free work space. All PETSc objects should be destroyed when they are no longer needed. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = VecDestroy(&x);CHKERRQ(ierr); ierr = VecDestroy(&b);CHKERRQ(ierr); ierr = SNESDestroy(&snes);CHKERRQ(ierr); ierr = DMDestroy(&da);CHKERRQ(ierr); ierr = PetscFinalize(); PetscFunctionReturn(0); }