PetscErrorCode SNESVIResetPCandKSP(SNES snes,Mat Amat,Mat Pmat) { PetscErrorCode ierr; KSP snesksp; PetscFunctionBegin; ierr = SNESGetKSP(snes,&snesksp);CHKERRQ(ierr); ierr = KSPReset(snesksp);CHKERRQ(ierr); /* KSP kspnew; PC pcnew; const MatSolverPackage stype; ierr = KSPCreate(((PetscObject)snes)->comm,&kspnew);CHKERRQ(ierr); kspnew->pc_side = snesksp->pc_side; kspnew->rtol = snesksp->rtol; kspnew->abstol = snesksp->abstol; kspnew->max_it = snesksp->max_it; ierr = KSPSetType(kspnew,((PetscObject)snesksp)->type_name);CHKERRQ(ierr); ierr = KSPGetPC(kspnew,&pcnew);CHKERRQ(ierr); ierr = PCSetType(kspnew->pc,((PetscObject)snesksp->pc)->type_name);CHKERRQ(ierr); ierr = PCSetOperators(kspnew->pc,Amat,Pmat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); ierr = PCFactorGetMatSolverPackage(snesksp->pc,&stype);CHKERRQ(ierr); ierr = PCFactorSetMatSolverPackage(kspnew->pc,stype);CHKERRQ(ierr); ierr = KSPDestroy(&snesksp);CHKERRQ(ierr); snes->ksp = kspnew; ierr = PetscLogObjectParent(snes,kspnew);CHKERRQ(ierr); ierr = KSPSetFromOptions(kspnew);CHKERRQ(ierr);*/ 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); }
/** My handrolled SNES monitor. Gives some information about KSP convergence as well as looking pretty. @param snes Petsc nonlinear context @param its number of iterations @param norm norm of nonlinear residual @param dctx application context */ PetscErrorCode MonitorFunction(SNES snes, PetscInt its, double norm, void *dctx) { PetscErrorCode ierr; PetscInt lits; PetscMPIInt rank; KSP ksp; KSPConvergedReason kspreason; PetscReal kspnorm; PetscFunctionBegin; ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr); ierr = SNESGetKSP(snes, &ksp);CHKERRQ(ierr); ierr = KSPGetConvergedReason(ksp, &kspreason);CHKERRQ(ierr); ierr = KSPGetResidualNorm(ksp, &kspnorm);CHKERRQ(ierr); ierr = KSPGetIterationNumber(ksp, &lits);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD, " %d SNES norm %e, %d KSP its last norm %e", its, norm, lits, kspnorm);CHKERRQ(ierr); if (kspreason < 0) { ierr = PetscPrintf(PETSC_COMM_WORLD, ", KSP failed: %s", KSPConvergedReasons[kspreason]);CHKERRQ(ierr); } ierr = PetscPrintf(PETSC_COMM_WORLD, ".\n");CHKERRQ(ierr); PetscFunctionReturn(0); }
void PetscOutputter::timestepSetupInternal() { // Only execute if PETSc exists #ifdef LIBMESH_HAVE_PETSC // Extract the non-linear and linear solvers from PETSc NonlinearSystem & nl = _problem_ptr->getNonlinearSystem(); PetscNonlinearSolver<Number> * petsc_solver = dynamic_cast<PetscNonlinearSolver<Number> *>(nl.sys().nonlinear_solver.get()); SNES snes = petsc_solver->snes(); KSP ksp; SNESGetKSP(snes, &ksp); // Update the pseudo times _nonlinear_time = _time_old; // non-linear time starts with the previous time step _nonlinear_dt = _dt/_nonlinear_dt_divisor; // set the pseudo non-linear timestep _linear_dt = _nonlinear_dt/_linear_dt_divisor; // set the pseudo linear timestep // Set the PETSc monitor functions if (_output_nonlinear || (_time >= _nonlinear_start_time - _t_tol && _time <= _nonlinear_end_time + _t_tol) ) { PetscErrorCode ierr = SNESMonitorSet(snes, petscNonlinearOutput, this, PETSC_NULL); CHKERRABORT(libMesh::COMM_WORLD,ierr); } if (_output_linear || (_time >= _linear_start_time - _t_tol && _time <= _linear_end_time + _t_tol) ) { PetscErrorCode ierr = KSPMonitorSet(ksp, petscLinearOutput, this, PETSC_NULL); CHKERRABORT(libMesh::COMM_WORLD,ierr); } #endif }
/* PostSetSubKSP - Optional user-defined routine that reset SubKSP options when hierarchical bjacobi PC is used e.g, mpiexec -n 8 ./ex3 -nox -n 10000 -ksp_type fgmres -pc_type bjacobi -pc_bjacobi_blocks 4 -sub_ksp_type gmres -sub_ksp_max_it 3 -post_setsubksp -sub_ksp_rtol 1.e-16 Set by SNESLineSearchSetPostCheck(). Input Parameters: linesearch - the LineSearch context xcurrent - current solution y - search direction and length x - the new candidate iterate Output Parameters: y - proposed step (search direction and length) (possibly changed) x - current iterate (possibly modified) */ PetscErrorCode PostSetSubKSP(SNESLineSearch linesearch,Vec xcurrent,Vec y,Vec x,PetscBool *changed_y,PetscBool *changed_x, void * ctx) { PetscErrorCode ierr; SetSubKSPCtx *check; PetscInt iter,its,sub_its,maxit; KSP ksp,sub_ksp,*sub_ksps; PC pc; PetscReal ksp_ratio; SNES snes; PetscFunctionBeginUser; ierr = SNESLineSearchGetSNES(linesearch, &snes);CHKERRQ(ierr); check = (SetSubKSPCtx*)ctx; ierr = SNESGetIterationNumber(snes,&iter);CHKERRQ(ierr); ierr = SNESGetKSP(snes,&ksp);CHKERRQ(ierr); ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); ierr = PCBJacobiGetSubKSP(pc,NULL,NULL,&sub_ksps);CHKERRQ(ierr); sub_ksp = sub_ksps[0]; ierr = KSPGetIterationNumber(ksp,&its);CHKERRQ(ierr); /* outer KSP iteration number */ ierr = KSPGetIterationNumber(sub_ksp,&sub_its);CHKERRQ(ierr); /* inner KSP iteration number */ if (iter) { ierr = PetscPrintf(PETSC_COMM_WORLD," ...PostCheck snes iteration %D, ksp_it %d %d, subksp_it %d\n",iter,check->its0,its,sub_its);CHKERRQ(ierr); ksp_ratio = ((PetscReal)(its))/check->its0; maxit = (PetscInt)(ksp_ratio*sub_its + 0.5); if (maxit < 2) maxit = 2; ierr = KSPSetTolerances(sub_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,maxit);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD," ...ksp_ratio %g, new maxit %d\n\n",ksp_ratio,maxit);CHKERRQ(ierr); } check->its0 = its; /* save current outer KSP iteration number */ PetscFunctionReturn(0); }
int main(int argc,char **argv) { PetscErrorCode ierr; SNES snes; KSP ksp; Vec u, uexact; FishCtx user; DMDALocalInfo info; double errnorm; PetscInitialize(&argc,&argv,NULL,help); user.printevals = PETSC_FALSE; ierr = PetscOptionsBegin(PETSC_COMM_WORLD, "f3_", "options for fish3", ""); CHKERRQ(ierr); ierr = PetscOptionsBool("-printevals","residual and Jacobian routines report grid", "fish3.c",user.printevals,&user.printevals,NULL);CHKERRQ(ierr); ierr = PetscOptionsEnd(); CHKERRQ(ierr); ierr = DMDACreate3d(COMM, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DMDA_STENCIL_STAR, 3,3,3,PETSC_DECIDE,PETSC_DECIDE,PETSC_DECIDE, 1,1, NULL,NULL,NULL,&(user.da)); CHKERRQ(ierr); ierr = DMSetFromOptions(user.da); CHKERRQ(ierr); ierr = DMSetUp(user.da); CHKERRQ(ierr); ierr = DMSetApplicationContext(user.da,&user);CHKERRQ(ierr); ierr = DMDAGetLocalInfo(user.da,&info); CHKERRQ(ierr); ierr = DMCreateGlobalVector(user.da,&u);CHKERRQ(ierr); ierr = VecDuplicate(u,&uexact);CHKERRQ(ierr); ierr = VecDuplicate(u,&(user.b));CHKERRQ(ierr); ierr = formExactRHS(&info,uexact,user.b,&user); CHKERRQ(ierr); ierr = SNESCreate(COMM,&snes); CHKERRQ(ierr); ierr = SNESSetDM(snes,user.da); CHKERRQ(ierr); ierr = DMDASNESSetFunctionLocal(user.da,INSERT_VALUES, (DMDASNESFunction)FormFunctionLocal,&user); CHKERRQ(ierr); ierr = DMDASNESSetJacobianLocal(user.da, (DMDASNESJacobian)FormJacobianLocal,&user); CHKERRQ(ierr); ierr = SNESGetKSP(snes,&ksp); CHKERRQ(ierr); ierr = KSPSetType(ksp,KSPCG); CHKERRQ(ierr); ierr = SNESSetFromOptions(snes); CHKERRQ(ierr); ierr = VecSet(u,0.0); CHKERRQ(ierr); ierr = SNESSolve(snes,NULL,u); CHKERRQ(ierr); ierr = VecAXPY(u,-1.0,uexact); CHKERRQ(ierr); // u <- u + (-1.0) uexact ierr = VecNorm(u,NORM_INFINITY,&errnorm); CHKERRQ(ierr); ierr = PetscPrintf(COMM,"on %d x %d x %d grid: error |u-uexact|_inf = %g\n", info.mx,info.my,info.mz,errnorm); CHKERRQ(ierr); VecDestroy(&u); VecDestroy(&uexact); VecDestroy(&(user.b)); SNESDestroy(&snes); DMDestroy(&(user.da)); PetscFinalize(); return 0; }
PetscErrorCode RunTest(int nx, int ny, int nz, int loops, double *wt) { Vec x,f; TS ts; AppCtx _app,*app=&_app; double t1,t2; PetscErrorCode ierr; PetscFunctionBegin; app->nx = nx; app->h[0] = 1./(nx-1); app->ny = ny; app->h[1] = 1./(ny-1); app->nz = nz; app->h[2] = 1./(nz-1); ierr = VecCreate(PETSC_COMM_SELF,&x);CHKERRQ(ierr); ierr = VecSetSizes(x,nx*ny*nz,nx*ny*nz);CHKERRQ(ierr); ierr = VecSetUp(x);CHKERRQ(ierr); ierr = VecDuplicate(x,&f);CHKERRQ(ierr); ierr = TSCreate(PETSC_COMM_SELF,&ts);CHKERRQ(ierr); ierr = TSSetProblemType(ts,TS_NONLINEAR);CHKERRQ(ierr); ierr = TSSetType(ts,TSTHETA);CHKERRQ(ierr); ierr = TSThetaSetTheta(ts,1.0);CHKERRQ(ierr); ierr = TSSetTimeStep(ts,0.01);CHKERRQ(ierr); ierr = TSSetTime(ts,0.0);CHKERRQ(ierr); ierr = TSSetDuration(ts,10,1.0);CHKERRQ(ierr); ierr = TSSetSolution(ts,x);CHKERRQ(ierr); ierr = TSSetIFunction(ts,f,FormFunction,app);CHKERRQ(ierr); ierr = PetscOptionsSetValue("-snes_mf","1");CHKERRQ(ierr); { SNES snes; KSP ksp; ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr); ierr = SNESGetKSP(snes,&ksp);CHKERRQ(ierr); ierr = KSPSetType(ksp,KSPCG);CHKERRQ(ierr); } ierr = TSSetFromOptions(ts);CHKERRQ(ierr); ierr = TSSetUp(ts);CHKERRQ(ierr); *wt = 1e300; while (loops-- > 0) { ierr = FormInitial(0.0,x,app);CHKERRQ(ierr); ierr = PetscGetTime(&t1);CHKERRQ(ierr); ierr = TSSolve(ts,x,PETSC_NULL);CHKERRQ(ierr); ierr = PetscGetTime(&t2);CHKERRQ(ierr); *wt = PetscMin(*wt,t2-t1); } ierr = VecDestroy(&x);CHKERRQ(ierr); ierr = VecDestroy(&f);CHKERRQ(ierr); ierr = TSDestroy(&ts);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode TSSundialsGetPC_Sundials(TS ts,PC *pc) { SNES snes; KSP ksp; PetscErrorCode ierr; PetscFunctionBegin; ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr); ierr = SNESGetKSP(snes,&ksp);CHKERRQ(ierr); ierr = KSPGetPC(ksp,pc);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); };
PetscErrorCode MatMultASPIN(Mat m,Vec X,Vec Y) { PetscErrorCode ierr; void *ctx; SNES snes; PetscInt n,i; VecScatter *oscatter; SNES *subsnes; PetscBool match; MPI_Comm comm; KSP ksp; Vec *x,*b; Vec W; SNES npc; Mat subJ,subpJ; PetscFunctionBegin; ierr = MatShellGetContext(m,&ctx);CHKERRQ(ierr); snes = (SNES)ctx; ierr = SNESGetNPC(snes,&npc);CHKERRQ(ierr); ierr = SNESGetFunction(npc,&W,NULL,NULL);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject)npc,SNESNASM,&match);CHKERRQ(ierr); if (!match) { ierr = PetscObjectGetComm((PetscObject)snes,&comm); SETERRQ(comm,PETSC_ERR_ARG_WRONGSTATE,"MatMultASPIN requires that the nonlinear preconditioner be Nonlinear additive Schwarz"); } ierr = SNESNASMGetSubdomains(npc,&n,&subsnes,NULL,&oscatter,NULL);CHKERRQ(ierr); ierr = SNESNASMGetSubdomainVecs(npc,&n,&x,&b,NULL,NULL);CHKERRQ(ierr); ierr = VecSet(Y,0);CHKERRQ(ierr); ierr = MatMult(npc->jacobian_pre,X,W);CHKERRQ(ierr); for (i=0;i<n;i++) { ierr = VecScatterBegin(oscatter[i],W,b[i],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); } for (i=0;i<n;i++) { ierr = VecScatterEnd(oscatter[i],W,b[i],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); ierr = VecSet(x[i],0.);CHKERRQ(ierr); ierr = SNESGetJacobian(subsnes[i],&subJ,&subpJ,NULL,NULL);CHKERRQ(ierr); ierr = SNESGetKSP(subsnes[i],&ksp);CHKERRQ(ierr); ierr = KSPSetOperators(ksp,subJ,subpJ);CHKERRQ(ierr); ierr = KSPSolve(ksp,b[i],x[i]);CHKERRQ(ierr); ierr = VecScatterBegin(oscatter[i],x[i],Y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); } for (i=0;i<n;i++) { ierr = VecScatterEnd(oscatter[i],x[i],Y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); } PetscFunctionReturn(0); }
EXTERN_C_END EXTERN_C_BEGIN #undef __FUNCT__ #define __FUNCT__ "TSSundialsGetPC_Sundials" PetscErrorCode TSSundialsGetPC_Sundials(TS ts,PC *pc) { SNES snes; KSP ksp; PetscErrorCode ierr; PetscFunctionBegin; ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr); ierr = SNESGetKSP(snes,&ksp);CHKERRQ(ierr); ierr = KSPGetPC(ksp,pc); CHKERRQ(ierr); PetscFunctionReturn(0); }
void petscSetDefaults(FEProblem & problem) { // dig out Petsc solver NonlinearSystem & nl = problem.getNonlinearSystem(); PetscNonlinearSolver<Number> * petsc_solver = dynamic_cast<PetscNonlinearSolver<Number> *>(nl.sys().nonlinear_solver.get()); SNES snes = petsc_solver->snes(); KSP ksp; SNESGetKSP(snes, &ksp); PCSide pcside = getPetscPCSide(nl.getPCSide()); #if PETSC_VERSION_LESS_THAN(3,2,0) // PETSc 3.1.x- KSPSetPreconditionerSide(ksp, pcside); #else // PETSc 3.2.x+ KSPSetPCSide(ksp, pcside); #endif SNESSetMaxLinearSolveFailures(snes, 1000000); #if PETSC_VERSION_LESS_THAN(3,0,0) // PETSc 2.3.3- KSPSetConvergenceTest(ksp, petscConverged, &problem); SNESSetConvergenceTest(snes, petscNonlinearConverged, &problem); #else // PETSc 3.0.0+ // In 3.0.0, the context pointer must actually be used, and the // final argument to KSPSetConvergenceTest() is a pointer to a // routine for destroying said private data context. In this case, // we use the default context provided by PETSc in addition to // a few other tests. { PetscErrorCode ierr = KSPSetConvergenceTest(ksp, petscConverged, &problem, PETSC_NULL); CHKERRABORT(nl.comm().get(),ierr); ierr = SNESSetConvergenceTest(snes, petscNonlinearConverged, &problem, PETSC_NULL); CHKERRABORT(nl.comm().get(),ierr); } #endif }
// ------------------------------------------------------------- // 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); } }
PetscErrorCode FormJacobian(SNES snes,Vec X,Mat *J,Mat *B,MatStructure *flag,void *ptr) { AppCtx *user = (AppCtx *) ptr; PetscErrorCode ierr; KSP ksp; PC pc; PetscBool ismg; *flag = SAME_NONZERO_PATTERN; ierr = FormJacobian_Grid(user,&user->fine,X,J,B);CHKERRQ(ierr); /* create coarse grid jacobian for preconditioner */ ierr = SNESGetKSP(snes,&ksp);CHKERRQ(ierr); ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject)pc,PCMG,&ismg);CHKERRQ(ierr); if (ismg) { ierr = KSPSetOperators(user->ksp_fine,user->fine.J,user->fine.J,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* restrict X to coarse grid */ ierr = MatMult(user->R,X,user->coarse.x);CHKERRQ(ierr); ierr = VecPointwiseMult(user->coarse.x,user->coarse.x,user->Rscale);CHKERRQ(ierr); /* form Jacobian on coarse grid */ if (user->redundant_build) { /* get copy of coarse X onto each processor */ ierr = VecScatterBegin(user->tolocalall,user->coarse.x,user->localall,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); ierr = VecScatterEnd(user->tolocalall,user->coarse.x,user->localall,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); ierr = FormJacobian_Coarse(user,&user->coarse,user->localall,&user->coarse.J,&user->coarse.J);CHKERRQ(ierr); } else { /* coarse grid Jacobian computed in parallel */ ierr = FormJacobian_Grid(user,&user->coarse,user->coarse.x,&user->coarse.J,&user->coarse.J);CHKERRQ(ierr); } ierr = KSPSetOperators(user->ksp_coarse,user->coarse.J,user->coarse.J,SAME_NONZERO_PATTERN);CHKERRQ(ierr); } return 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); }
void PetscOutput::solveSetup() { // Only execute if PETSc exists #ifdef LIBMESH_HAVE_PETSC // Extract the non-linear and linear solvers from PETSc NonlinearSystem & nl = _problem_ptr->getNonlinearSystem(); PetscNonlinearSolver<Number> * petsc_solver = dynamic_cast<PetscNonlinearSolver<Number> *>(nl.sys().nonlinear_solver.get()); SNES snes = petsc_solver->snes(); KSP ksp; SNESGetKSP(snes, &ksp); // Update the pseudo times _nonlinear_time = _time_old; // non-linear time starts with the previous time step if (_dt != 0) _nonlinear_dt = _dt/_nonlinear_dt_divisor; // set the pseudo non-linear timestep as fraction of real timestep for transient executioners else _nonlinear_dt = 1./_nonlinear_dt_divisor; // set the pseudo non-linear timestep for steady executioners (here _dt==0) _linear_dt = _nonlinear_dt/_linear_dt_divisor; // set the pseudo linear timestep // Set the PETSc monitor functions if (_output_on.contains(EXEC_NONLINEAR) && (_time >= _nonlinear_start_time - _t_tol && _time <= _nonlinear_end_time + _t_tol) ) { PetscErrorCode ierr = SNESMonitorSet(snes, petscNonlinearOutput, this, PETSC_NULL); CHKERRABORT(_communicator.get(),ierr); } if (_output_on.contains(EXEC_LINEAR) && (_time >= _linear_start_time - _t_tol && _time <= _linear_end_time + _t_tol) ) { PetscErrorCode ierr = KSPMonitorSet(ksp, petscLinearOutput, this, PETSC_NULL); CHKERRABORT(_communicator.get(),ierr); } #endif }
int main(int argc,char **argv) { PetscErrorCode ierr; PetscInt time_steps=100,iout,NOUT=1; PetscMPIInt size; Vec global; PetscReal dt,ftime,ftime_original; TS ts; PetscViewer viewfile; Mat J = 0; Vec x; Data data; PetscInt mn; PetscBool flg; MatColoring mc; ISColoring iscoloring; MatFDColoring matfdcoloring = 0; PetscBool fd_jacobian_coloring = PETSC_FALSE; SNES snes; KSP ksp; PC pc; PetscViewer viewer; char pcinfo[120],tsinfo[120]; TSType tstype; PetscBool sundials; ierr = PetscInitialize(&argc,&argv,(char*)0,help);CHKERRQ(ierr); ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr); /* set data */ data.m = 9; data.n = 9; data.a = 1.0; data.epsilon = 0.1; data.dx = 1.0/(data.m+1.0); data.dy = 1.0/(data.n+1.0); mn = (data.m)*(data.n); ierr = PetscOptionsGetInt(NULL,"-time",&time_steps,NULL);CHKERRQ(ierr); /* set initial conditions */ ierr = VecCreate(PETSC_COMM_WORLD,&global);CHKERRQ(ierr); ierr = VecSetSizes(global,PETSC_DECIDE,mn);CHKERRQ(ierr); ierr = VecSetFromOptions(global);CHKERRQ(ierr); ierr = Initial(global,&data);CHKERRQ(ierr); ierr = VecDuplicate(global,&x);CHKERRQ(ierr); /* create timestep context */ ierr = TSCreate(PETSC_COMM_WORLD,&ts);CHKERRQ(ierr); ierr = TSMonitorSet(ts,Monitor,&data,NULL);CHKERRQ(ierr); #if defined(PETSC_HAVE_SUNDIALS) ierr = TSSetType(ts,TSSUNDIALS);CHKERRQ(ierr); #else ierr = TSSetType(ts,TSEULER);CHKERRQ(ierr); #endif dt = 0.1; ftime_original = data.tfinal = 1.0; ierr = TSSetInitialTimeStep(ts,0.0,dt);CHKERRQ(ierr); ierr = TSSetDuration(ts,time_steps,ftime_original);CHKERRQ(ierr); ierr = TSSetSolution(ts,global);CHKERRQ(ierr); /* set user provided RHSFunction and RHSJacobian */ ierr = TSSetRHSFunction(ts,NULL,RHSFunction,&data);CHKERRQ(ierr); ierr = MatCreate(PETSC_COMM_WORLD,&J);CHKERRQ(ierr); ierr = MatSetSizes(J,PETSC_DECIDE,PETSC_DECIDE,mn,mn);CHKERRQ(ierr); ierr = MatSetFromOptions(J);CHKERRQ(ierr); ierr = MatSeqAIJSetPreallocation(J,5,NULL);CHKERRQ(ierr); ierr = MatMPIAIJSetPreallocation(J,5,NULL,5,NULL);CHKERRQ(ierr); ierr = PetscOptionsHasName(NULL,"-ts_fd",&flg);CHKERRQ(ierr); if (!flg) { ierr = TSSetRHSJacobian(ts,J,J,RHSJacobian,&data);CHKERRQ(ierr); } else { ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr); ierr = PetscOptionsHasName(NULL,"-fd_color",&fd_jacobian_coloring);CHKERRQ(ierr); if (fd_jacobian_coloring) { /* Use finite differences with coloring */ /* Get data structure of J */ PetscBool pc_diagonal; ierr = PetscOptionsHasName(NULL,"-pc_diagonal",&pc_diagonal);CHKERRQ(ierr); if (pc_diagonal) { /* the preconditioner of J is a diagonal matrix */ PetscInt rstart,rend,i; PetscScalar zero=0.0; ierr = MatGetOwnershipRange(J,&rstart,&rend);CHKERRQ(ierr); for (i=rstart; i<rend; i++) { ierr = MatSetValues(J,1,&i,1,&i,&zero,INSERT_VALUES);CHKERRQ(ierr); } ierr = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); } else { /* Fill the structure using the expensive SNESComputeJacobianDefault. Temporarily set up the TS so we can call this function */ ierr = TSSetType(ts,TSBEULER);CHKERRQ(ierr); ierr = TSSetUp(ts);CHKERRQ(ierr); ierr = SNESComputeJacobianDefault(snes,x,J,J,ts);CHKERRQ(ierr); } /* create coloring context */ ierr = MatColoringCreate(J,&mc);CHKERRQ(ierr); ierr = MatColoringSetType(mc,MATCOLORINGSL);CHKERRQ(ierr); ierr = MatColoringSetFromOptions(mc);CHKERRQ(ierr); ierr = MatColoringApply(mc,&iscoloring);CHKERRQ(ierr); ierr = MatColoringDestroy(&mc);CHKERRQ(ierr); ierr = MatFDColoringCreate(J,iscoloring,&matfdcoloring);CHKERRQ(ierr); ierr = MatFDColoringSetFunction(matfdcoloring,(PetscErrorCode (*)(void))SNESTSFormFunction,ts);CHKERRQ(ierr); ierr = MatFDColoringSetFromOptions(matfdcoloring);CHKERRQ(ierr); ierr = MatFDColoringSetUp(J,iscoloring,matfdcoloring);CHKERRQ(ierr); ierr = SNESSetJacobian(snes,J,J,SNESComputeJacobianDefaultColor,matfdcoloring);CHKERRQ(ierr); ierr = ISColoringDestroy(&iscoloring);CHKERRQ(ierr); } else { /* Use finite differences (slow) */ ierr = SNESSetJacobian(snes,J,J,SNESComputeJacobianDefault,NULL);CHKERRQ(ierr); } } /* Pick up a Petsc preconditioner */ /* one can always set method or preconditioner during the run time */ ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr); ierr = SNESGetKSP(snes,&ksp);CHKERRQ(ierr); ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); ierr = PCSetType(pc,PCJACOBI);CHKERRQ(ierr); ierr = TSSetFromOptions(ts);CHKERRQ(ierr); ierr = TSSetUp(ts);CHKERRQ(ierr); /* Test TSSetPostStep() */ ierr = PetscOptionsHasName(NULL,"-test_PostStep",&flg);CHKERRQ(ierr); if (flg) { ierr = TSSetPostStep(ts,PostStep);CHKERRQ(ierr); } ierr = PetscOptionsGetInt(NULL,"-NOUT",&NOUT,NULL);CHKERRQ(ierr); for (iout=1; iout<=NOUT; iout++) { ierr = TSSetDuration(ts,time_steps,iout*ftime_original/NOUT);CHKERRQ(ierr); ierr = TSSolve(ts,global);CHKERRQ(ierr); ierr = TSGetSolveTime(ts,&ftime);CHKERRQ(ierr); ierr = TSSetInitialTimeStep(ts,ftime,dt);CHKERRQ(ierr); } /* Interpolate solution at tfinal */ ierr = TSGetSolution(ts,&global);CHKERRQ(ierr); ierr = TSInterpolate(ts,ftime_original,global);CHKERRQ(ierr); ierr = PetscOptionsHasName(NULL,"-matlab_view",&flg);CHKERRQ(ierr); if (flg) { /* print solution into a MATLAB file */ ierr = PetscViewerASCIIOpen(PETSC_COMM_WORLD,"out.m",&viewfile);CHKERRQ(ierr); ierr = PetscViewerSetFormat(viewfile,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr); ierr = VecView(global,viewfile);CHKERRQ(ierr); ierr = PetscViewerDestroy(&viewfile);CHKERRQ(ierr); } /* display solver info for Sundials */ ierr = TSGetType(ts,&tstype);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject)ts,TSSUNDIALS,&sundials);CHKERRQ(ierr); if (sundials) { ierr = PetscViewerStringOpen(PETSC_COMM_WORLD,tsinfo,120,&viewer);CHKERRQ(ierr); ierr = TSView(ts,viewer);CHKERRQ(ierr); ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); ierr = PetscViewerStringOpen(PETSC_COMM_WORLD,pcinfo,120,&viewer);CHKERRQ(ierr); ierr = PCView(pc,viewer);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"%d Procs,%s TSType, %s Preconditioner\n",size,tsinfo,pcinfo);CHKERRQ(ierr); ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); } /* free the memories */ ierr = TSDestroy(&ts);CHKERRQ(ierr); ierr = VecDestroy(&global);CHKERRQ(ierr); ierr = VecDestroy(&x);CHKERRQ(ierr); ierr = MatDestroy(&J);CHKERRQ(ierr); if (fd_jacobian_coloring) {ierr = MatFDColoringDestroy(&matfdcoloring);CHKERRQ(ierr);} ierr = PetscFinalize(); return 0; }
static PetscErrorCode SNESSolve_TR(SNES snes) { SNES_TR *neP = (SNES_TR*)snes->data; Vec X,F,Y,G,Ytmp; PetscErrorCode ierr; PetscInt maxits,i,lits; MatStructure flg = DIFFERENT_NONZERO_PATTERN; PetscReal rho,fnorm,gnorm,gpnorm,xnorm=0,delta,nrm,ynorm,norm1; PetscScalar cnorm; KSP ksp; SNESConvergedReason reason = SNES_CONVERGED_ITERATING; PetscBool conv = PETSC_FALSE,breakout = PETSC_FALSE; PetscBool domainerror; PetscFunctionBegin; maxits = snes->max_its; /* maximum number of iterations */ X = snes->vec_sol; /* solution vector */ F = snes->vec_func; /* residual vector */ Y = snes->work[0]; /* work vectors */ G = snes->work[1]; Ytmp = snes->work[2]; ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); snes->iter = 0; ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); if (!snes->vec_func_init_set) { ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); /* F(X) */ ierr = SNESGetFunctionDomainError(snes, &domainerror);CHKERRQ(ierr); if (domainerror) { snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; PetscFunctionReturn(0); } } else { snes->vec_func_init_set = PETSC_FALSE; } if (!snes->norm_init_set) { ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr); /* fnorm <- || F || */ if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); } else { fnorm = snes->norm_init; snes->norm_init_set = PETSC_FALSE; } ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); snes->norm = fnorm; ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); delta = neP->delta0*fnorm; neP->delta = delta; SNESLogConvHistory(snes,fnorm,0); ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); /* set parameter for default relative tolerance convergence test */ snes->ttol = fnorm*snes->rtol; /* test convergence */ ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); if (snes->reason) PetscFunctionReturn(0); /* Set the stopping criteria to use the More' trick. */ ierr = PetscOptionsGetBool(PETSC_NULL,"-snes_tr_ksp_regular_convergence_test",&conv,PETSC_NULL);CHKERRQ(ierr); if (!conv) { SNES_TR_KSPConverged_Ctx *ctx; ierr = SNESGetKSP(snes,&ksp);CHKERRQ(ierr); ierr = PetscNew(SNES_TR_KSPConverged_Ctx,&ctx);CHKERRQ(ierr); ctx->snes = snes; ierr = KSPDefaultConvergedCreate(&ctx->ctx);CHKERRQ(ierr); ierr = KSPSetConvergenceTest(ksp,SNES_TR_KSPConverged_Private,ctx,SNES_TR_KSPConverged_Destroy);CHKERRQ(ierr); ierr = PetscInfo(snes,"Using Krylov convergence test SNES_TR_KSPConverged_Private\n");CHKERRQ(ierr); } for (i=0; i<maxits; i++) { /* Call general purpose update function */ if (snes->ops->update) { ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); } /* Solve J Y = F, where J is Jacobian matrix */ ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr); ierr = KSPSetOperators(snes->ksp,snes->jacobian,snes->jacobian_pre,flg);CHKERRQ(ierr); ierr = SNES_KSPSolve(snes,snes->ksp,F,Ytmp);CHKERRQ(ierr); ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr); snes->linear_its += lits; ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr); ierr = VecNorm(Ytmp,NORM_2,&nrm);CHKERRQ(ierr); norm1 = nrm; while(1) { ierr = VecCopy(Ytmp,Y);CHKERRQ(ierr); nrm = norm1; /* Scale Y if need be and predict new value of F norm */ if (nrm >= delta) { nrm = delta/nrm; gpnorm = (1.0 - nrm)*fnorm; cnorm = nrm; ierr = PetscInfo1(snes,"Scaling direction by %G\n",nrm);CHKERRQ(ierr); ierr = VecScale(Y,cnorm);CHKERRQ(ierr); nrm = gpnorm; ynorm = delta; } else { gpnorm = 0.0; ierr = PetscInfo(snes,"Direction is in Trust Region\n");CHKERRQ(ierr); ynorm = nrm; } ierr = VecAYPX(Y,-1.0,X);CHKERRQ(ierr); /* Y <- X - Y */ ierr = VecCopy(X,snes->vec_sol_update);CHKERRQ(ierr); ierr = SNESComputeFunction(snes,Y,G);CHKERRQ(ierr); /* F(X) */ ierr = VecNorm(G,NORM_2,&gnorm);CHKERRQ(ierr); /* gnorm <- || g || */ if (fnorm == gpnorm) rho = 0.0; else rho = (fnorm*fnorm - gnorm*gnorm)/(fnorm*fnorm - gpnorm*gpnorm); /* Update size of trust region */ if (rho < neP->mu) delta *= neP->delta1; else if (rho < neP->eta) delta *= neP->delta2; else delta *= neP->delta3; ierr = PetscInfo3(snes,"fnorm=%G, gnorm=%G, ynorm=%G\n",fnorm,gnorm,ynorm);CHKERRQ(ierr); ierr = PetscInfo3(snes,"gpred=%G, rho=%G, delta=%G\n",gpnorm,rho,delta);CHKERRQ(ierr); neP->delta = delta; if (rho > neP->sigma) break; ierr = PetscInfo(snes,"Trying again in smaller region\n");CHKERRQ(ierr); /* check to see if progress is hopeless */ neP->itflag = PETSC_FALSE; ierr = SNES_TR_Converged_Private(snes,snes->iter,xnorm,ynorm,fnorm,&reason,snes->cnvP);CHKERRQ(ierr); if (!reason) { ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&reason,snes->cnvP);CHKERRQ(ierr); } if (reason) { /* We're not progressing, so return with the current iterate */ ierr = SNESMonitor(snes,i+1,fnorm);CHKERRQ(ierr); breakout = PETSC_TRUE; break; } snes->numFailures++; } if (!breakout) { /* Update function and solution vectors */ fnorm = gnorm; ierr = VecCopy(G,F);CHKERRQ(ierr); ierr = VecCopy(Y,X);CHKERRQ(ierr); /* Monitor convergence */ ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); snes->iter = i+1; snes->norm = fnorm; ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); SNESLogConvHistory(snes,snes->norm,lits); ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); /* Test for convergence, xnorm = || X || */ neP->itflag = PETSC_TRUE; if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); } ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&reason,snes->cnvP);CHKERRQ(ierr); if (reason) break; } else { break; } } if (i == maxits) { ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr); if (!reason) reason = SNES_DIVERGED_MAX_IT; } ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); snes->reason = reason; ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); PetscFunctionReturn(0); }
/* SNESSolve_NEWTONTR - Implements Newton's Method with a very simple trust region approach for solving systems of nonlinear equations. */ static PetscErrorCode SNESSolve_NEWTONTR(SNES snes) { SNES_NEWTONTR *neP = (SNES_NEWTONTR*)snes->data; Vec X,F,Y,G,Ytmp; PetscErrorCode ierr; PetscInt maxits,i,lits; PetscReal rho,fnorm,gnorm,gpnorm,xnorm=0,delta,nrm,ynorm,norm1; PetscScalar cnorm; KSP ksp; SNESConvergedReason reason = SNES_CONVERGED_ITERATING; PetscBool conv = PETSC_FALSE,breakout = PETSC_FALSE; PetscFunctionBegin; if (snes->xl || snes->xu || snes->ops->computevariablebounds) SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE, "SNES solver %s does not support bounds", ((PetscObject)snes)->type_name); maxits = snes->max_its; /* maximum number of iterations */ X = snes->vec_sol; /* solution vector */ F = snes->vec_func; /* residual vector */ Y = snes->work[0]; /* work vectors */ G = snes->work[1]; Ytmp = snes->work[2]; ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); snes->iter = 0; ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); if (!snes->vec_func_init_set) { ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); /* F(X) */ } else snes->vec_func_init_set = PETSC_FALSE; ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr); /* fnorm <- || F || */ SNESCheckFunctionNorm(snes,fnorm); ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); /* fnorm <- || F || */ ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); snes->norm = fnorm; ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); delta = xnorm ? neP->delta0*xnorm : neP->delta0; neP->delta = delta; ierr = SNESLogConvergenceHistory(snes,fnorm,0);CHKERRQ(ierr); ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); /* test convergence */ ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); if (snes->reason) PetscFunctionReturn(0); /* Set the stopping criteria to use the More' trick. */ ierr = PetscOptionsGetBool(((PetscObject)snes)->options,((PetscObject)snes)->prefix,"-snes_tr_ksp_regular_convergence_test",&conv,NULL);CHKERRQ(ierr); if (!conv) { SNES_TR_KSPConverged_Ctx *ctx; ierr = SNESGetKSP(snes,&ksp);CHKERRQ(ierr); ierr = PetscNew(&ctx);CHKERRQ(ierr); ctx->snes = snes; ierr = KSPConvergedDefaultCreate(&ctx->ctx);CHKERRQ(ierr); ierr = KSPSetConvergenceTest(ksp,SNESTR_KSPConverged_Private,ctx,SNESTR_KSPConverged_Destroy);CHKERRQ(ierr); ierr = PetscInfo(snes,"Using Krylov convergence test SNESTR_KSPConverged_Private\n");CHKERRQ(ierr); } for (i=0; i<maxits; i++) { /* Call general purpose update function */ if (snes->ops->update) { ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); } /* Solve J Y = F, where J is Jacobian matrix */ ierr = SNESComputeJacobian(snes,X,snes->jacobian,snes->jacobian_pre);CHKERRQ(ierr); SNESCheckJacobianDomainerror(snes); ierr = KSPSetOperators(snes->ksp,snes->jacobian,snes->jacobian_pre);CHKERRQ(ierr); ierr = KSPSolve(snes->ksp,F,Ytmp);CHKERRQ(ierr); ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr); snes->linear_its += lits; ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr); ierr = VecNorm(Ytmp,NORM_2,&nrm);CHKERRQ(ierr); norm1 = nrm; while (1) { ierr = VecCopy(Ytmp,Y);CHKERRQ(ierr); nrm = norm1; /* Scale Y if need be and predict new value of F norm */ if (nrm >= delta) { nrm = delta/nrm; gpnorm = (1.0 - nrm)*fnorm; cnorm = nrm; ierr = PetscInfo1(snes,"Scaling direction by %g\n",(double)nrm);CHKERRQ(ierr); ierr = VecScale(Y,cnorm);CHKERRQ(ierr); nrm = gpnorm; ynorm = delta; } else { gpnorm = 0.0; ierr = PetscInfo(snes,"Direction is in Trust Region\n");CHKERRQ(ierr); ynorm = nrm; } ierr = VecAYPX(Y,-1.0,X);CHKERRQ(ierr); /* Y <- X - Y */ ierr = VecCopy(X,snes->vec_sol_update);CHKERRQ(ierr); ierr = SNESComputeFunction(snes,Y,G);CHKERRQ(ierr); /* F(X) */ ierr = VecNorm(G,NORM_2,&gnorm);CHKERRQ(ierr); /* gnorm <- || g || */ if (fnorm == gpnorm) rho = 0.0; else rho = (fnorm*fnorm - gnorm*gnorm)/(fnorm*fnorm - gpnorm*gpnorm); /* Update size of trust region */ if (rho < neP->mu) delta *= neP->delta1; else if (rho < neP->eta) delta *= neP->delta2; else delta *= neP->delta3; ierr = PetscInfo3(snes,"fnorm=%g, gnorm=%g, ynorm=%g\n",(double)fnorm,(double)gnorm,(double)ynorm);CHKERRQ(ierr); ierr = PetscInfo3(snes,"gpred=%g, rho=%g, delta=%g\n",(double)gpnorm,(double)rho,(double)delta);CHKERRQ(ierr); neP->delta = delta; if (rho > neP->sigma) break; ierr = PetscInfo(snes,"Trying again in smaller region\n");CHKERRQ(ierr); /* check to see if progress is hopeless */ neP->itflag = PETSC_FALSE; ierr = SNESTR_Converged_Private(snes,snes->iter,xnorm,ynorm,fnorm,&reason,snes->cnvP);CHKERRQ(ierr); if (!reason) { ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&reason,snes->cnvP);CHKERRQ(ierr); } if (reason) { /* We're not progressing, so return with the current iterate */ ierr = SNESMonitor(snes,i+1,fnorm);CHKERRQ(ierr); breakout = PETSC_TRUE; break; } snes->numFailures++; } if (!breakout) { /* Update function and solution vectors */ fnorm = gnorm; ierr = VecCopy(G,F);CHKERRQ(ierr); ierr = VecCopy(Y,X);CHKERRQ(ierr); /* Monitor convergence */ ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); snes->iter = i+1; snes->norm = fnorm; snes->xnorm = xnorm; snes->ynorm = ynorm; ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); ierr = SNESLogConvergenceHistory(snes,snes->norm,lits);CHKERRQ(ierr); ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); /* Test for convergence, xnorm = || X || */ neP->itflag = PETSC_TRUE; if (snes->ops->converged != SNESConvergedSkip) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); } ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&reason,snes->cnvP);CHKERRQ(ierr); if (reason) break; } else break; } if (i == maxits) { ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr); if (!reason) reason = SNES_DIVERGED_MAX_IT; } ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); snes->reason = reason; ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);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); }
void PetscNonlinearSolver<T>::init () { // Initialize the data structures if not done so already. if (!this->initialized()) { this->_is_initialized = true; PetscErrorCode ierr=0; #if PETSC_VERSION_LESS_THAN(2,1,2) // At least until Petsc 2.1.1, the SNESCreate had a different calling syntax. // The second argument was of type SNESProblemType, and could have a value of // either SNES_NONLINEAR_EQUATIONS or SNES_UNCONSTRAINED_MINIMIZATION. ierr = SNESCreate(this->comm().get(), SNES_NONLINEAR_EQUATIONS, &_snes); LIBMESH_CHKERRABORT(ierr); #else ierr = SNESCreate(this->comm().get(),&_snes); LIBMESH_CHKERRABORT(ierr); #endif #if PETSC_VERSION_LESS_THAN(2,3,3) ierr = SNESSetMonitor (_snes, __libmesh_petsc_snes_monitor, this, PETSC_NULL); #else // API name change in PETSc 2.3.3 ierr = SNESMonitorSet (_snes, __libmesh_petsc_snes_monitor, this, PETSC_NULL); #endif LIBMESH_CHKERRABORT(ierr); #if PETSC_VERSION_LESS_THAN(3,1,0) // Cannot call SNESSetOptions before SNESSetFunction when using // any matrix free options with PETSc 3.1.0+ ierr = SNESSetFromOptions(_snes); LIBMESH_CHKERRABORT(ierr); #endif if(this->_preconditioner) { KSP ksp; ierr = SNESGetKSP (_snes, &ksp); LIBMESH_CHKERRABORT(ierr); PC pc; ierr = KSPGetPC(ksp,&pc); LIBMESH_CHKERRABORT(ierr); this->_preconditioner->init(); PCSetType(pc, PCSHELL); PCShellSetContext(pc,(void*)this->_preconditioner); //Re-Use the shell functions from petsc_linear_solver PCShellSetSetUp(pc,__libmesh_petsc_preconditioner_setup); PCShellSetApply(pc,__libmesh_petsc_preconditioner_apply); } } }
int main(int argc,char **argv) { AppCtx user; /* user-defined work context */ PetscInt mx,my; PetscErrorCode ierr; MPI_Comm comm; DM da; Vec x; Mat J = NULL,Jmf = NULL; MatShellCtx matshellctx; PetscInt mlocal,nlocal; PC pc; KSP ksp; PetscBool errorinmatmult = PETSC_FALSE,errorinpcapply = PETSC_FALSE,errorinpcsetup = PETSC_FALSE; ierr = PetscInitialize(&argc,&argv,(char*)0,help);if (ierr) return(1); PetscFunctionBeginUser; ierr = PetscOptionsGetBool(NULL,"-error_in_matmult",&errorinmatmult,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetBool(NULL,"-error_in_pcapply",&errorinpcapply,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetBool(NULL,"-error_in_pcsetup",&errorinpcsetup,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetBool(NULL,"-error_in_domain",&user.errorindomain,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetBool(NULL,"-error_in_domainmf",&user.errorindomainmf,NULL);CHKERRQ(ierr); comm = PETSC_COMM_WORLD; ierr = SNESCreate(comm,&user.snes);CHKERRQ(ierr); /* Create distributed array object to manage parallel grid and vectors for principal unknowns (x) and governing residuals (f) */ ierr = DMDACreate2d(PETSC_COMM_WORLD,DM_BOUNDARY_NONE,DM_BOUNDARY_NONE,DMDA_STENCIL_STAR,-4,-4,PETSC_DECIDE,PETSC_DECIDE,4,1,0,0,&da);CHKERRQ(ierr); ierr = SNESSetDM(user.snes,da);CHKERRQ(ierr); ierr = DMDAGetInfo(da,0,&mx,&my,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE, PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE);CHKERRQ(ierr); /* Problem parameters (velocity of lid, prandtl, and grashof numbers) */ user.lidvelocity = 1.0/(mx*my); user.prandtl = 1.0; user.grashof = 1.0; ierr = PetscOptionsGetReal(NULL,"-lidvelocity",&user.lidvelocity,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetReal(NULL,"-prandtl",&user.prandtl,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetReal(NULL,"-grashof",&user.grashof,NULL);CHKERRQ(ierr); ierr = PetscOptionsHasName(NULL,"-contours",&user.draw_contours);CHKERRQ(ierr); ierr = DMDASetFieldName(da,0,"x_velocity");CHKERRQ(ierr); ierr = DMDASetFieldName(da,1,"y_velocity");CHKERRQ(ierr); ierr = DMDASetFieldName(da,2,"Omega");CHKERRQ(ierr); ierr = DMDASetFieldName(da,3,"temperature");CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create user context, set problem data, create vector data structures. Also, compute the initial guess. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create nonlinear solver context - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = DMSetApplicationContext(da,&user);CHKERRQ(ierr); ierr = DMDASNESSetFunctionLocal(da,INSERT_VALUES,(PetscErrorCode (*)(DMDALocalInfo*,void*,void*,void*))FormFunctionLocal,&user);CHKERRQ(ierr); if (errorinmatmult) { ierr = MatCreateSNESMF(user.snes,&Jmf);CHKERRQ(ierr); ierr = MatSetFromOptions(Jmf);CHKERRQ(ierr); ierr = MatGetLocalSize(Jmf,&mlocal,&nlocal);CHKERRQ(ierr); matshellctx.Jmf = Jmf; ierr = MatCreateShell(PetscObjectComm((PetscObject)Jmf),mlocal,nlocal,PETSC_DECIDE,PETSC_DECIDE,&matshellctx,&J);CHKERRQ(ierr); ierr = MatShellSetOperation(J,MATOP_MULT,(void (*)(void))MatMult_MyShell);CHKERRQ(ierr); ierr = MatShellSetOperation(J,MATOP_ASSEMBLY_END,(void (*)(void))MatAssemblyEnd_MyShell);CHKERRQ(ierr); ierr = SNESSetJacobian(user.snes,J,J,MatMFFDComputeJacobian,NULL);CHKERRQ(ierr); } ierr = SNESSetFromOptions(user.snes);CHKERRQ(ierr); ierr = PetscPrintf(comm,"lid velocity = %g, prandtl # = %g, grashof # = %g\n",(double)user.lidvelocity,(double)user.prandtl,(double)user.grashof);CHKERRQ(ierr); if (errorinpcapply) { ierr = SNESGetKSP(user.snes,&ksp);CHKERRQ(ierr); ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); ierr = PCSetType(pc,PCSHELL);CHKERRQ(ierr); ierr = PCShellSetApply(pc,PCApply_MyShell);CHKERRQ(ierr); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Solve the nonlinear system - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = DMCreateGlobalVector(da,&x);CHKERRQ(ierr); ierr = FormInitialGuess(&user,da,x);CHKERRQ(ierr); if (errorinpcsetup) { ierr = SNESSetUp(user.snes);CHKERRQ(ierr); ierr = SNESSetJacobian(user.snes,NULL,NULL,SNESComputeJacobian_MyShell,NULL);CHKERRQ(ierr); } ierr = SNESSolve(user.snes,NULL,x);CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Free work space. All PETSc objects should be destroyed when they are no longer needed. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = MatDestroy(&J);CHKERRQ(ierr); ierr = MatDestroy(&Jmf);CHKERRQ(ierr); ierr = VecDestroy(&x);CHKERRQ(ierr); ierr = DMDestroy(&da);CHKERRQ(ierr); ierr = SNESDestroy(&user.snes);CHKERRQ(ierr); ierr = PetscFinalize(); return 0; }
int main(int argc,char **argv) { DMMG *dmmg; /* multilevel grid structure */ PetscErrorCode ierr; DA da; AppCtx app; PC pc; KSP ksp; PetscTruth isshell; PetscViewer v1; PetscInitialize(&argc,&argv,(char *)0,help); PreLoadBegin(PETSC_TRUE,"SetUp"); app.comm = PETSC_COMM_WORLD; app.nxv = 6; app.nyvf = 3; app.nyv = app.nyvf + 2; ierr = PetscOptionsBegin(app.comm,PETSC_NULL,"Options for Grid Sizes",PETSC_NULL); ierr = PetscOptionsInt("-nxv","Grid spacing in X direction",PETSC_NULL,app.nxv,&app.nxv,PETSC_NULL); CHKERRQ(ierr); ierr = PetscOptionsInt("-nyvf","Grid spacing in Y direction of Fuel",PETSC_NULL,app.nyvf,&app.nyvf,PETSC_NULL); CHKERRQ(ierr); ierr = PetscOptionsInt("-nyv","Total Grid spacing in Y direction of",PETSC_NULL,app.nyv,&app.nyv,PETSC_NULL); CHKERRQ(ierr); ierr = PetscOptionsEnd(); ierr = PetscViewerDrawOpen(app.comm,PETSC_NULL,"",-1,-1,-1,-1,&v1); CHKERRQ(ierr); /* Create the DMComposite object to manage the three grids/physics. We use a 1d decomposition along the y direction (since one of the grids is 1d). */ ierr = DMCompositeCreate(app.comm,&app.pack); CHKERRQ(ierr); /* 6 fluid unknowns, 3 ghost points on each end for either periodicity or simply boundary conditions */ ierr = DACreate1d(app.comm,DA_XPERIODIC,app.nxv,6,3,0,&da); CHKERRQ(ierr); ierr = DASetFieldName(da,0,"prss"); CHKERRQ(ierr); ierr = DASetFieldName(da,1,"ergg"); CHKERRQ(ierr); ierr = DASetFieldName(da,2,"ergf"); CHKERRQ(ierr); ierr = DASetFieldName(da,3,"alfg"); CHKERRQ(ierr); ierr = DASetFieldName(da,4,"velg"); CHKERRQ(ierr); ierr = DASetFieldName(da,5,"velf"); CHKERRQ(ierr); ierr = DMCompositeAddDM(app.pack,(DM)da); CHKERRQ(ierr); ierr = DADestroy(da); CHKERRQ(ierr); ierr = DACreate2d(app.comm,DA_YPERIODIC,DA_STENCIL_STAR,app.nxv,app.nyv,PETSC_DETERMINE,1,1,1,0,0,&da); CHKERRQ(ierr); ierr = DASetFieldName(da,0,"Tempature"); CHKERRQ(ierr); ierr = DMCompositeAddDM(app.pack,(DM)da); CHKERRQ(ierr); ierr = DADestroy(da); CHKERRQ(ierr); ierr = DACreate2d(app.comm,DA_XYPERIODIC,DA_STENCIL_STAR,app.nxv,app.nyvf,PETSC_DETERMINE,1,2,1,0,0,&da); CHKERRQ(ierr); ierr = DASetFieldName(da,0,"Phi"); CHKERRQ(ierr); ierr = DASetFieldName(da,1,"Pre"); CHKERRQ(ierr); ierr = DMCompositeAddDM(app.pack,(DM)da); CHKERRQ(ierr); ierr = DADestroy(da); CHKERRQ(ierr); app.pri = 1.0135e+5; app.ugi = 2.5065e+6; app.ufi = 4.1894e+5; app.agi = 1.00e-1; app.vgi = 1.0e-1 ; app.vfi = 1.0e-1; app.prin = 1.0135e+5; app.ugin = 2.5065e+6; app.ufin = 4.1894e+5; app.agin = 1.00e-1; app.vgin = 1.0e-1 ; app.vfin = 1.0e-1; app.prout = 1.0135e+5; app.ugout = 2.5065e+6; app.ufout = 4.1894e+5; app.agout = 3.0e-1; app.twi = 373.15e+0; app.phii = 1.0e+0; app.prei = 1.0e-5; /* Create the solver object and attach the grid/physics info */ ierr = DMMGCreate(app.comm,1,0,&dmmg); CHKERRQ(ierr); ierr = DMMGSetDM(dmmg,(DM)app.pack); CHKERRQ(ierr); ierr = DMMGSetUser(dmmg,0,&app); CHKERRQ(ierr); ierr = DMMGSetISColoringType(dmmg,IS_COLORING_GLOBAL); CHKERRQ(ierr); CHKMEMQ; ierr = DMMGSetInitialGuess(dmmg,FormInitialGuess); CHKERRQ(ierr); ierr = DMMGSetSNES(dmmg,FormFunction,0); CHKERRQ(ierr); ierr = DMMGSetFromOptions(dmmg); CHKERRQ(ierr); /* Supply custom shell preconditioner if requested */ ierr = SNESGetKSP(DMMGGetSNES(dmmg),&ksp); CHKERRQ(ierr); ierr = KSPGetPC(ksp,&pc); CHKERRQ(ierr); ierr = PetscTypeCompare((PetscObject)pc,PCSHELL,&isshell); CHKERRQ(ierr); if (isshell) { ierr = PCShellSetContext(pc,&app); CHKERRQ(ierr); ierr = PCShellSetSetUp(pc,MyPCSetUp); CHKERRQ(ierr); ierr = PCShellSetApply(pc,MyPCApply); CHKERRQ(ierr); ierr = PCShellSetDestroy(pc,MyPCDestroy); CHKERRQ(ierr); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Solve the nonlinear system - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ PreLoadStage("Solve"); ierr = DMMGSolve(dmmg); CHKERRQ(ierr); ierr = VecView(DMMGGetx(dmmg),v1); CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Free work space. All PETSc objects should be destroyed when they are no longer needed. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = PetscViewerDestroy(v1); CHKERRQ(ierr); ierr = DMCompositeDestroy(app.pack); CHKERRQ(ierr); ierr = DMMGDestroy(dmmg); CHKERRQ(ierr); PreLoadEnd(); ierr = PetscFinalize(); CHKERRQ(ierr); return 0; }
int main(int argc,char **args) { Mat Amat; PetscErrorCode ierr; SNES snes; KSP ksp; MPI_Comm comm; PetscMPIInt npe,rank; PetscLogStage stage[7]; PetscBool test_nonzero_cols=PETSC_FALSE,use_nearnullspace=PETSC_TRUE; Vec xx,bb; PetscInt iter,i,N,dim=3,cells[3]={1,1,1},max_conv_its,local_sizes[7],run_type=1; DM dm,distdm,basedm; PetscBool flg; char convType[256]; PetscReal Lx,mdisp[10],err[10]; const char * const options[10] = {"-ex56_dm_refine 0", "-ex56_dm_refine 1", "-ex56_dm_refine 2", "-ex56_dm_refine 3", "-ex56_dm_refine 4", "-ex56_dm_refine 5", "-ex56_dm_refine 6", "-ex56_dm_refine 7", "-ex56_dm_refine 8", "-ex56_dm_refine 9"}; PetscFunctionBeginUser; ierr = PetscInitialize(&argc,&args,(char*)0,help);if (ierr) return ierr; comm = PETSC_COMM_WORLD; ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); ierr = MPI_Comm_size(comm, &npe);CHKERRQ(ierr); /* options */ ierr = PetscOptionsBegin(comm,NULL,"3D bilinear Q1 elasticity options","");CHKERRQ(ierr); { i = 3; ierr = PetscOptionsIntArray("-cells", "Number of (flux tube) processor in each dimension", "ex56.c", cells, &i, NULL);CHKERRQ(ierr); Lx = 1.; /* or ne for rod */ max_conv_its = 3; ierr = PetscOptionsInt("-max_conv_its","Number of iterations in convergence study","",max_conv_its,&max_conv_its,NULL);CHKERRQ(ierr); if (max_conv_its<=0 || max_conv_its>7) SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_USER, "Bad number of iterations for convergence test (%D)",max_conv_its); ierr = PetscOptionsReal("-lx","Length of domain","",Lx,&Lx,NULL);CHKERRQ(ierr); ierr = PetscOptionsReal("-alpha","material coefficient inside circle","",s_soft_alpha,&s_soft_alpha,NULL);CHKERRQ(ierr); ierr = PetscOptionsBool("-test_nonzero_cols","nonzero test","",test_nonzero_cols,&test_nonzero_cols,NULL);CHKERRQ(ierr); ierr = PetscOptionsBool("-use_mat_nearnullspace","MatNearNullSpace API test","",use_nearnullspace,&use_nearnullspace,NULL);CHKERRQ(ierr); ierr = PetscOptionsInt("-run_type","0: twisting load on cantalever, 1: 3rd order accurate convergence test","",run_type,&run_type,NULL);CHKERRQ(ierr); i = 3; ierr = PetscOptionsInt("-mat_block_size","","",i,&i,&flg);CHKERRQ(ierr); if (!flg || i!=3) SETERRQ2(PETSC_COMM_WORLD, PETSC_ERR_USER, "'-mat_block_size 3' must be set (%D) and = 3 (%D)",flg,flg? i : 3); } ierr = PetscOptionsEnd();CHKERRQ(ierr); ierr = PetscLogStageRegister("Mesh Setup", &stage[6]);CHKERRQ(ierr); ierr = PetscLogStageRegister("1st Setup", &stage[0]);CHKERRQ(ierr); ierr = PetscLogStageRegister("1st Solve", &stage[1]);CHKERRQ(ierr); /* create DM, Plex calls DMSetup */ ierr = PetscLogStagePush(stage[6]);CHKERRQ(ierr); ierr = DMPlexCreateHexBoxMesh(comm, dim, cells, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, &dm);CHKERRQ(ierr); { DMLabel label; IS is; ierr = DMCreateLabel(dm, "boundary");CHKERRQ(ierr); ierr = DMGetLabel(dm, "boundary", &label);CHKERRQ(ierr); ierr = DMPlexMarkBoundaryFaces(dm, label);CHKERRQ(ierr); if (run_type==0) { ierr = DMGetStratumIS(dm, "boundary", 1, &is);CHKERRQ(ierr); ierr = DMCreateLabel(dm,"Faces");CHKERRQ(ierr); if (is) { PetscInt d, f, Nf; const PetscInt *faces; PetscInt csize; PetscSection cs; Vec coordinates ; DM cdm; ierr = ISGetLocalSize(is, &Nf);CHKERRQ(ierr); ierr = ISGetIndices(is, &faces);CHKERRQ(ierr); ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); ierr = DMGetDefaultSection(cdm, &cs);CHKERRQ(ierr); /* Check for each boundary face if any component of its centroid is either 0.0 or 1.0 */ for (f = 0; f < Nf; ++f) { PetscReal faceCoord; PetscInt b,v; PetscScalar *coords = NULL; PetscInt Nv; ierr = DMPlexVecGetClosure(cdm, cs, coordinates, faces[f], &csize, &coords);CHKERRQ(ierr); Nv = csize/dim; /* Calculate mean coordinate vector */ for (d = 0; d < dim; ++d) { faceCoord = 0.0; for (v = 0; v < Nv; ++v) faceCoord += PetscRealPart(coords[v*dim+d]); faceCoord /= Nv; for (b = 0; b < 2; ++b) { if (PetscAbs(faceCoord - b) < PETSC_SMALL) { /* domain have not been set yet, still [0,1]^3 */ ierr = DMSetLabelValue(dm, "Faces", faces[f], d*2+b+1);CHKERRQ(ierr); } } } ierr = DMPlexVecRestoreClosure(cdm, cs, coordinates, faces[f], &csize, &coords);CHKERRQ(ierr); } ierr = ISRestoreIndices(is, &faces);CHKERRQ(ierr); } ierr = ISDestroy(&is);CHKERRQ(ierr); ierr = DMGetLabel(dm, "Faces", &label);CHKERRQ(ierr); ierr = DMPlexLabelComplete(dm, label);CHKERRQ(ierr); } } { PetscInt dimEmbed, i; PetscInt nCoords; PetscScalar *coords,bounds[] = {0,Lx,-.5,.5,-.5,.5,}; /* x_min,x_max,y_min,y_max */ Vec coordinates; if (run_type==1) { for (i = 0; i < 2*dim; i++) bounds[i] = (i%2) ? 1 : 0; } ierr = DMGetCoordinatesLocal(dm,&coordinates);CHKERRQ(ierr); ierr = DMGetCoordinateDim(dm,&dimEmbed);CHKERRQ(ierr); if (dimEmbed != dim) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"dimEmbed != dim %D",dimEmbed);CHKERRQ(ierr); ierr = VecGetLocalSize(coordinates,&nCoords);CHKERRQ(ierr); if (nCoords % dimEmbed) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Coordinate vector the wrong size");CHKERRQ(ierr); ierr = VecGetArray(coordinates,&coords);CHKERRQ(ierr); for (i = 0; i < nCoords; i += dimEmbed) { PetscInt j; PetscScalar *coord = &coords[i]; for (j = 0; j < dimEmbed; j++) { coord[j] = bounds[2 * j] + coord[j] * (bounds[2 * j + 1] - bounds[2 * j]); } } ierr = VecRestoreArray(coordinates,&coords);CHKERRQ(ierr); ierr = DMSetCoordinatesLocal(dm,coordinates);CHKERRQ(ierr); } /* convert to p4est, and distribute */ ierr = PetscOptionsBegin(comm, "", "Mesh conversion options", "DMPLEX");CHKERRQ(ierr); ierr = PetscOptionsFList("-dm_type","Convert DMPlex to another format (should not be Plex!)","ex56.c",DMList,DMPLEX,convType,256,&flg);CHKERRQ(ierr); ierr = PetscOptionsEnd(); if (flg) { DM newdm; ierr = DMConvert(dm,convType,&newdm);CHKERRQ(ierr); if (newdm) { const char *prefix; PetscBool isForest; ierr = PetscObjectGetOptionsPrefix((PetscObject)dm,&prefix);CHKERRQ(ierr); ierr = PetscObjectSetOptionsPrefix((PetscObject)newdm,prefix);CHKERRQ(ierr); ierr = DMIsForest(newdm,&isForest);CHKERRQ(ierr); if (isForest) { } else SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_USER, "Converted to non Forest?"); ierr = DMDestroy(&dm);CHKERRQ(ierr); dm = newdm; } else SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_USER, "Convert failed?"); } else { /* Plex Distribute mesh over processes */ ierr = DMPlexDistribute(dm, 0, NULL, &distdm);CHKERRQ(ierr); if (distdm) { const char *prefix; ierr = PetscObjectGetOptionsPrefix((PetscObject)dm,&prefix);CHKERRQ(ierr); ierr = PetscObjectSetOptionsPrefix((PetscObject)distdm,prefix);CHKERRQ(ierr); ierr = DMDestroy(&dm);CHKERRQ(ierr); dm = distdm; } } ierr = PetscLogStagePop();CHKERRQ(ierr); basedm = dm; dm = NULL; for (iter=0 ; iter<max_conv_its ; iter++) { ierr = PetscLogStagePush(stage[6]);CHKERRQ(ierr); /* make new DM */ ierr = DMClone(basedm, &dm);CHKERRQ(ierr); ierr = PetscObjectSetOptionsPrefix((PetscObject) dm, "ex56_");CHKERRQ(ierr); ierr = PetscObjectSetName( (PetscObject)dm,"Mesh");CHKERRQ(ierr); ierr = PetscOptionsClearValue(NULL,"-ex56_dm_refine");CHKERRQ(ierr); ierr = PetscOptionsInsertString(NULL,options[iter]);CHKERRQ(ierr); ierr = DMSetFromOptions(dm);CHKERRQ(ierr); /* refinement done here in Plex, p4est */ /* snes */ ierr = SNESCreate(comm, &snes);CHKERRQ(ierr); ierr = SNESSetDM(snes, dm);CHKERRQ(ierr); /* fem */ { const PetscInt Ncomp = dim; const PetscInt components[] = {0,1,2}; const PetscInt Nfid = 1, Npid = 1; const PetscInt fid[] = {1}; /* The fixed faces (x=0) */ const PetscInt pid[] = {2}; /* The faces with loading (x=L_x) */ PetscFE fe; PetscDS prob; DM cdm = dm; ierr = PetscFECreateDefault(dm, dim, dim, PETSC_FALSE, NULL, PETSC_DECIDE, &fe);CHKERRQ(ierr); /* elasticity */ ierr = PetscObjectSetName((PetscObject) fe, "deformation");CHKERRQ(ierr); /* FEM prob */ ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); ierr = PetscDSSetDiscretization(prob, 0, (PetscObject) fe);CHKERRQ(ierr); /* setup problem */ if (run_type==1) { ierr = PetscDSSetJacobian(prob, 0, 0, NULL, NULL, NULL, g3_uu_3d);CHKERRQ(ierr); ierr = PetscDSSetResidual(prob, 0, f0_u_x4, f1_u_3d);CHKERRQ(ierr); } else { ierr = PetscDSSetJacobian(prob, 0, 0, NULL, NULL, NULL, g3_uu_3d_alpha);CHKERRQ(ierr); ierr = PetscDSSetResidual(prob, 0, f0_u, f1_u_3d_alpha);CHKERRQ(ierr); ierr = PetscDSSetBdResidual(prob, 0, f0_bd_u_3d, f1_bd_u);CHKERRQ(ierr); } /* bcs */ if (run_type==1) { PetscInt id = 1; ierr = DMAddBoundary(dm, DM_BC_ESSENTIAL, "wall", "boundary", 0, 0, NULL, (void (*)()) zero, 1, &id, NULL);CHKERRQ(ierr); } else { ierr = PetscDSAddBoundary(prob, DM_BC_ESSENTIAL, "fixed", "Faces", 0, Ncomp, components, (void (*)()) zero, Nfid, fid, NULL);CHKERRQ(ierr); ierr = PetscDSAddBoundary(prob, DM_BC_NATURAL, "traction", "Faces", 0, Ncomp, components, NULL, Npid, pid, NULL);CHKERRQ(ierr); } while (cdm) { ierr = DMSetDS(cdm,prob);CHKERRQ(ierr); ierr = DMGetCoarseDM(cdm, &cdm);CHKERRQ(ierr); } ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); } /* vecs & mat */ ierr = DMCreateGlobalVector(dm,&xx);CHKERRQ(ierr); ierr = VecDuplicate(xx, &bb);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) bb, "b");CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) xx, "u");CHKERRQ(ierr); ierr = DMCreateMatrix(dm, &Amat);CHKERRQ(ierr); ierr = VecGetSize(bb,&N);CHKERRQ(ierr); local_sizes[iter] = N; ierr = PetscPrintf(PETSC_COMM_WORLD,"[%d]%s %d global equations, %d vertices\n",rank,PETSC_FUNCTION_NAME,N,N/dim);CHKERRQ(ierr); if (use_nearnullspace && N/dim > 1) { /* Set up the near null space (a.k.a. rigid body modes) that will be used by the multigrid preconditioner */ DM subdm; MatNullSpace nearNullSpace; PetscInt fields = 0; PetscObject deformation; ierr = DMCreateSubDM(dm, 1, &fields, NULL, &subdm);CHKERRQ(ierr); ierr = DMPlexCreateRigidBody(subdm, &nearNullSpace);CHKERRQ(ierr); ierr = DMGetField(dm, 0, &deformation);CHKERRQ(ierr); ierr = PetscObjectCompose(deformation, "nearnullspace", (PetscObject) nearNullSpace);CHKERRQ(ierr); ierr = DMDestroy(&subdm);CHKERRQ(ierr); ierr = MatNullSpaceDestroy(&nearNullSpace);CHKERRQ(ierr); /* created by DM and destroyed by Mat */ } ierr = DMPlexSetSNESLocalFEM(dm,NULL,NULL,NULL);CHKERRQ(ierr); ierr = SNESSetJacobian(snes, Amat, Amat, NULL, NULL);CHKERRQ(ierr); ierr = SNESSetFromOptions(snes);CHKERRQ(ierr); ierr = DMSetUp(dm);CHKERRQ(ierr); ierr = PetscLogStagePop();CHKERRQ(ierr); ierr = PetscLogStagePush(stage[0]);CHKERRQ(ierr); /* ksp */ ierr = SNESGetKSP(snes, &ksp);CHKERRQ(ierr); ierr = KSPSetComputeSingularValues(ksp,PETSC_TRUE);CHKERRQ(ierr); /* test BCs */ ierr = VecZeroEntries(xx);CHKERRQ(ierr); if (test_nonzero_cols) { if (rank==0) ierr = VecSetValue(xx,0,1.0,INSERT_VALUES);CHKERRQ(ierr); ierr = VecAssemblyBegin(xx);CHKERRQ(ierr); ierr = VecAssemblyEnd(xx);CHKERRQ(ierr); } ierr = VecZeroEntries(bb);CHKERRQ(ierr); ierr = VecGetSize(bb,&i);CHKERRQ(ierr); local_sizes[iter] = i; ierr = PetscPrintf(PETSC_COMM_WORLD,"[%d]%s %d equations in vector, %d vertices\n",rank,PETSC_FUNCTION_NAME,i,i/dim);CHKERRQ(ierr); /* setup solver, dummy solve to really setup */ if (0) { ierr = KSPSetTolerances(ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr); ierr = SNESSolve(snes, bb, xx);CHKERRQ(ierr); ierr = KSPSetTolerances(ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,50);CHKERRQ(ierr); ierr = VecZeroEntries(xx);CHKERRQ(ierr); } ierr = PetscLogStagePop();CHKERRQ(ierr); /* solve */ ierr = PetscLogStagePush(stage[1]);CHKERRQ(ierr); ierr = SNESSolve(snes, bb, xx);CHKERRQ(ierr); ierr = PetscLogStagePop();CHKERRQ(ierr); ierr = VecNorm(xx,NORM_INFINITY,&mdisp[iter]);CHKERRQ(ierr); ierr = DMViewFromOptions(dm, NULL, "-dm_view");CHKERRQ(ierr); { PetscViewer viewer = NULL; PetscViewerFormat fmt; ierr = PetscOptionsGetViewer(comm,"ex56_","-vec_view",&viewer,&fmt,&flg);CHKERRQ(ierr); if (flg) { ierr = PetscViewerPushFormat(viewer,fmt);CHKERRQ(ierr); ierr = VecView(xx,viewer);CHKERRQ(ierr); ierr = VecView(bb,viewer);CHKERRQ(ierr); ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); } ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); } /* Free work space */ ierr = DMDestroy(&dm);CHKERRQ(ierr); ierr = SNESDestroy(&snes);CHKERRQ(ierr); ierr = VecDestroy(&xx);CHKERRQ(ierr); ierr = VecDestroy(&bb);CHKERRQ(ierr); ierr = MatDestroy(&Amat);CHKERRQ(ierr); } ierr = DMDestroy(&basedm);CHKERRQ(ierr); if (run_type==1) { err[0] = 59.975208 - mdisp[0]; /* error with what I think is the exact solution */ } else { err[0] = 171.038 - mdisp[0]; } for (iter=1 ; iter<max_conv_its ; iter++) { if (run_type==1) { err[iter] = 59.975208 - mdisp[iter]; } else { err[iter] = 171.038 - mdisp[iter]; } PetscPrintf(PETSC_COMM_WORLD,"[%d]%s %D) N=%12D, max displ=%9.7e, disp diff=%9.2e, error=%4.3e, rate=%3.2g\n", rank,PETSC_FUNCTION_NAME,iter,local_sizes[iter],mdisp[iter], mdisp[iter]-mdisp[iter-1],err[iter],log(err[iter-1]/err[iter])/log(2.)); } ierr = PetscFinalize(); return ierr; }
void PETScNewtonKrylovSolver::initializeSolverState(const SAMRAIVectorReal<NDIM, double>& x, const SAMRAIVectorReal<NDIM, double>& b) { IBTK_TIMER_START(t_initialize_solver_state); int ierr; // Rudimentary error checking. #if !defined(NDEBUG) if (x.getNumberOfComponents() != b.getNumberOfComponents()) { TBOX_ERROR(d_object_name << "::initializeSolverState()\n" << " vectors must have the same number of components" << std::endl); } const Pointer<PatchHierarchy<NDIM> >& patch_hierarchy = x.getPatchHierarchy(); if (patch_hierarchy != b.getPatchHierarchy()) { TBOX_ERROR(d_object_name << "::initializeSolverState()\n" << " vectors must have the same hierarchy" << std::endl); } const int coarsest_ln = x.getCoarsestLevelNumber(); if (coarsest_ln < 0) { TBOX_ERROR(d_object_name << "::initializeSolverState()\n" << " coarsest level number must not be negative" << std::endl); } if (coarsest_ln != b.getCoarsestLevelNumber()) { TBOX_ERROR(d_object_name << "::initializeSolverState()\n" << " vectors must have same coarsest level number" << std::endl); } const int finest_ln = x.getFinestLevelNumber(); if (finest_ln < coarsest_ln) { TBOX_ERROR(d_object_name << "::initializeSolverState()\n" << " finest level number must be >= coarsest level number" << std::endl); } if (finest_ln != b.getFinestLevelNumber()) { TBOX_ERROR(d_object_name << "::initializeSolverState()\n" << " vectors must have same finest level number" << std::endl); } for (int ln = coarsest_ln; ln <= finest_ln; ++ln) { if (!patch_hierarchy->getPatchLevel(ln)) { TBOX_ERROR(d_object_name << "::initializeSolverState()\n" << " hierarchy level " << ln << " does not exist" << std::endl); } } #endif // Deallocate the solver state if the solver is already initialized. if (d_is_initialized) { d_reinitializing_solver = true; deallocateSolverState(); } // Create the SNES solver. if (d_managing_petsc_snes) { ierr = SNESCreate(d_petsc_comm, &d_petsc_snes); IBTK_CHKERRQ(ierr); resetSNESOptions(); } else if (!d_petsc_snes) { TBOX_ERROR(d_object_name << "::initializeSolverState()\n" << " cannot initialize solver state for wrapped PETSc SNES " "object if the wrapped object is NULL" << std::endl); } // Setup solution and rhs vectors. d_x = x.cloneVector(x.getName()); d_petsc_x = PETScSAMRAIVectorReal::createPETScVector(d_x, d_petsc_comm); d_b = b.cloneVector(b.getName()); d_petsc_b = PETScSAMRAIVectorReal::createPETScVector(d_b, d_petsc_comm); d_r = b.cloneVector(b.getName()); d_petsc_r = PETScSAMRAIVectorReal::createPETScVector(d_r, d_petsc_comm); // Setup the nonlinear operator. if (d_F) d_F->initializeOperatorState(*d_x, *d_b); if (d_managing_petsc_snes || d_user_provided_function) resetSNESFunction(); // Setup the Jacobian. if (d_J) d_J->initializeOperatorState(*d_x, *d_b); if (d_managing_petsc_snes || d_user_provided_jacobian) resetSNESJacobian(); // Set the SNES options from the PETSc options database. if (d_options_prefix != "") { ierr = SNESSetOptionsPrefix(d_petsc_snes, d_options_prefix.c_str()); IBTK_CHKERRQ(ierr); } ierr = SNESSetFromOptions(d_petsc_snes); IBTK_CHKERRQ(ierr); // Reset the member state variables to correspond to the values used by the // SNES object. (Command-line options always take precedence.) ierr = SNESGetTolerances(d_petsc_snes, &d_abs_residual_tol, &d_rel_residual_tol, &d_solution_tol, &d_max_iterations, &d_max_evaluations); IBTK_CHKERRQ(ierr); // Setup the KrylovLinearSolver wrapper to correspond to the KSP employed by // the SNES solver. KSP petsc_ksp; ierr = SNESGetKSP(d_petsc_snes, &petsc_ksp); IBTK_CHKERRQ(ierr); Pointer<PETScKrylovLinearSolver> p_krylov_solver = d_krylov_solver; if (p_krylov_solver) p_krylov_solver->resetWrappedKSP(petsc_ksp); // Setup the Krylov solver. if (d_krylov_solver) d_krylov_solver->initializeSolverState(*d_x, *d_b); // Indicate that the solver is initialized. d_reinitializing_solver = false; d_is_initialized = true; IBTK_TIMER_STOP(t_initialize_solver_state); return; } // initializeSolverState
int main(int argc,char **argv) { SNES snes; /* nonlinear solver context */ KSP ksp; /* linear solver context */ PC pc; /* preconditioner context */ Vec x,r; /* solution, residual vectors */ Mat J; /* Jacobian matrix */ PetscErrorCode ierr; PetscInt its; PetscMPIInt size,rank; PetscScalar pfive = .5,*xx; PetscBool flg; AppCtx user; /* user-defined work context */ IS isglobal,islocal; PetscInitialize(&argc,&argv,(char *)0,help); ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr); ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);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);CHKERRQ(ierr); ierr = VecSetFromOptions(x);CHKERRQ(ierr); ierr = VecDuplicate(x,&r);CHKERRQ(ierr); if (size > 1){ ierr = VecCreateSeq(PETSC_COMM_SELF,2,&user.xloc);CHKERRQ(ierr); ierr = VecDuplicate(user.xloc,&user.rloc);CHKERRQ(ierr); /* Create the scatter between the global x and local xloc */ ierr = ISCreateStride(MPI_COMM_SELF,2,0,1,&islocal);CHKERRQ(ierr); ierr = ISCreateStride(MPI_COMM_SELF,2,0,1,&isglobal);CHKERRQ(ierr); ierr = VecScatterCreate(x,isglobal,user.xloc,islocal,&user.scatter);CHKERRQ(ierr); ierr = ISDestroy(&isglobal);CHKERRQ(ierr); ierr = ISDestroy(&islocal);CHKERRQ(ierr); } /* Create Jacobian matrix data structure */ ierr = MatCreate(PETSC_COMM_WORLD,&J);CHKERRQ(ierr); ierr = MatSetSizes(J,PETSC_DECIDE,PETSC_DECIDE,2,2);CHKERRQ(ierr); ierr = MatSetFromOptions(J);CHKERRQ(ierr); ierr = MatSetUp(J);CHKERRQ(ierr); ierr = PetscOptionsHasName(PETSC_NULL,"-hard",&flg);CHKERRQ(ierr); if (!flg) { /* Set function evaluation routine and vector. */ ierr = SNESSetFunction(snes,r,FormFunction1,&user);CHKERRQ(ierr); /* Set Jacobian matrix data structure and Jacobian evaluation routine */ ierr = SNESSetJacobian(snes,J,J,FormJacobian1,PETSC_NULL);CHKERRQ(ierr); } else { if (size != 1) SETERRQ(PETSC_COMM_SELF,1,"This case is a uniprocessor example only!"); ierr = SNESSetFunction(snes,r,FormFunction2,PETSC_NULL);CHKERRQ(ierr); ierr = SNESSetJacobian(snes,J,J,FormJacobian2,PETSC_NULL);CHKERRQ(ierr); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Customize nonlinear solver; set runtime options - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* Set linear solver defaults for this problem. By extracting the KSP, KSP, and PC contexts from the SNES context, we can then directly call any KSP, KSP, and PC routines to set various options. */ ierr = SNESGetKSP(snes,&ksp);CHKERRQ(ierr); ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); ierr = PCSetType(pc,PCNONE);CHKERRQ(ierr); ierr = KSPSetTolerances(ksp,1.e-4,PETSC_DEFAULT,PETSC_DEFAULT,20);CHKERRQ(ierr); /* Set SNES/KSP/KSP/PC runtime options, e.g., -snes_view -snes_monitor -ksp_type <ksp> -pc_type <pc> These options will override those specified above as long as SNESSetFromOptions() is called _after_ any other customization routines. */ ierr = SNESSetFromOptions(snes);CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Evaluate initial guess; then solve nonlinear system - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ if (!flg) { ierr = VecSet(x,pfive);CHKERRQ(ierr); } else { ierr = VecGetArray(x,&xx);CHKERRQ(ierr); xx[0] = 2.0; xx[1] = 3.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 = SNESSolve(snes,PETSC_NULL,x);CHKERRQ(ierr); ierr = SNESGetIterationNumber(snes,&its);CHKERRQ(ierr); if (flg) { Vec f; ierr = VecView(x,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); ierr = SNESGetFunction(snes,&f,0,0);CHKERRQ(ierr); ierr = VecView(r,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); } ierr = PetscPrintf(PETSC_COMM_WORLD,"number of SNES iterations = %D\n",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(&r);CHKERRQ(ierr); ierr = MatDestroy(&J);CHKERRQ(ierr); ierr = SNESDestroy(&snes);CHKERRQ(ierr); if (size > 1){ ierr = VecDestroy(&user.xloc);CHKERRQ(ierr); ierr = VecDestroy(&user.rloc);CHKERRQ(ierr); ierr = VecScatterDestroy(&user.scatter);CHKERRQ(ierr); } ierr = PetscFinalize(); return 0; }
PetscErrorCode SNESSetUp_NASM(SNES snes) { SNES_NASM *nasm = (SNES_NASM*)snes->data; PetscErrorCode ierr; DM dm,subdm; DM *subdms; PetscInt i; const char *optionsprefix; Vec F; PetscMPIInt size; KSP ksp; PC pc; PetscFunctionBegin; if (!nasm->subsnes) { ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); if (dm) { nasm->usesdm = PETSC_TRUE; ierr = DMCreateDomainDecomposition(dm,&nasm->n,NULL,NULL,NULL,&subdms);CHKERRQ(ierr); if (!subdms) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"DM has no default decomposition defined. Set subsolves manually with SNESNASMSetSubdomains()."); ierr = DMCreateDomainDecompositionScatters(dm,nasm->n,subdms,&nasm->iscatter,&nasm->oscatter,&nasm->gscatter);CHKERRQ(ierr); ierr = SNESGetOptionsPrefix(snes, &optionsprefix);CHKERRQ(ierr); ierr = PetscMalloc(nasm->n*sizeof(SNES),&nasm->subsnes);CHKERRQ(ierr); for (i=0; i<nasm->n; i++) { ierr = SNESCreate(PETSC_COMM_SELF,&nasm->subsnes[i]);CHKERRQ(ierr); ierr = SNESAppendOptionsPrefix(nasm->subsnes[i],optionsprefix);CHKERRQ(ierr); ierr = SNESAppendOptionsPrefix(nasm->subsnes[i],"sub_");CHKERRQ(ierr); ierr = SNESSetDM(nasm->subsnes[i],subdms[i]);CHKERRQ(ierr); ierr = MPI_Comm_size(PetscObjectComm((PetscObject)nasm->subsnes[i]),&size);CHKERRQ(ierr); if (size == 1) { ierr = SNESGetKSP(nasm->subsnes[i],&ksp);CHKERRQ(ierr); ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); ierr = KSPSetType(ksp,KSPPREONLY);CHKERRQ(ierr); ierr = PCSetType(pc,PCLU);CHKERRQ(ierr); } ierr = SNESSetFromOptions(nasm->subsnes[i]);CHKERRQ(ierr); ierr = DMDestroy(&subdms[i]);CHKERRQ(ierr); } ierr = PetscFree(subdms);CHKERRQ(ierr); } else SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"Cannot construct local problems automatically without a DM!"); } else SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"Must set subproblems manually if there is no DM!"); /* allocate the global vectors */ if (!nasm->x) { ierr = PetscMalloc(nasm->n*sizeof(Vec),&nasm->x);CHKERRQ(ierr); ierr = PetscMemzero(nasm->x,nasm->n*sizeof(Vec));CHKERRQ(ierr); } if (!nasm->xl) { ierr = PetscMalloc(nasm->n*sizeof(Vec),&nasm->xl);CHKERRQ(ierr); ierr = PetscMemzero(nasm->xl,nasm->n*sizeof(Vec));CHKERRQ(ierr); } if (!nasm->y) { ierr = PetscMalloc(nasm->n*sizeof(Vec),&nasm->y);CHKERRQ(ierr); ierr = PetscMemzero(nasm->y,nasm->n*sizeof(Vec));CHKERRQ(ierr); } if (!nasm->b) { ierr = PetscMalloc(nasm->n*sizeof(Vec),&nasm->b);CHKERRQ(ierr); ierr = PetscMemzero(nasm->b,nasm->n*sizeof(Vec));CHKERRQ(ierr); } for (i=0; i<nasm->n; i++) { ierr = SNESGetFunction(nasm->subsnes[i],&F,NULL,NULL);CHKERRQ(ierr); if (!nasm->x[i]) {ierr = VecDuplicate(F,&nasm->x[i]);CHKERRQ(ierr);} if (!nasm->y[i]) {ierr = VecDuplicate(F,&nasm->y[i]);CHKERRQ(ierr);} if (!nasm->b[i]) {ierr = VecDuplicate(F,&nasm->b[i]);CHKERRQ(ierr);} if (!nasm->xl[i]) { ierr = SNESGetDM(nasm->subsnes[i],&subdm);CHKERRQ(ierr); ierr = DMCreateLocalVector(subdm,&nasm->xl[i]);CHKERRQ(ierr); } ierr = DMGlobalToLocalHookAdd(subdm,DMGlobalToLocalSubDomainDirichletHook_Private,NULL,nasm->xl[i]);CHKERRQ(ierr); } if (nasm->finaljacobian) { ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr); if (nasm->fjtype == 2) { ierr = VecDuplicate(snes->vec_sol,&nasm->xinit);CHKERRQ(ierr); } for (i=0; i<nasm->n;i++) { ierr = SNESSetUpMatrices(nasm->subsnes[i]);CHKERRQ(ierr); } } PetscFunctionReturn(0); }
static PetscErrorCode TSAdjointStep_Theta(TS ts) { TS_Theta *th = (TS_Theta*)ts->data; Vec *VecsDeltaLam = th->VecsDeltaLam,*VecsDeltaMu = th->VecsDeltaMu,*VecsSensiTemp = th->VecsSensiTemp; PetscInt nadj; PetscErrorCode ierr; Mat J,Jp; KSP ksp; PetscReal shift; PetscFunctionBegin; th->status = TS_STEP_INCOMPLETE; ierr = SNESGetKSP(ts->snes,&ksp);CHKERRQ(ierr); ierr = TSGetIJacobian(ts,&J,&Jp,NULL,NULL);CHKERRQ(ierr); /* If endpoint=1, th->ptime and th->X0 will be used; if endpoint=0, th->stage_time and th->X will be used. */ th->stage_time = ts->ptime + (th->endpoint ? ts->time_step : (1.-th->Theta)*ts->time_step); /* time_step is negative*/ th->ptime = ts->ptime + ts->time_step; /* Build RHS */ if (ts->vec_costintegral) { /* Cost function has an integral term */ if (th->endpoint) { ierr = TSAdjointComputeDRDYFunction(ts,ts->ptime,ts->vec_sol,ts->vecs_drdy);CHKERRQ(ierr); }else { ierr = TSAdjointComputeDRDYFunction(ts,th->stage_time,th->X,ts->vecs_drdy);CHKERRQ(ierr); } } for (nadj=0; nadj<ts->numcost; nadj++) { ierr = VecCopy(ts->vecs_sensi[nadj],VecsSensiTemp[nadj]);CHKERRQ(ierr); ierr = VecScale(VecsSensiTemp[nadj],-1./(th->Theta*ts->time_step));CHKERRQ(ierr); if (ts->vec_costintegral) { ierr = VecAXPY(VecsSensiTemp[nadj],1.,ts->vecs_drdy[nadj]);CHKERRQ(ierr); } } /* Build LHS */ shift = -1./(th->Theta*ts->time_step); if (th->endpoint) { ierr = TSComputeIJacobian(ts,ts->ptime,ts->vec_sol,th->Xdot,shift,J,Jp,PETSC_FALSE);CHKERRQ(ierr); }else { ierr = TSComputeIJacobian(ts,th->stage_time,th->X,th->Xdot,shift,J,Jp,PETSC_FALSE);CHKERRQ(ierr); } ierr = KSPSetOperators(ksp,J,Jp);CHKERRQ(ierr); /* Solve LHS X = RHS */ for (nadj=0; nadj<ts->numcost; nadj++) { ierr = KSPSolveTranspose(ksp,VecsSensiTemp[nadj],VecsDeltaLam[nadj]);CHKERRQ(ierr); } /* Update sensitivities, and evaluate integrals if there is any */ if(th->endpoint) { /* two-stage case */ if (th->Theta!=1.) { shift = -1./((th->Theta-1.)*ts->time_step); ierr = TSComputeIJacobian(ts,th->ptime,th->X0,th->Xdot,shift,J,Jp,PETSC_FALSE);CHKERRQ(ierr); if (ts->vec_costintegral) { ierr = TSAdjointComputeDRDYFunction(ts,th->ptime,th->X0,ts->vecs_drdy);CHKERRQ(ierr); } for (nadj=0; nadj<ts->numcost; nadj++) { ierr = MatMultTranspose(J,VecsDeltaLam[nadj],ts->vecs_sensi[nadj]);CHKERRQ(ierr); if (ts->vec_costintegral) { ierr = VecAXPY(ts->vecs_sensi[nadj],-1.,ts->vecs_drdy[nadj]);CHKERRQ(ierr); } ierr = VecScale(ts->vecs_sensi[nadj],1./shift);CHKERRQ(ierr); } }else { /* backward Euler */ shift = 0.0; ierr = TSComputeIJacobian(ts,ts->ptime,ts->vec_sol,th->Xdot,shift,J,Jp,PETSC_FALSE);CHKERRQ(ierr); /* get -f_y */ for (nadj=0; nadj<ts->numcost; nadj++) { ierr = MatMultTranspose(J,VecsDeltaLam[nadj],VecsSensiTemp[nadj]);CHKERRQ(ierr); ierr = VecAXPY(ts->vecs_sensi[nadj],ts->time_step,VecsSensiTemp[nadj]);CHKERRQ(ierr); if (ts->vec_costintegral) { ierr = VecAXPY(ts->vecs_sensi[nadj],-ts->time_step,ts->vecs_drdy[nadj]);CHKERRQ(ierr); } } } if (ts->vecs_sensip) { /* sensitivities wrt parameters */ ierr = TSAdjointComputeRHSJacobian(ts,ts->ptime,ts->vec_sol,ts->Jacp);CHKERRQ(ierr); for (nadj=0; nadj<ts->numcost; nadj++) { ierr = MatMultTranspose(ts->Jacp,VecsDeltaLam[nadj],VecsDeltaMu[nadj]);CHKERRQ(ierr); ierr = VecAXPY(ts->vecs_sensip[nadj],-ts->time_step*th->Theta,VecsDeltaMu[nadj]);CHKERRQ(ierr); } if (th->Theta!=1.) { ierr = TSAdjointComputeRHSJacobian(ts,th->ptime,th->X0,ts->Jacp);CHKERRQ(ierr); for (nadj=0; nadj<ts->numcost; nadj++) { ierr = MatMultTranspose(ts->Jacp,VecsDeltaLam[nadj],VecsDeltaMu[nadj]);CHKERRQ(ierr); ierr = VecAXPY(ts->vecs_sensip[nadj],-ts->time_step*(1.-th->Theta),VecsDeltaMu[nadj]);CHKERRQ(ierr); } } if (ts->vec_costintegral) { ierr = TSAdjointComputeDRDPFunction(ts,ts->ptime,ts->vec_sol,ts->vecs_drdp);CHKERRQ(ierr); for (nadj=0; nadj<ts->numcost; nadj++) { ierr = VecAXPY(ts->vecs_sensip[nadj],-ts->time_step*th->Theta,ts->vecs_drdp[nadj]);CHKERRQ(ierr); } if (th->Theta!=1.) { ierr = TSAdjointComputeDRDPFunction(ts,th->ptime,th->X0,ts->vecs_drdp);CHKERRQ(ierr); for (nadj=0; nadj<ts->numcost; nadj++) { ierr = VecAXPY(ts->vecs_sensip[nadj],-ts->time_step*(1.-th->Theta),ts->vecs_drdp[nadj]);CHKERRQ(ierr); } } } } }else { /* one-stage case */ shift = 0.0; ierr = TSComputeIJacobian(ts,th->stage_time,th->X,th->Xdot,shift,J,Jp,PETSC_FALSE);CHKERRQ(ierr); /* get -f_y */ if (ts->vec_costintegral) { ierr = TSAdjointComputeDRDYFunction(ts,th->stage_time,th->X,ts->vecs_drdy);CHKERRQ(ierr); } for (nadj=0; nadj<ts->numcost; nadj++) { ierr = MatMultTranspose(J,VecsDeltaLam[nadj],VecsSensiTemp[nadj]);CHKERRQ(ierr); ierr = VecAXPY(ts->vecs_sensi[nadj],ts->time_step,VecsSensiTemp[nadj]);CHKERRQ(ierr); if (ts->vec_costintegral) { ierr = VecAXPY(ts->vecs_sensi[nadj],-ts->time_step,ts->vecs_drdy[nadj]);CHKERRQ(ierr); } } if (ts->vecs_sensip) { ierr = TSAdjointComputeRHSJacobian(ts,th->stage_time,th->X,ts->Jacp);CHKERRQ(ierr); for (nadj=0; nadj<ts->numcost; nadj++) { ierr = MatMultTranspose(ts->Jacp,VecsDeltaLam[nadj],VecsDeltaMu[nadj]);CHKERRQ(ierr); ierr = VecAXPY(ts->vecs_sensip[nadj],-ts->time_step,VecsDeltaMu[nadj]);CHKERRQ(ierr); } if (ts->vec_costintegral) { ierr = TSAdjointComputeDRDPFunction(ts,th->stage_time,th->X,ts->vecs_drdp);CHKERRQ(ierr); for (nadj=0; nadj<ts->numcost; nadj++) { ierr = VecAXPY(ts->vecs_sensip[nadj],-ts->time_step,ts->vecs_drdp[nadj]);CHKERRQ(ierr); } } } } th->status = TS_STEP_COMPLETE; PetscFunctionReturn(0); }
int main(int argc,char **argv) { PetscErrorCode ierr; PetscBool view = PETSC_FALSE, viewsoln = PETSC_FALSE, noprealloc = PETSC_FALSE; char root[256] = "", nodesname[256], issname[256], solnname[256]; UM mesh; unfemCtx user; SNES snes; KSP ksp; PC pc; Mat A; Vec r, u, uexact; double err, h_max; PetscInitialize(&argc,&argv,NULL,help); ierr = PetscLogStageRegister("Read mesh ", &user.readstage); CHKERRQ(ierr); //STRIP ierr = PetscLogStageRegister("Set-up ", &user.setupstage); CHKERRQ(ierr); //STRIP ierr = PetscLogStageRegister("Solver ", &user.solverstage); CHKERRQ(ierr); //STRIP ierr = PetscLogStageRegister("Residual eval ", &user.resstage); CHKERRQ(ierr); //STRIP ierr = PetscLogStageRegister("Jacobian eval ", &user.jacstage); CHKERRQ(ierr); //STRIP user.quaddeg = 1; user.solncase = 0; ierr = PetscOptionsBegin(PETSC_COMM_WORLD, "un_", "options for unfem", ""); CHKERRQ(ierr); ierr = PetscOptionsInt("-case", "exact solution cases: 0=linear, 1=nonlinear, 2=nonhomoNeumann, 3=chapter3, 4=koch", "unfem.c",user.solncase,&(user.solncase),NULL); CHKERRQ(ierr); ierr = PetscOptionsString("-mesh", "file name root of mesh stored in PETSc binary with .vec,.is extensions", "unfem.c",root,root,sizeof(root),NULL); CHKERRQ(ierr); ierr = PetscOptionsInt("-quaddeg", "quadrature degree (1,2,3)", "unfem.c",user.quaddeg,&(user.quaddeg),NULL); CHKERRQ(ierr); ierr = PetscOptionsBool("-view", "view loaded nodes and elements at stdout", "unfem.c",view,&view,NULL); CHKERRQ(ierr); ierr = PetscOptionsBool("-view_solution", "view solution u(x,y) to binary file; uses root name of mesh plus .soln\nsee petsc2tricontour.py to view graphically", "unfem.c",viewsoln,&viewsoln,NULL); CHKERRQ(ierr); ierr = PetscOptionsBool("-noprealloc", "do not perform preallocation before matrix assembly", "unfem.c",noprealloc,&noprealloc,NULL); CHKERRQ(ierr); ierr = PetscOptionsEnd(); CHKERRQ(ierr); // set parameters and exact solution user.a_fcn = &a_lin; user.f_fcn = &f_lin; user.uexact_fcn = &uexact_lin; user.gD_fcn = &gD_lin; user.gN_fcn = &gN_lin; switch (user.solncase) { case 0 : break; case 1 : user.a_fcn = &a_nonlin; user.f_fcn = &f_nonlin; break; case 2 : user.gN_fcn = &gN_linneu; break; case 3 : user.a_fcn = &a_square; user.f_fcn = &f_square; user.uexact_fcn = &uexact_square; user.gD_fcn = &gD_square; user.gN_fcn = NULL; // seg fault if ever called break; case 4 : user.a_fcn = &a_koch; user.f_fcn = &f_koch; user.uexact_fcn = NULL; user.gD_fcn = &gD_koch; user.gN_fcn = NULL; // seg fault if ever called break; default : SETERRQ(PETSC_COMM_WORLD,1,"other solution cases not implemented"); } // determine filenames strcpy(nodesname, root); strncat(nodesname, ".vec", 4); strcpy(issname, root); strncat(issname, ".is", 3); //STARTMAININITIAL PetscLogStagePush(user.readstage); //STRIP // read mesh object of type UM ierr = UMInitialize(&mesh); CHKERRQ(ierr); ierr = UMReadNodes(&mesh,nodesname); CHKERRQ(ierr); ierr = UMReadISs(&mesh,issname); CHKERRQ(ierr); ierr = UMStats(&mesh, &h_max, NULL, NULL, NULL); CHKERRQ(ierr); if (view) { //STRIP PetscViewer stdoutviewer; //STRIP ierr = PetscViewerASCIIGetStdout(PETSC_COMM_WORLD,&stdoutviewer); CHKERRQ(ierr); //STRIP ierr = UMViewASCII(&mesh,stdoutviewer); CHKERRQ(ierr); //STRIP } //STRIP user.mesh = &mesh; PetscLogStagePop(); //STRIP // configure Vecs and SNES PetscLogStagePush(user.setupstage); //STRIP ierr = VecCreate(PETSC_COMM_WORLD,&r); CHKERRQ(ierr); ierr = VecSetSizes(r,PETSC_DECIDE,mesh.N); CHKERRQ(ierr); ierr = VecSetFromOptions(r); CHKERRQ(ierr); ierr = VecDuplicate(r,&u); CHKERRQ(ierr); ierr = VecSet(u,0.0); CHKERRQ(ierr); ierr = SNESCreate(PETSC_COMM_WORLD,&snes); CHKERRQ(ierr); ierr = SNESSetFunction(snes,r,FormFunction,&user); CHKERRQ(ierr); // reset default KSP and PC ierr = SNESGetKSP(snes,&ksp); CHKERRQ(ierr); ierr = KSPSetType(ksp,KSPCG); CHKERRQ(ierr); ierr = KSPGetPC(ksp,&pc); CHKERRQ(ierr); ierr = PCSetType(pc,PCICC); CHKERRQ(ierr); // setup matrix for Picard iteration, including preallocation ierr = MatCreate(PETSC_COMM_WORLD,&A); CHKERRQ(ierr); ierr = MatSetSizes(A,PETSC_DECIDE,PETSC_DECIDE,mesh.N,mesh.N); CHKERRQ(ierr); ierr = MatSetFromOptions(A); CHKERRQ(ierr); ierr = MatSetOption(A,MAT_SYMMETRIC,PETSC_TRUE); CHKERRQ(ierr); if (noprealloc) { ierr = MatSetUp(A); CHKERRQ(ierr); } else { ierr = Preallocation(A,&user); CHKERRQ(ierr); } ierr = SNESSetJacobian(snes,A,A,FormPicard,&user); CHKERRQ(ierr); ierr = SNESSetFromOptions(snes); CHKERRQ(ierr); PetscLogStagePop(); //STRIP // solve PetscLogStagePush(user.solverstage); //STRIP ierr = SNESSolve(snes,NULL,u);CHKERRQ(ierr); PetscLogStagePop(); //STRIP //ENDMAININITIAL if (viewsoln) { strcpy(solnname, root); strncat(solnname, ".soln", 5); ierr = UMViewSolutionBinary(&mesh,solnname,u); CHKERRQ(ierr); } if (user.uexact_fcn) { // measure error relative to exact solution ierr = VecDuplicate(r,&uexact); CHKERRQ(ierr); ierr = FillExact(uexact,&user); CHKERRQ(ierr); ierr = VecAXPY(u,-1.0,uexact); CHKERRQ(ierr); // u <- u + (-1.0) uexact ierr = VecNorm(u,NORM_INFINITY,&err); CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD, "case %d result for N=%d nodes with h = %.3e : |u-u_ex|_inf = %g\n", user.solncase,mesh.N,h_max,err); CHKERRQ(ierr); VecDestroy(&uexact); } else { ierr = PetscPrintf(PETSC_COMM_WORLD, "case %d completed for N=%d nodes with h = %.3e (no exact solution)\n", user.solncase,mesh.N,h_max); CHKERRQ(ierr); } // clean-up SNESDestroy(&snes); MatDestroy(&A); VecDestroy(&u); VecDestroy(&r); UMDestroy(&mesh); PetscFinalize(); return 0; }
/*@ PetscConvEstGetConvRate - Returns an estimate of the convergence rate for the discretization Not collective Input Parameter: . ce - The PetscConvEst object Output Parameter: . alpha - The convergence rate for each field Note: The convergence rate alpha is defined by $ || u_h - u_exact || < C h^alpha where u_h is the discrete solution, and h is a measure of the discretization size. We solve a series of problems on refined meshes, calculate an error based upon the exact solution in the DS, and then fit the result to our model above using linear regression. Options database keys: . -snes_convergence_estimate : Execute convergence estimation and print out the rate Level: intermediate .keywords: PetscConvEst, convergence .seealso: PetscConvEstSetSolver(), PetscConvEstCreate(), PetscConvEstGetConvRate() @*/ PetscErrorCode PetscConvEstGetConvRate(PetscConvEst ce, PetscReal alpha[]) { DM *dm; PetscObject disc; MPI_Comm comm; const char *uname, *dmname; void *ctx; Vec u; PetscReal t = 0.0, *x, *y, slope, intercept; PetscInt *dof, dim, Nr = ce->Nr, r, f, oldlevel, oldnlev; PetscLogEvent event; PetscErrorCode ierr; PetscFunctionBegin; ierr = PetscObjectGetComm((PetscObject) ce, &comm);CHKERRQ(ierr); ierr = DMGetDimension(ce->idm, &dim);CHKERRQ(ierr); ierr = DMGetApplicationContext(ce->idm, &ctx);CHKERRQ(ierr); ierr = DMPlexSetRefinementUniform(ce->idm, PETSC_TRUE);CHKERRQ(ierr); ierr = DMGetRefineLevel(ce->idm, &oldlevel);CHKERRQ(ierr); ierr = PetscMalloc2((Nr+1), &dm, (Nr+1)*ce->Nf, &dof);CHKERRQ(ierr); dm[0] = ce->idm; for (f = 0; f < ce->Nf; ++f) alpha[f] = 0.0; /* Loop over meshes */ ierr = PetscLogEventRegister("ConvEst Error", PETSC_OBJECT_CLASSID, &event);CHKERRQ(ierr); for (r = 0; r <= Nr; ++r) { PetscLogStage stage; char stageName[PETSC_MAX_PATH_LEN]; ierr = PetscSNPrintf(stageName, PETSC_MAX_PATH_LEN-1, "ConvEst Refinement Level %D", r);CHKERRQ(ierr); ierr = PetscLogStageRegister(stageName, &stage);CHKERRQ(ierr); ierr = PetscLogStagePush(stage);CHKERRQ(ierr); if (r > 0) { ierr = DMRefine(dm[r-1], MPI_COMM_NULL, &dm[r]);CHKERRQ(ierr); ierr = DMSetCoarseDM(dm[r], dm[r-1]);CHKERRQ(ierr); ierr = DMCopyDisc(ce->idm, dm[r]);CHKERRQ(ierr); ierr = DMCopyTransform(ce->idm, dm[r]);CHKERRQ(ierr); ierr = PetscObjectGetName((PetscObject) dm[r-1], &dmname);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) dm[r], dmname);CHKERRQ(ierr); for (f = 0; f <= ce->Nf; ++f) { PetscErrorCode (*nspconstr)(DM, PetscInt, MatNullSpace *); ierr = DMGetNullSpaceConstructor(dm[r-1], f, &nspconstr);CHKERRQ(ierr); ierr = DMSetNullSpaceConstructor(dm[r], f, nspconstr);CHKERRQ(ierr); } } ierr = DMViewFromOptions(dm[r], NULL, "-conv_dm_view");CHKERRQ(ierr); /* Create solution */ ierr = DMCreateGlobalVector(dm[r], &u);CHKERRQ(ierr); ierr = DMGetField(dm[r], 0, NULL, &disc);CHKERRQ(ierr); ierr = PetscObjectGetName(disc, &uname);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) u, uname);CHKERRQ(ierr); /* Setup solver */ ierr = SNESReset(ce->snes);CHKERRQ(ierr); ierr = SNESSetDM(ce->snes, dm[r]);CHKERRQ(ierr); ierr = DMPlexSetSNESLocalFEM(dm[r], ctx, ctx, ctx);CHKERRQ(ierr); ierr = SNESSetFromOptions(ce->snes);CHKERRQ(ierr); /* Create initial guess */ ierr = DMProjectFunction(dm[r], t, ce->initGuess, ce->ctxs, INSERT_VALUES, u);CHKERRQ(ierr); ierr = SNESSolve(ce->snes, NULL, u);CHKERRQ(ierr); ierr = PetscLogEventBegin(event, ce, 0, 0, 0);CHKERRQ(ierr); ierr = DMComputeL2FieldDiff(dm[r], t, ce->exactSol, ce->ctxs, u, &ce->errors[r*ce->Nf]);CHKERRQ(ierr); ierr = PetscLogEventEnd(event, ce, 0, 0, 0);CHKERRQ(ierr); for (f = 0; f < ce->Nf; ++f) { PetscSection s, fs; PetscInt lsize; /* Could use DMGetOutputDM() to add in Dirichlet dofs */ ierr = DMGetSection(dm[r], &s);CHKERRQ(ierr); ierr = PetscSectionGetField(s, f, &fs);CHKERRQ(ierr); ierr = PetscSectionGetConstrainedStorageSize(fs, &lsize);CHKERRQ(ierr); ierr = MPI_Allreduce(&lsize, &dof[r*ce->Nf+f], 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) ce->snes));CHKERRQ(ierr); ierr = PetscLogEventSetDof(event, f, dof[r*ce->Nf+f]);CHKERRQ(ierr); ierr = PetscLogEventSetError(event, f, ce->errors[r*ce->Nf+f]);CHKERRQ(ierr); } /* Monitor */ if (ce->monitor) { PetscReal *errors = &ce->errors[r*ce->Nf]; ierr = PetscPrintf(comm, "L_2 Error: ");CHKERRQ(ierr); if (ce->Nf > 1) {ierr = PetscPrintf(comm, "[");CHKERRQ(ierr);} for (f = 0; f < ce->Nf; ++f) { if (f > 0) {ierr = PetscPrintf(comm, ", ");CHKERRQ(ierr);} if (errors[f] < 1.0e-11) {ierr = PetscPrintf(comm, "< 1e-11");CHKERRQ(ierr);} else {ierr = PetscPrintf(comm, "%g", (double)errors[f]);CHKERRQ(ierr);} } if (ce->Nf > 1) {ierr = PetscPrintf(comm, "]");CHKERRQ(ierr);} ierr = PetscPrintf(comm, "\n");CHKERRQ(ierr); } if (!r) { /* PCReset() does not wipe out the level structure */ KSP ksp; PC pc; ierr = SNESGetKSP(ce->snes, &ksp);CHKERRQ(ierr); ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr); ierr = PCMGGetLevels(pc, &oldnlev);CHKERRQ(ierr); } /* Cleanup */ ierr = VecDestroy(&u);CHKERRQ(ierr); ierr = PetscLogStagePop();CHKERRQ(ierr); } for (r = 1; r <= Nr; ++r) { ierr = DMDestroy(&dm[r]);CHKERRQ(ierr); } /* Fit convergence rate */ ierr = PetscMalloc2(Nr+1, &x, Nr+1, &y);CHKERRQ(ierr); for (f = 0; f < ce->Nf; ++f) { for (r = 0; r <= Nr; ++r) { x[r] = PetscLog10Real(dof[r*ce->Nf+f]); y[r] = PetscLog10Real(ce->errors[r*ce->Nf+f]); } ierr = PetscLinearRegression(Nr+1, x, y, &slope, &intercept);CHKERRQ(ierr); /* Since h^{-dim} = N, lg err = s lg N + b = -s dim lg h + b */ alpha[f] = -slope * dim; } ierr = PetscFree2(x, y);CHKERRQ(ierr); ierr = PetscFree2(dm, dof);CHKERRQ(ierr); /* Restore solver */ ierr = SNESReset(ce->snes);CHKERRQ(ierr); { /* PCReset() does not wipe out the level structure */ KSP ksp; PC pc; ierr = SNESGetKSP(ce->snes, &ksp);CHKERRQ(ierr); ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr); ierr = PCMGSetLevels(pc, oldnlev, NULL);CHKERRQ(ierr); ierr = DMSetRefineLevel(ce->idm, oldlevel);CHKERRQ(ierr); /* The damn DMCoarsen() calls in PCMG can reset this */ } ierr = SNESSetDM(ce->snes, ce->idm);CHKERRQ(ierr); ierr = DMPlexSetSNESLocalFEM(ce->idm, ctx, ctx, ctx);CHKERRQ(ierr); ierr = SNESSetFromOptions(ce->snes);CHKERRQ(ierr); PetscFunctionReturn(0); }