/* 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); }
void PetscDMNonlinearSolver<T>::init() { PetscErrorCode ierr; DM dm; this->PetscNonlinearSolver<T>::init(); // Attaching a DM with the function and Jacobian callbacks to SNES. ierr = DMCreateLibMesh(libMesh::COMM_WORLD, this->system(), &dm); CHKERRABORT(libMesh::COMM_WORLD, ierr); ierr = DMSetFromOptions(dm); CHKERRABORT(libMesh::COMM_WORLD, ierr); ierr = DMSetUp(dm); CHKERRABORT(libMesh::COMM_WORLD, ierr); ierr = SNESSetDM(this->_snes, dm); CHKERRABORT(libMesh::COMM_WORLD, ierr); // SNES now owns the reference to dm. ierr = DMDestroy(&dm); CHKERRABORT(libMesh::COMM_WORLD, ierr); KSP ksp; ierr = SNESGetKSP (this->_snes, &ksp); CHKERRABORT(libMesh::COMM_WORLD,ierr); // Set the tolerances for the iterative solver. Use the user-supplied // tolerance for the relative residual & leave the others at default values ierr = KSPSetTolerances (ksp, this->initial_linear_tolerance, PETSC_DEFAULT,PETSC_DEFAULT, this->max_linear_iterations); CHKERRABORT(libMesh::COMM_WORLD,ierr); // Set the tolerances for the non-linear solver. ierr = SNESSetTolerances(this->_snes, this->absolute_residual_tolerance, this->relative_residual_tolerance, this->absolute_step_tolerance, this->max_nonlinear_iterations, this->max_function_evaluations); CHKERRABORT(libMesh::COMM_WORLD,ierr); //Pull in command-line options KSPSetFromOptions(ksp); SNESSetFromOptions(this->_snes); }
/** The second heart of the nonlinear solver. Assembles Jacobian matrix. If nonlinear solves are not converging, this is the place to start looking. @param snes nonlinear solver context @param g point at which Jacobian is to be evaluated @param jac matrix pointer to put values in @param B preconditioner pointer to put values in (usually == jac) */ PetscErrorCode FormJacobian(SNES snes, Vec g, Mat jac, Mat B, void *ctx) { User user = (User) ctx; //Algebra algebra = user->algebra; PetscErrorCode ierr; PetscMPIInt rank; PetscFunctionBegin; ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr); //ierr = MatCreateSNESMF(snes,&jac);CHKERRQ(ierr); if (user->fd_jacobian) { /* compute the Jacobian using FD */ // PetscPrintf(PETSC_COMM_WORLD,"Form Jacobian\n"); ierr = SNESComputeJacobianDefault(snes, g, jac, jac, (void*) ctx);CHKERRQ(ierr); ierr = SNESSetTolerances(snes,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1.e6);CHKERRQ(ierr); // MatView(jac,PETSC_VIEWER_STDOUT_WORLD); }else if(user->fd_jacobian_color){ /* compute the Jacobian using FD coloring */ /* using the FD coloring to find the jacobian of the stabilizd term and form the analytic jacobian of the linear and nonlinear term */ ierr = SNESComputeJacobianDefaultColor(snes, g, jac, jac, 0);CHKERRQ(ierr); }else { /* form the analytic Jacobian for all the terms */ ierr = SetupJacobian(user->dm, g, jac, B, user);CHKERRQ(ierr); } PetscFunctionReturn(0); }
/*@ SNESFASCycleSetCycles - Sets the number of cycles on a particular level. Logically Collective on SNES Input Parameters: + snes - the multigrid context . level - the level to set the number of cycles on - cycles - the number of cycles -- 1 for V-cycle, 2 for W-cycle Level: advanced .keywords: SNES, FAS, set, cycles, V-cycle, W-cycle, multigrid .seealso: SNESFASSetCycles() @*/ PetscErrorCode SNESFASCycleSetCycles(SNES snes, PetscInt cycles) { SNES_FAS *fas = (SNES_FAS*)snes->data; PetscErrorCode ierr; PetscFunctionBegin; fas->n_cycles = cycles; ierr = SNESSetTolerances(snes, snes->abstol, snes->rtol, snes->stol, cycles, snes->max_funcs);CHKERRQ(ierr); 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); };
/*@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); }
/*@ SNESFASSetNumberSmoothDown - Sets the number of pre-smoothing steps to use on all levels. Logically Collective on SNES Input Parameters: + snes - the multigrid context - n - the number of smoothing steps Options Database Key: . -snes_fas_smoothdown <n> - Sets number of pre-smoothing steps Level: advanced .keywords: FAS, MG, smooth, down, pre-smoothing, steps, multigrid .seealso: SNESFASSetNumberSmoothUp() @*/ PetscErrorCode SNESFASSetNumberSmoothDown(SNES snes, PetscInt n) { SNES_FAS *fas = (SNES_FAS*)snes->data; PetscErrorCode ierr = 0; PetscFunctionBegin; if (!fas->smoothd) { ierr = SNESFASCycleCreateSmoother_Private(snes, &fas->smoothd);CHKERRQ(ierr); } ierr = SNESSetTolerances(fas->smoothd, fas->smoothd->abstol, fas->smoothd->rtol, fas->smoothd->stol, n, fas->smoothd->max_funcs);CHKERRQ(ierr); fas->max_down_it = n; if (fas->next) { ierr = SNESFASSetNumberSmoothDown(fas->next, n);CHKERRQ(ierr); } PetscFunctionReturn(0); }
// ------------------------------------------------------------- // PetscNonlinearSolverImplementation::p_build // ------------------------------------------------------------- void PetscNonlinearSolverImplementation::p_build(const std::string& option_prefix) { PetscErrorCode ierr(0); try { ierr = SNESCreate(this->communicator(), &p_snes); CHKERRXX(ierr); p_petsc_F = PETScVector(*p_F); if (!p_function.empty()) { ierr = SNESSetFunction(p_snes, *p_petsc_F, FormFunction, static_cast<void *>(this)); CHKERRXX(ierr); } p_petsc_J = PETScMatrix(*p_J); if (!p_jacobian.empty()) { ierr = SNESSetJacobian(p_snes, *p_petsc_J, *p_petsc_J, FormJacobian, static_cast<void *>(this)); CHKERRXX(ierr); } // set the ierr = SNESSetOptionsPrefix(p_snes, option_prefix.c_str()); CHKERRXX(ierr); KSP ksp; ierr = SNESGetKSP(p_snes, &ksp); CHKERRXX(ierr); ierr = KSPSetOptionsPrefix(ksp, option_prefix.c_str()); CHKERRXX(ierr); PC pc; ierr = KSPGetPC(ksp, &pc); CHKERRXX(ierr); ierr = PCSetOptionsPrefix(pc, option_prefix.c_str()); CHKERRXX(ierr); ierr = SNESMonitorSet(p_snes, MonitorNorms, PETSC_NULL, PETSC_NULL); CHKERRXX(ierr); ierr = SNESSetTolerances(p_snes, p_functionTolerance, PETSC_DEFAULT, p_solutionTolerance, p_maxIterations, PETSC_DEFAULT); ierr = SNESSetFromOptions(p_snes); CHKERRXX(ierr); } catch (const PETSC_EXCEPTION_TYPE& e) { throw PETScException(ierr, e); } }
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); }
/*@ SNESFASSetCycles - Sets the number of FAS multigrid cycles to use each time a grid is visited. Use SNESFASSetCyclesOnLevel() for more complicated cycling. Logically Collective on SNES Input Parameters: + snes - the multigrid context - cycles - the number of cycles -- 1 for V-cycle, 2 for W-cycle Options Database Key: . -snes_fas_cycles 1 or 2 Level: advanced .keywords: MG, set, cycles, V-cycle, W-cycle, multigrid .seealso: SNESFASSetCyclesOnLevel() @*/ PetscErrorCode SNESFASSetCycles(SNES snes, PetscInt cycles) { SNES_FAS *fas = (SNES_FAS*)snes->data; PetscErrorCode ierr; PetscBool isFine; PetscFunctionBegin; ierr = SNESFASCycleIsFine(snes, &isFine);CHKERRQ(ierr); fas->n_cycles = cycles; if (!isFine) { ierr = SNESSetTolerances(snes, snes->abstol, snes->rtol, snes->stol, cycles, snes->max_funcs);CHKERRQ(ierr); } if (fas->next) { ierr = SNESFASSetCycles(fas->next, cycles);CHKERRQ(ierr); } PetscFunctionReturn(0); }
/*@ SNESFASSetNumberSmoothUp - Sets the number of post-smoothing steps to use on all levels. Logically Collective on SNES Input Parameters: + snes - the multigrid context - n - the number of smoothing steps Options Database Key: . -snes_fas_smoothup <n> - Sets number of pre-smoothing steps Level: advanced .keywords: FAS, MG, smooth, down, pre-smoothing, steps, multigrid .seealso: SNESFASSetNumberSmoothDown() @*/ PetscErrorCode SNESFASSetNumberSmoothUp(SNES snes, PetscInt n) { SNES_FAS *fas = (SNES_FAS*)snes->data; PetscErrorCode ierr; PetscFunctionBegin; fas->max_up_it = n; if (!fas->smoothu && fas->level != 0) { ierr = SNESFASCycleCreateSmoother_Private(snes, &fas->smoothu);CHKERRQ(ierr); } if (fas->smoothu) { ierr = SNESSetTolerances(fas->smoothu, fas->smoothu->abstol, fas->smoothu->rtol, fas->smoothu->stol, n, fas->smoothu->max_funcs);CHKERRQ(ierr); } if (fas->next) { ierr = SNESFASSetNumberSmoothUp(fas->next, n);CHKERRQ(ierr); } 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); }
std::pair<unsigned int, Real> PetscNonlinearSolver<T>::solve (SparseMatrix<T>& jac_in, // System Jacobian Matrix NumericVector<T>& x_in, // Solution vector NumericVector<T>& r_in, // Residual vector const double, // Stopping tolerance const unsigned int) { START_LOG("solve()", "PetscNonlinearSolver"); this->init (); // Make sure the data passed in are really of Petsc types PetscMatrix<T>* jac = libmesh_cast_ptr<PetscMatrix<T>*>(&jac_in); PetscVector<T>* x = libmesh_cast_ptr<PetscVector<T>*>(&x_in); PetscVector<T>* r = libmesh_cast_ptr<PetscVector<T>*>(&r_in); PetscErrorCode ierr=0; PetscInt n_iterations =0; // Should actually be a PetscReal, but I don't know which version of PETSc first introduced PetscReal Real final_residual_norm=0.; ierr = SNESSetFunction (_snes, r->vec(), __libmesh_petsc_snes_residual, this); LIBMESH_CHKERRABORT(ierr); // Only set the jacobian function if we've been provided with something to call. // This allows a user to set their own jacobian function if they want to if (this->jacobian || this->jacobian_object || this->residual_and_jacobian_object) { ierr = SNESSetJacobian (_snes, jac->mat(), jac->mat(), __libmesh_petsc_snes_jacobian, this); LIBMESH_CHKERRABORT(ierr); } #if !PETSC_VERSION_LESS_THAN(3,3,0) // Only set the nullspace if we have a way of computing it and the result is non-empty. if (this->nullspace || this->nullspace_object) { MatNullSpace msp; this->build_mat_null_space(this->nullspace_object, this->nullspace, &msp); if (msp) { ierr = MatSetNullSpace(jac->mat(), msp); LIBMESH_CHKERRABORT(ierr); ierr = MatNullSpaceDestroy(&msp); LIBMESH_CHKERRABORT(ierr); } } // Only set the nearnullspace if we have a way of computing it and the result is non-empty. if (this->nearnullspace || this->nearnullspace_object) { MatNullSpace msp = PETSC_NULL; this->build_mat_null_space(this->nearnullspace_object, this->nearnullspace, &msp); if(msp) { ierr = MatSetNearNullSpace(jac->mat(), msp); LIBMESH_CHKERRABORT(ierr); ierr = MatNullSpaceDestroy(&msp); LIBMESH_CHKERRABORT(ierr); } } #endif // Have the Krylov subspace method use our good initial guess rather than 0 KSP ksp; ierr = SNESGetKSP (_snes, &ksp); LIBMESH_CHKERRABORT(ierr); // Set the tolerances for the iterative solver. Use the user-supplied // tolerance for the relative residual & leave the others at default values ierr = KSPSetTolerances (ksp, this->initial_linear_tolerance, PETSC_DEFAULT, PETSC_DEFAULT, this->max_linear_iterations); LIBMESH_CHKERRABORT(ierr); // Set the tolerances for the non-linear solver. ierr = SNESSetTolerances(_snes, this->absolute_residual_tolerance, this->relative_residual_tolerance, this->relative_step_tolerance, this->max_nonlinear_iterations, this->max_function_evaluations); LIBMESH_CHKERRABORT(ierr); //Pull in command-line options KSPSetFromOptions(ksp); SNESSetFromOptions(_snes); if (this->user_presolve) this->user_presolve(this->system()); //Set the preconditioning matrix if(this->_preconditioner) { this->_preconditioner->set_matrix(jac_in); this->_preconditioner->init(); } // ierr = KSPSetInitialGuessNonzero (ksp, PETSC_TRUE); // LIBMESH_CHKERRABORT(ierr); // Older versions (at least up to 2.1.5) of SNESSolve took 3 arguments, // the last one being a pointer to an int to hold the number of iterations required. # if PETSC_VERSION_LESS_THAN(2,2,0) ierr = SNESSolve (_snes, x->vec(), &n_iterations); LIBMESH_CHKERRABORT(ierr); // 2.2.x style #elif PETSC_VERSION_LESS_THAN(2,3,0) ierr = SNESSolve (_snes, x->vec()); LIBMESH_CHKERRABORT(ierr); // 2.3.x & newer style #else ierr = SNESSolve (_snes, PETSC_NULL, x->vec()); LIBMESH_CHKERRABORT(ierr); ierr = SNESGetIterationNumber(_snes,&n_iterations); LIBMESH_CHKERRABORT(ierr); ierr = SNESGetLinearSolveIterations(_snes, &_n_linear_iterations); LIBMESH_CHKERRABORT(ierr); ierr = SNESGetFunctionNorm(_snes,&final_residual_norm); LIBMESH_CHKERRABORT(ierr); #endif // Get and store the reason for convergence SNESGetConvergedReason(_snes, &_reason); //Based on Petsc 2.3.3 documentation all diverged reasons are negative this->converged = (_reason >= 0); this->clear(); STOP_LOG("solve()", "PetscNonlinearSolver"); // return the # of its. and the final residual norm. return std::make_pair(n_iterations, final_residual_norm); }
int main(int argc,char **argv) { SNES snes; /* nonlinear solver context */ Vec x,r; /* solution, residual vectors */ Mat J; /* Jacobian matrix */ PetscErrorCode ierr; PetscScalar *xx; PetscInt i,max_snes_solves = 20,snes_steps_per_solve = 2,criteria_reduce = 1; Ctx ctx; SNESConvergedReason reason; PetscInitialize(&argc,&argv,(char*)0,help); ctx.n = 0; ierr = PetscOptionsGetInt(NULL,"-n",&ctx.n,NULL);CHKERRQ(ierr); ctx.p = 0; ierr = PetscOptionsGetInt(NULL,"-p",&ctx.p,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetInt(NULL,"-max_snes_solves",&max_snes_solves,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetInt(NULL,"-snes_steps_per_solve",&snes_steps_per_solve,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetInt(NULL,"-criteria_reduce",&criteria_reduce,NULL);CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create nonlinear solver context - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = SNESCreate(PETSC_COMM_WORLD,&snes);CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create matrix and vector data structures; set corresponding routines - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* Create vectors for solution and nonlinear function */ ierr = VecCreate(PETSC_COMM_WORLD,&x);CHKERRQ(ierr); ierr = VecSetSizes(x,PETSC_DECIDE,2+ctx.n+ctx.p);CHKERRQ(ierr); ierr = VecSetFromOptions(x);CHKERRQ(ierr); ierr = VecDuplicate(x,&r);CHKERRQ(ierr); /* Create Jacobian matrix data structure */ ierr = MatCreate(PETSC_COMM_WORLD,&J);CHKERRQ(ierr); ierr = MatSetSizes(J,PETSC_DECIDE,PETSC_DECIDE,2+ctx.p+ctx.n,2+ctx.p+ctx.n);CHKERRQ(ierr); ierr = MatSetFromOptions(J);CHKERRQ(ierr); ierr = MatSetUp(J);CHKERRQ(ierr); /* Set function evaluation routine and vector. */ ierr = SNESSetFunction(snes,r,FormFunction1,(void*)&ctx);CHKERRQ(ierr); /* Set Jacobian matrix data structure and Jacobian evaluation routine */ ierr = SNESSetJacobian(snes,J,J,FormJacobian1,(void*)&ctx);CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Customize nonlinear solver; set runtime options - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = SNESSetFromOptions(snes);CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Evaluate initial guess; then solve nonlinear system - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = VecSet(x,0.0);CHKERRQ(ierr); ierr = VecGetArray(x,&xx);CHKERRQ(ierr); xx[0] = -1.2; for (i=1; i<ctx.p+2; i++) xx[i] = 1.0; ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr); /* Note: The user should initialize the vector, x, with the initial guess for the nonlinear solver prior to calling SNESSolve(). In particular, to employ an initial guess of zero, the user should explicitly set this vector to zero by calling VecSet(). */ ierr = SNESMonitorSet(snes,MonitorRange,0,0);CHKERRQ(ierr); ierr = SNESSetTolerances(snes,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,snes_steps_per_solve,PETSC_DEFAULT);CHKERRQ(ierr); for (i=0; i<max_snes_solves; i++) { ierr = SNESSolve(snes,NULL,x);CHKERRQ(ierr); ierr = SNESGetConvergedReason(snes,&reason);CHKERRQ(ierr); if (reason && reason != SNES_DIVERGED_MAX_IT) break; if (CountGood > criteria_reduce) { ierr = SolveSubproblem(snes);CHKERRQ(ierr); CountGood = 0; } } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Free work space. All PETSc objects should be destroyed when they are no longer needed. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = VecDestroy(&x);CHKERRQ(ierr); ierr = VecDestroy(&r);CHKERRQ(ierr); ierr = MatDestroy(&J);CHKERRQ(ierr); ierr = SNESDestroy(&snes);CHKERRQ(ierr); ierr = PetscFinalize(); 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)); }