int main(int argc, char** argv) { PetscInitialize( &argc, &argv, (char *)0, 0 ) ; int ncpus; MPI_Comm_size(PETSC_COMM_WORLD,&ncpus); if (ncpus > 1) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP, "Example is only for sequential runs"); Vec x, r; VecCreate(PETSC_COMM_WORLD, &x); VecSetSizes(x, PETSC_DECIDE, 2); VecSetFromOptions(x); VecDuplicate(x, &r); Mat J; MatCreate(PETSC_COMM_WORLD, &J); MatSetSizes(J, PETSC_DECIDE, PETSC_DECIDE, 2, 2); MatSetFromOptions(J); MatSetUp(J); SNES snes; SNESCreate(PETSC_COMM_WORLD, &snes); SNESSetFunction(snes, r, CalculateFunc, NULL); SNESSetJacobian(snes, J, J, CalculateJacobian, NULL); SNESSetFromOptions(snes); VecSet(x, 1.0); SNESSolve(snes, NULL, x); VecView(x,PETSC_VIEWER_STDOUT_WORLD); SNESGetFunction(snes,&r,0,0); VecView(r,PETSC_VIEWER_STDOUT_WORLD); SNESDestroy(&snes); MatDestroy(&J); VecDestroy(&r); VecDestroy(&x); PetscFinalize(); return 0; }
PetscErrorCode Monitor(SNES snes,PetscInt its,PetscReal rnorm,void *dummy) { UserCtx *user = (UserCtx*)dummy; PetscErrorCode ierr; Vec w,u,lambda,U,F; PetscFunctionBeginUser; ierr = SNESGetSolution(snes,&U);CHKERRQ(ierr); ierr = DMCompositeGetAccess(user->packer,U,&w,&u,&lambda);CHKERRQ(ierr); ierr = VecView(u,user->u_viewer);CHKERRQ(ierr); ierr = VecView(lambda,user->lambda_viewer);CHKERRQ(ierr); ierr = DMCompositeRestoreAccess(user->packer,U,&w,&u,&lambda);CHKERRQ(ierr); ierr = SNESGetFunction(snes,&F,0,0);CHKERRQ(ierr); ierr = DMCompositeGetAccess(user->packer,F,&w,&u,&lambda);CHKERRQ(ierr); ierr = VecView(u,user->fu_viewer);CHKERRQ(ierr); ierr = VecView(lambda,user->flambda_viewer);CHKERRQ(ierr); ierr = DMCompositeRestoreAccess(user->packer,F,&w,&u,&lambda);CHKERRQ(ierr); PetscFunctionReturn(0); }
/* Defines the action of the upsmoother */ PetscErrorCode SNESFASUpSmooth_Private (SNES snes, Vec B, Vec X, Vec F, PetscReal *fnorm) { PetscErrorCode ierr = 0; SNESConvergedReason reason; Vec FPC; SNES smoothu; PetscFunctionBegin; ierr = SNESFASCycleGetSmootherUp(snes, &smoothu);CHKERRQ(ierr); ierr = SNESSolve(smoothu, B, X);CHKERRQ(ierr); /* check convergence reason for the smoother */ ierr = SNESGetConvergedReason(smoothu,&reason);CHKERRQ(ierr); if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } ierr = SNESGetFunction(smoothu, &FPC, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); ierr = VecCopy(FPC, F);CHKERRQ(ierr); ierr = SNESGetFunctionNorm(smoothu, fnorm);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*MC SNESASPIN - Helper SNES type for Additive-Schwarz Preconditioned Inexact Newton Options Database: + -npc_snes_ - options prefix of the nonlinear subdomain solver (must be of type NASM) . -npc_sub_snes_ - options prefix of the subdomain nonlinear solves . -npc_sub_ksp_ - options prefix of the subdomain Krylov solver - -npc_sub_pc_ - options prefix of the subdomain preconditioner Notes: This routine sets up an instance of NETWONLS with nonlinear left preconditioning. It differs from other similar functionality in SNES as it creates a linear shell matrix that corresponds to the product: \sum_{i=0}^{N_b}J_b({X^b_{converged}})^{-1}J(X + \sum_{i=0}^{N_b}(X^b_{converged} - X^b)) which is the ASPIN preconditioned matrix. Similar solvers may be constructed by having matrix-free differencing of nonlinear solves per linear iteration, but this is far more efficient when subdomain sparse-direct preconditioner factorizations are reused on each application of J_b^{-1}. Level: intermediate .seealso: SNESCreate(), SNES, SNESSetType(), SNESNEWTONLS, SNESNASM, SNESGetNPC(), SNESGetNPCSide() M*/ PETSC_EXTERN PetscErrorCode SNESCreate_ASPIN(SNES snes) { PetscErrorCode ierr; SNES npc; KSP ksp; PC pc; Mat aspinmat; MPI_Comm comm; Vec F; PetscInt n; SNESLineSearch linesearch; PetscFunctionBegin; /* set up the solver */ ierr = SNESSetType(snes,SNESNEWTONLS);CHKERRQ(ierr); ierr = SNESSetNPCSide(snes,PC_LEFT);CHKERRQ(ierr); ierr = SNESSetFunctionType(snes,SNES_FUNCTION_PRECONDITIONED);CHKERRQ(ierr); ierr = SNESGetNPC(snes,&npc);CHKERRQ(ierr); ierr = SNESSetType(npc,SNESNASM);CHKERRQ(ierr); ierr = SNESNASMSetType(npc,PC_ASM_BASIC);CHKERRQ(ierr); ierr = SNESNASMSetComputeFinalJacobian(npc,PETSC_TRUE);CHKERRQ(ierr); ierr = SNESGetKSP(snes,&ksp);CHKERRQ(ierr); ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); ierr = PCSetType(pc,PCNONE);CHKERRQ(ierr); ierr = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr); ierr = SNESGetLineSearch(snes,&linesearch);CHKERRQ(ierr); ierr = SNESLineSearchSetType(linesearch,SNESLINESEARCHBT);CHKERRQ(ierr); /* set up the shell matrix */ ierr = SNESGetFunction(snes,&F,NULL,NULL);CHKERRQ(ierr); ierr = VecGetLocalSize(F,&n);CHKERRQ(ierr); ierr = MatCreateShell(comm,n,n,PETSC_DECIDE,PETSC_DECIDE,snes,&aspinmat);CHKERRQ(ierr); ierr = MatSetType(aspinmat,MATSHELL);CHKERRQ(ierr); ierr = MatShellSetOperation(aspinmat,MATOP_MULT,(void(*)(void))MatMultASPIN);CHKERRQ(ierr); ierr = SNESSetJacobian(snes,aspinmat,NULL,NULL,NULL);CHKERRQ(ierr); ierr = MatDestroy(&aspinmat);CHKERRQ(ierr); PetscFunctionReturn(0); }
/* Defines the action of the downsmoother */ PetscErrorCode SNESFASDownSmooth_Private(SNES snes, Vec B, Vec X, Vec F, PetscReal *fnorm) { PetscErrorCode ierr = 0; SNESConvergedReason reason; Vec FPC; SNES smoothd; PetscFunctionBegin; ierr = SNESFASCycleGetSmootherDown(snes, &smoothd);CHKERRQ(ierr); ierr = SNESSetInitialFunction(smoothd, F);CHKERRQ(ierr); ierr = SNESSetInitialFunctionNorm(smoothd, *fnorm);CHKERRQ(ierr); ierr = SNESSolve(smoothd, B, X);CHKERRQ(ierr); /* check convergence reason for the smoother */ ierr = SNESGetConvergedReason(smoothd,&reason);CHKERRQ(ierr); if (reason < 0 && !(reason == SNES_DIVERGED_MAX_IT || reason == SNES_DIVERGED_LOCAL_MIN)) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } ierr = SNESGetFunction(smoothd, &FPC, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); ierr = VecCopy(FPC, F);CHKERRQ(ierr); ierr = SNESGetFunctionNorm(smoothd, fnorm);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode Monitor(SNES snes,PetscInt its,PetscReal rnorm,void *dummy) { UserCtx *user; PetscErrorCode ierr; PetscInt m,N; PetscScalar *w,*dw; Vec u_lambda,U,F,Uexact; DM packer; PetscReal norm; DM da; PetscFunctionBeginUser; ierr = SNESGetDM(snes,&packer);CHKERRQ(ierr); ierr = DMGetApplicationContext(packer,&user);CHKERRQ(ierr); ierr = SNESGetSolution(snes,&U);CHKERRQ(ierr); ierr = DMCompositeGetAccess(packer,U,&w,&u_lambda);CHKERRQ(ierr); ierr = VecView(u_lambda,user->u_lambda_viewer);CHKERRQ(ierr); ierr = DMCompositeRestoreAccess(packer,U,&w,&u_lambda);CHKERRQ(ierr); ierr = SNESGetFunction(snes,&F,0,0);CHKERRQ(ierr); ierr = DMCompositeGetAccess(packer,F,&w,&u_lambda);CHKERRQ(ierr); /* ierr = VecView(u_lambda,user->fu_lambda_viewer); */ ierr = DMCompositeRestoreAccess(packer,U,&w,&u_lambda);CHKERRQ(ierr); ierr = DMCompositeGetEntries(packer,&m,&da);CHKERRQ(ierr); ierr = DMDAGetInfo(da,0,&N,0,0,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr); ierr = VecDuplicate(U,&Uexact);CHKERRQ(ierr); ierr = ExactSolution(packer,Uexact);CHKERRQ(ierr); ierr = VecAXPY(Uexact,-1.0,U);CHKERRQ(ierr); ierr = DMCompositeGetAccess(packer,Uexact,&dw,&u_lambda);CHKERRQ(ierr); ierr = VecStrideNorm(u_lambda,0,NORM_2,&norm);CHKERRQ(ierr); norm = norm/PetscSqrtReal((PetscReal)N-1.); if (dw) ierr = PetscPrintf(PETSC_COMM_WORLD,"Norm of error %g Error at x = 0 %g\n",(double)norm,(double)PetscRealPart(dw[0]));CHKERRQ(ierr); ierr = VecView(u_lambda,user->fu_lambda_viewer);CHKERRQ(ierr); ierr = DMCompositeRestoreAccess(packer,Uexact,&dw,&u_lambda);CHKERRQ(ierr); ierr = VecDestroy(&Uexact);CHKERRQ(ierr); PetscFunctionReturn(0); }
// Function to hand to PETSc's SNES, // which monitors convergence at X PetscErrorCode __libmesh_petsc_diff_solver_monitor (SNES snes, PetscInt its, PetscReal fnorm, void *ctx) { PetscDiffSolver& solver = *(static_cast<PetscDiffSolver*> (ctx)); if (solver.verbose) libMesh::out << " PetscDiffSolver step " << its << ", |residual|_2 = " << fnorm << std::endl; if (solver.linear_solution_monitor.get()) { int ierr = 0; Vec petsc_delta_u; ierr = SNESGetSolutionUpdate(snes, &petsc_delta_u); CHKERRABORT(libMesh::COMM_WORLD, ierr); PetscVector<Number> delta_u(petsc_delta_u, solver.comm()); delta_u.close(); Vec petsc_u; ierr = SNESGetSolution(snes, &petsc_u); CHKERRABORT(libMesh::COMM_WORLD, ierr); PetscVector<Number> u(petsc_u, solver.comm()); u.close(); Vec petsc_res; ierr = SNESGetFunction(snes, &petsc_res, NULL, NULL); CHKERRABORT(libMesh::COMM_WORLD, ierr); PetscVector<Number> res(petsc_res, solver.comm()); res.close(); (*solver.linear_solution_monitor)( delta_u, delta_u.l2_norm(), u, u.l2_norm(), res, res.l2_norm(), its); } return 0; }
PetscErrorCode SNESMonitorRange_Private(SNES snes,PetscInt it,PetscReal *per) { PetscErrorCode ierr; Vec resid; PetscReal rmax,pwork; PetscInt i,n,N; PetscScalar *r; PetscFunctionBegin; ierr = SNESGetFunction(snes,&resid,0,0);CHKERRQ(ierr); ierr = VecNorm(resid,NORM_INFINITY,&rmax);CHKERRQ(ierr); ierr = VecGetLocalSize(resid,&n);CHKERRQ(ierr); ierr = VecGetSize(resid,&N);CHKERRQ(ierr); ierr = VecGetArray(resid,&r);CHKERRQ(ierr); pwork = 0.0; for (i=0; i<n; i++) { pwork += (PetscAbsScalar(r[i]) > .20*rmax); } ierr = MPI_Allreduce(&pwork,per,1,MPIU_REAL,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr); ierr = VecRestoreArray(resid,&r);CHKERRQ(ierr); *per = *per/N; PetscFunctionReturn(0); }
/*@C SNESMonitorDefaultField - Monitors progress of the SNES solvers, separated into fields. Collective on SNES Input Parameters: + snes - the SNES context . its - iteration number . fgnorm - 2-norm of residual - ctx - the PetscViewer Notes: This routine uses the DM attached to the residual vector Level: intermediate .keywords: SNES, nonlinear, field, monitor, norm .seealso: SNESMonitorSet(), SNESMonitorSolution(), SNESMonitorDefault(), SNESMonitorDefaultShort() @*/ PetscErrorCode SNESMonitorDefaultField(SNES snes, PetscInt its, PetscReal fgnorm, void *ctx) { PetscViewer viewer = (PetscViewer) ctx; Vec r; DM dm; PetscReal res[256]; PetscInt tablevel; PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4); ierr = SNESGetFunction(snes, &r, NULL, NULL);CHKERRQ(ierr); ierr = VecGetDM(r, &dm);CHKERRQ(ierr); if (!dm) {ierr = SNESMonitorDefault(snes, its, fgnorm, ctx);CHKERRQ(ierr);} else { PetscSection s, gs; PetscInt Nf, f; ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr); ierr = DMGetDefaultGlobalSection(dm, &gs);CHKERRQ(ierr); if (!s || !gs) {ierr = SNESMonitorDefault(snes, its, fgnorm, ctx);CHKERRQ(ierr);} ierr = PetscSectionGetNumFields(s, &Nf);CHKERRQ(ierr); if (Nf > 256) SETERRQ1(PetscObjectComm((PetscObject) snes), PETSC_ERR_SUP, "Do not support %d fields > 256", Nf); ierr = PetscSectionVecNorm(s, gs, r, NORM_2, res);CHKERRQ(ierr); ierr = PetscObjectGetTabLevel((PetscObject) snes, &tablevel);CHKERRQ(ierr); ierr = PetscViewerASCIIAddTab(viewer, tablevel);CHKERRQ(ierr); ierr = PetscViewerASCIIPrintf(viewer, "%3D SNES Function norm %14.12e [", its, (double) fgnorm);CHKERRQ(ierr); for (f = 0; f < Nf; ++f) { if (f) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} ierr = PetscViewerASCIIPrintf(viewer, "%14.12e", res[f]);CHKERRQ(ierr); } ierr = PetscViewerASCIIPrintf(viewer, "] \n");CHKERRQ(ierr); ierr = PetscViewerASCIISubtractTab(viewer, tablevel);CHKERRQ(ierr); } PetscFunctionReturn(0); }
/* Defines the action of the upsmoother */ PetscErrorCode SNESFASUpSmooth_Private(SNES snes, Vec B, Vec X, Vec F, PetscReal *fnorm) { PetscErrorCode ierr = 0; SNESConvergedReason reason; Vec FPC; SNES smoothu; SNES_FAS *fas = (SNES_FAS*) snes->data; PetscFunctionBegin; ierr = SNESFASCycleGetSmootherUp(snes, &smoothu);CHKERRQ(ierr); if (fas->eventsmoothsolve) {ierr = PetscLogEventBegin(fas->eventsmoothsolve,0,0,0,0);CHKERRQ(ierr);} ierr = SNESSolve(smoothu, B, X);CHKERRQ(ierr); if (fas->eventsmoothsolve) {ierr = PetscLogEventEnd(fas->eventsmoothsolve,0,0,0,0);CHKERRQ(ierr);} /* check convergence reason for the smoother */ ierr = SNESGetConvergedReason(smoothu,&reason);CHKERRQ(ierr); if (reason < 0 && !(reason == SNES_DIVERGED_MAX_IT || reason == SNES_DIVERGED_LOCAL_MIN || reason == SNES_DIVERGED_LINE_SEARCH)) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } ierr = SNESGetFunction(smoothu, &FPC, NULL, NULL);CHKERRQ(ierr); ierr = VecCopy(FPC, F);CHKERRQ(ierr); if (fnorm) {ierr = VecNorm(F,NORM_2,fnorm);CHKERRQ(ierr);} PetscFunctionReturn(0); }
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 JacMatMultCompare(SNES snes,Vec x,Vec p,double hopt) { Vec yy1, yy2; /* work vectors */ PetscViewer view2; /* viewer */ Mat J; /* analytic Jacobian (set as preconditioner matrix) */ Mat Jmf; /* matrix-free Jacobian (set as true system matrix) */ double h; /* differencing parameter */ Vec f; PetscScalar alpha; PetscReal yy1n,yy2n,enorm; PetscErrorCode ierr; PetscInt i; PetscBool printv = PETSC_FALSE; char filename[32]; MPI_Comm comm; PetscFunctionBegin; ierr = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr); /* Compute function and analytic Jacobian at x */ ierr = SNESGetJacobian(snes,&Jmf,&J,NULL,NULL);CHKERRQ(ierr); ierr = SNESComputeJacobian(snes,x,Jmf,J);CHKERRQ(ierr); ierr = SNESGetFunction(snes,&f,NULL,NULL);CHKERRQ(ierr); ierr = SNESComputeFunction(snes,x,f);CHKERRQ(ierr); /* Duplicate work vectors */ ierr = VecDuplicate(x,&yy2);CHKERRQ(ierr); ierr = VecDuplicate(x,&yy1);CHKERRQ(ierr); /* Compute true matrix-vector product */ ierr = MatMult(J,p,yy1);CHKERRQ(ierr); ierr = VecNorm(yy1,NORM_2,&yy1n);CHKERRQ(ierr); /* View product vector if desired */ ierr = PetscOptionsGetBool(NULL,"-print_vecs",&printv,NULL);CHKERRQ(ierr); if (printv) { ierr = PetscViewerASCIIOpen(comm,"y1.out",&view2);CHKERRQ(ierr); ierr = PetscViewerSetFormat(view2,PETSC_VIEWER_ASCII_COMMON);CHKERRQ(ierr); ierr = VecView(yy1,view2);CHKERRQ(ierr); ierr = PetscViewerDestroy(&view2);CHKERRQ(ierr); } /* Test Jacobian-vector product computation */ alpha = -1.0; h = 0.01 * hopt; for (i=0; i<5; i++) { /* Set differencing parameter for matrix-free multiplication */ ierr = SNESDefaultMatrixFreeSetParameters2(Jmf,PETSC_DEFAULT,PETSC_DEFAULT,h);CHKERRQ(ierr); /* Compute matrix-vector product via differencing approximation */ ierr = MatMult(Jmf,p,yy2);CHKERRQ(ierr); ierr = VecNorm(yy2,NORM_2,&yy2n);CHKERRQ(ierr); /* View product vector if desired */ if (printv) { sprintf(filename,"y2.%d.out",(int)i); ierr = PetscViewerASCIIOpen(comm,filename,&view2);CHKERRQ(ierr); ierr = PetscViewerSetFormat(view2,PETSC_VIEWER_ASCII_COMMON);CHKERRQ(ierr); ierr = VecView(yy2,view2);CHKERRQ(ierr); ierr = PetscViewerDestroy(&view2);CHKERRQ(ierr); } /* Compute relative error */ ierr = VecAXPY(yy2,alpha,yy1);CHKERRQ(ierr); ierr = VecNorm(yy2,NORM_2,&enorm);CHKERRQ(ierr); enorm = enorm/yy1n; ierr = PetscFPrintf(comm,stdout,"h = %g: relative error = %g\n",(double)h,(double)enorm);CHKERRQ(ierr); h *= 10.0; } PetscFunctionReturn(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 SNESSolve_QN(SNES snes) { PetscErrorCode ierr; SNES_QN *qn = (SNES_QN*) snes->data; Vec X,Xold; Vec F,B; Vec Y,FPC,D,Dold; SNESConvergedReason reason; PetscInt i, i_r; PetscReal fnorm,xnorm,ynorm,gnorm; PetscBool lssucceed,powell,periodic; PetscScalar DolddotD,DolddotDold,DdotD,YdotD; MatStructure flg = DIFFERENT_NONZERO_PATTERN; /* basically just a regular newton's method except for the application of the jacobian */ PetscFunctionBegin; F = snes->vec_func; /* residual vector */ Y = snes->vec_sol_update; /* search direction generated by J^-1D*/ B = snes->vec_rhs; X = snes->vec_sol; /* solution vector */ Xold = snes->work[0]; /* directions generated by the preconditioned problem with F_pre = F or x - M(x, b) */ D = snes->work[1]; Dold = snes->work[2]; snes->reason = SNES_CONVERGED_ITERATING; ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); snes->iter = 0; snes->norm = 0.; ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); if (!snes->vec_func_init_set){ ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); if (snes->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,"Infinite or not-a-number generated in norm"); } else { fnorm = snes->norm_init; snes->norm_init_set = PETSC_FALSE; } ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); snes->norm = fnorm; ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 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,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); if (snes->reason) PetscFunctionReturn(0); /* composed solve */ if (snes->pc && snes->pcside == PC_RIGHT) { ierr = SNESSetInitialFunction(snes->pc, F);CHKERRQ(ierr); ierr = SNESSetInitialFunctionNorm(snes->pc, fnorm);CHKERRQ(ierr); ierr = SNESSolve(snes->pc, B, X);CHKERRQ(ierr); ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); if (reason < 0 && (reason != SNES_DIVERGED_MAX_IT)) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } ierr = SNESGetFunction(snes->pc, &FPC, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); ierr = VecCopy(FPC, F);CHKERRQ(ierr); ierr = SNESGetFunctionNorm(snes->pc, &fnorm);CHKERRQ(ierr); ierr = VecCopy(F, Y);CHKERRQ(ierr); } else { ierr = VecCopy(F, Y);CHKERRQ(ierr); } ierr = VecCopy(Y, D);CHKERRQ(ierr); /* scale the initial update */ if (qn->scale_type == SNES_QN_SCALE_JACOBIAN) { ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr); } for (i = 0, i_r = 0; i < snes->max_its; i++, i_r++) { switch(qn->type) { case SNES_QN_BADBROYDEN: ierr = SNESQNApply_BadBroyden(snes,i_r,Y,X,Xold,D,Dold);CHKERRQ(ierr); break; case SNES_QN_BROYDEN: ierr = SNESQNApply_Broyden(snes,i_r,Y,X,Xold,D,Dold);CHKERRQ(ierr); break; case SNES_QN_LBFGS: SNESQNApply_LBFGS(snes,i_r,Y,X,Xold,D,Dold);CHKERRQ(ierr); break; } /* line search for lambda */ ynorm = 1; gnorm = fnorm; ierr = VecCopy(D, Dold);CHKERRQ(ierr); ierr = VecCopy(X, Xold);CHKERRQ(ierr); ierr = SNESLineSearchApply(snes->linesearch, X, F, &fnorm, Y);CHKERRQ(ierr); if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break; if (snes->domainerror) { snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; PetscFunctionReturn(0); } ierr = SNESLineSearchGetSuccess(snes->linesearch, &lssucceed);CHKERRQ(ierr); if (!lssucceed) { if (++snes->numFailures >= snes->maxFailures) { snes->reason = SNES_DIVERGED_LINE_SEARCH; break; } } ierr = SNESLineSearchGetNorms(snes->linesearch, &xnorm, &fnorm, &ynorm);CHKERRQ(ierr); if (qn->scale_type == SNES_QN_SCALE_LINESEARCH) { ierr = SNESLineSearchGetLambda(snes->linesearch, &qn->scaling);CHKERRQ(ierr); } /* convergence monitoring */ ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",(double)fnorm,(double)gnorm,(double)ynorm,(int)lssucceed);CHKERRQ(ierr); ierr = SNESSetIterationNumber(snes, i+1);CHKERRQ(ierr); ierr = SNESSetFunctionNorm(snes, fnorm);CHKERRQ(ierr); SNESLogConvHistory(snes,snes->norm,snes->iter); ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); /* set parameter for default relative tolerance convergence test */ ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); if (snes->reason) PetscFunctionReturn(0); if (snes->pc && snes->pcside == PC_RIGHT) { ierr = SNESSetInitialFunction(snes->pc, F);CHKERRQ(ierr); ierr = SNESSetInitialFunctionNorm(snes->pc, fnorm);CHKERRQ(ierr); ierr = SNESSolve(snes->pc, B, X);CHKERRQ(ierr); ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); if (reason < 0 && (reason != SNES_DIVERGED_MAX_IT)) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } ierr = SNESGetFunction(snes->pc, &FPC, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); ierr = VecCopy(FPC, F);CHKERRQ(ierr); ierr = SNESGetFunctionNorm(snes->pc, &fnorm);CHKERRQ(ierr); ierr = VecCopy(F, D);CHKERRQ(ierr); } else { ierr = VecCopy(F, D);CHKERRQ(ierr); } powell = PETSC_FALSE; if (qn->restart_type == SNES_QN_RESTART_POWELL) { /* check restart by Powell's Criterion: |F^T H_0 Fold| > 0.2 * |Fold^T H_0 Fold| */ ierr = VecDotBegin(Dold, Dold, &DolddotDold);CHKERRQ(ierr); ierr = VecDotBegin(Dold, D, &DolddotD);CHKERRQ(ierr); ierr = VecDotBegin(D, D, &DdotD);CHKERRQ(ierr); ierr = VecDotBegin(Y, D, &YdotD);CHKERRQ(ierr); ierr = VecDotEnd(Dold, Dold, &DolddotDold);CHKERRQ(ierr); ierr = VecDotEnd(Dold, D, &DolddotD);CHKERRQ(ierr); ierr = VecDotEnd(D, D, &DdotD);CHKERRQ(ierr); ierr = VecDotEnd(Y, D, &YdotD);CHKERRQ(ierr); if (PetscAbs(PetscRealPart(DolddotD)) > qn->powell_gamma*PetscAbs(PetscRealPart(DolddotDold))) powell = PETSC_TRUE; } periodic = PETSC_FALSE; if (qn->restart_type == SNES_QN_RESTART_PERIODIC) { if (i_r>qn->m-1) periodic = PETSC_TRUE; } /* restart if either powell or periodic restart is satisfied. */ if (powell || periodic) { if (qn->monitor) { ierr = PetscViewerASCIIAddTab(qn->monitor,((PetscObject)snes)->tablevel+2);CHKERRQ(ierr); ierr = PetscViewerASCIIPrintf(qn->monitor, "restart! |%14.12e| > %4.2f*|%14.12e| or i_r = %d\n", PetscRealPart(DolddotD), qn->powell_gamma, PetscRealPart(DolddotDold), i_r);CHKERRQ(ierr); ierr = PetscViewerASCIISubtractTab(qn->monitor,((PetscObject)snes)->tablevel+2);CHKERRQ(ierr); } i_r = -1; /* general purpose update */ if (snes->ops->update) { ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); } if (qn->scale_type == SNES_QN_SCALE_JACOBIAN) { ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr); } } /* general purpose update */ if (snes->ops->update) { ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); } } if (i == snes->max_its) { ierr = PetscInfo1(snes, "Maximum number of iterations has been reached: %D\n", snes->max_its);CHKERRQ(ierr); if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; } PetscFunctionReturn(0); }
static PetscErrorCode SNESCompositeApply_Multiplicative(SNES snes,Vec X,Vec B,Vec F,PetscReal *fnorm) { PetscErrorCode ierr; SNES_Composite *jac = (SNES_Composite*)snes->data; SNES_CompositeLink next = jac->head; Vec FSub; SNESConvergedReason reason; PetscFunctionBegin; if (!next) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"No composite SNESes supplied via SNESCompositeAddSNES() or -snes_composite_sneses"); if (snes->normschedule == SNES_NORM_ALWAYS) { ierr = SNESSetInitialFunction(next->snes,F);CHKERRQ(ierr); } ierr = SNESSolve(next->snes,B,X);CHKERRQ(ierr); ierr = SNESGetConvergedReason(next->snes,&reason);CHKERRQ(ierr); if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { jac->innerFailures++; if (jac->innerFailures >= snes->maxFailures) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } } while (next->next) { /* only copy the function over in the case where the functions correspond */ if (next->snes->pcside == PC_RIGHT && next->snes->normschedule != SNES_NORM_NONE) { ierr = SNESGetFunction(next->snes,&FSub,NULL,NULL);CHKERRQ(ierr); next = next->next; ierr = SNESSetInitialFunction(next->snes,FSub);CHKERRQ(ierr); } else { next = next->next; } ierr = SNESSolve(next->snes,B,X);CHKERRQ(ierr); ierr = SNESGetConvergedReason(next->snes,&reason);CHKERRQ(ierr); if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { jac->innerFailures++; if (jac->innerFailures >= snes->maxFailures) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } } } if (next->snes->pcside == PC_RIGHT) { ierr = SNESGetFunction(next->snes,&FSub,NULL,NULL);CHKERRQ(ierr); ierr = VecCopy(FSub,F);CHKERRQ(ierr); if (fnorm) { if (snes->xl && snes->xu) { ierr = SNESVIComputeInactiveSetFnorm(snes, F, X, fnorm);CHKERRQ(ierr); } else { ierr = VecNorm(F, NORM_2, fnorm);CHKERRQ(ierr); } SNESCheckFunctionNorm(snes,*fnorm); } } else if (snes->normschedule == SNES_NORM_ALWAYS) { ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); if (fnorm) { if (snes->xl && snes->xu) { ierr = SNESVIComputeInactiveSetFnorm(snes, F, X, fnorm);CHKERRQ(ierr); } else { ierr = VecNorm(F, NORM_2, fnorm);CHKERRQ(ierr); } SNESCheckFunctionNorm(snes,*fnorm); } } PetscFunctionReturn(0); }
static int block_system(void) { 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; PetscScalar pfive = .5; PetscBool flg; Mat j11, j12, j21, j22; Vec x1, x2, r1, r2; Vec bv; Vec bx[2]; Mat bA[2][2]; PetscFunctionBegin; PetscPrintf( PETSC_COMM_WORLD, "\n\n========================= Block system =========================\n\n" ); ierr = SNESCreate(PETSC_COMM_WORLD,&snes); CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create matrix and vector data structures; set corresponding routines - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* Create sub vectors for solution and nonlinear function */ ierr = VecCreateSeq(PETSC_COMM_SELF,1,&x1); CHKERRQ(ierr); ierr = VecDuplicate(x1,&r1); CHKERRQ(ierr); ierr = VecCreateSeq(PETSC_COMM_SELF,1,&x2); CHKERRQ(ierr); ierr = VecDuplicate(x2,&r2); CHKERRQ(ierr); /* Create the block vectors */ bx[0] = x1; bx[1] = x2; ierr = VecCreateNest(PETSC_COMM_WORLD,2,PETSC_NULL,bx,&x); CHKERRQ(ierr); ierr = VecAssemblyBegin(x); CHKERRQ(ierr); ierr = VecAssemblyEnd(x); CHKERRQ(ierr); ierr = VecDestroy(&x1); CHKERRQ(ierr); ierr = VecDestroy(&x2); CHKERRQ(ierr); bx[0] = r1; bx[1] = r2; ierr = VecCreateNest(PETSC_COMM_WORLD,2,PETSC_NULL,bx,&r); CHKERRQ(ierr); ierr = VecDestroy(&r1); CHKERRQ(ierr); ierr = VecDestroy(&r2); CHKERRQ(ierr); ierr = VecAssemblyBegin(r); CHKERRQ(ierr); ierr = VecAssemblyEnd(r); CHKERRQ(ierr); /* Create sub Jacobian matrix data structure */ ierr = MatCreate( PETSC_COMM_WORLD, &j11 ); CHKERRQ(ierr); ierr = MatSetSizes( j11, 1, 1, 1, 1 ); CHKERRQ(ierr); ierr = MatSetType( j11, MATSEQAIJ ); CHKERRQ(ierr); ierr = MatSetUp(j11); CHKERRQ(ierr); ierr = MatCreate( PETSC_COMM_WORLD, &j12 ); CHKERRQ(ierr); ierr = MatSetSizes( j12, 1, 1, 1, 1 ); CHKERRQ(ierr); ierr = MatSetType( j12, MATSEQAIJ ); CHKERRQ(ierr); ierr = MatSetUp(j12); CHKERRQ(ierr); ierr = MatCreate( PETSC_COMM_WORLD, &j21 ); CHKERRQ(ierr); ierr = MatSetSizes( j21, 1, 1, 1, 1 ); CHKERRQ(ierr); ierr = MatSetType( j21, MATSEQAIJ ); CHKERRQ(ierr); ierr = MatSetUp(j21); CHKERRQ(ierr); ierr = MatCreate( PETSC_COMM_WORLD, &j22 ); CHKERRQ(ierr); ierr = MatSetSizes( j22, PETSC_DECIDE, PETSC_DECIDE, 1, 1 ); CHKERRQ(ierr); ierr = MatSetType( j22, MATSEQAIJ ); CHKERRQ(ierr); ierr = MatSetUp(j22); CHKERRQ(ierr); /* Create block Jacobian matrix data structure */ bA[0][0] = j11; bA[0][1] = j12; bA[1][0] = j21; bA[1][1] = j22; ierr = MatCreateNest(PETSC_COMM_WORLD,2,PETSC_NULL,2,PETSC_NULL,&bA[0][0],&J); CHKERRQ(ierr); ierr = MatSetUp(J); CHKERRQ(ierr); ierr = MatNestSetVecType(J,VECNEST); CHKERRQ(ierr); ierr = MatDestroy(&j11); CHKERRQ(ierr); ierr = MatDestroy(&j12); CHKERRQ(ierr); ierr = MatDestroy(&j21); CHKERRQ(ierr); ierr = MatDestroy(&j22); CHKERRQ(ierr); ierr = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); ierr = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); ierr = PetscOptionsHasName(PETSC_NULL,"-hard",&flg); CHKERRQ(ierr); if (!flg) { /* Set function evaluation routine and vector. */ ierr = SNESSetFunction(snes,r,FormFunction1_block,PETSC_NULL); CHKERRQ(ierr); /* Set Jacobian matrix data structure and Jacobian evaluation routine */ ierr = SNESSetJacobian(snes,J,J,FormJacobian1_block,PETSC_NULL); CHKERRQ(ierr); } else { ierr = SNESSetFunction(snes,r,FormFunction2_block,PETSC_NULL); CHKERRQ(ierr); ierr = SNESSetJacobian(snes,J,J,FormJacobian2_block,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 { Vec *vecs; ierr = VecNestGetSubVecs( x, PETSC_NULL, &vecs ); CHKERRQ(ierr); bv = vecs[0]; // ierr = VecBlockGetSubVec( x, 0, &bv );CHKERRQ(ierr); ierr = VecSetValue( bv, 0, 2.0, INSERT_VALUES ); CHKERRQ(ierr); /* xx[0] = 2.0; */ ierr = VecAssemblyBegin(bv); CHKERRQ(ierr); ierr = VecAssemblyEnd(bv); CHKERRQ(ierr); // ierr = VecBlockGetSubVec( x, 1, &bv );CHKERRQ(ierr); bv = vecs[1]; ierr = VecSetValue( bv, 0, 3.0, INSERT_VALUES ); CHKERRQ(ierr); /* xx[1] = 3.0; */ ierr = VecAssemblyBegin(bv); CHKERRQ(ierr); ierr = VecAssemblyEnd(bv); 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_SELF,"number of SNES iterations = %D\n\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); PetscFunctionReturn(0); }
PetscErrorCode SNESSolve_NEWTONLS(SNES snes) { PetscErrorCode ierr; PetscInt maxits,i,lits; PetscBool lssucceed; MatStructure flg = DIFFERENT_NONZERO_PATTERN; PetscReal fnorm,gnorm,xnorm,ynorm; Vec Y,X,F,G,W,FPC; KSPConvergedReason kspreason; PetscBool domainerror; SNESLineSearch linesearch; SNESConvergedReason reason; PetscFunctionBegin; snes->numFailures = 0; snes->numLinearSolveFailures = 0; snes->reason = SNES_CONVERGED_ITERATING; maxits = snes->max_its; /* maximum number of iterations */ X = snes->vec_sol; /* solution vector */ F = snes->vec_func; /* residual vector */ Y = snes->vec_sol_update; /* newton step */ G = snes->work[0]; W = snes->work[1]; ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); snes->iter = 0; snes->norm = 0.0; ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); ierr = SNESGetSNESLineSearch(snes, &linesearch);CHKERRQ(ierr); if (!snes->vec_func_init_set) { ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 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 = VecNormBegin(F,NORM_2,&fnorm);CHKERRQ(ierr); /* fnorm <- ||F|| */ ierr = VecNormEnd(F,NORM_2,&fnorm);CHKERRQ(ierr); 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); 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,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); if (snes->reason) PetscFunctionReturn(0); for (i=0; i<maxits; i++) { /* Call general purpose update function */ if (snes->ops->update) { ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); } /* apply the nonlinear preconditioner if it's right preconditioned */ if (snes->pc && snes->pcside == PC_RIGHT) { ierr = SNESSetInitialFunction(snes->pc, F);CHKERRQ(ierr); ierr = SNESSetInitialFunctionNorm(snes->pc, fnorm);CHKERRQ(ierr); ierr = SNESSolve(snes->pc, snes->vec_rhs, X);CHKERRQ(ierr); ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } ierr = SNESGetFunction(snes->pc, &FPC, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); ierr = VecCopy(FPC, F);CHKERRQ(ierr); ierr = SNESGetFunctionNorm(snes->pc, &fnorm);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,Y);CHKERRQ(ierr); ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr); if (kspreason < 0) { if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) { ierr = PetscInfo2(snes,"iter=%D, number linear solve failures %D greater than current SNES allowed, stopping solve\n",snes->iter,snes->numLinearSolveFailures);CHKERRQ(ierr); snes->reason = SNES_DIVERGED_LINEAR_SOLVE; break; } } 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); if (PetscLogPrintInfo){ ierr = SNESNEWTONLSCheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr); } /* Compute a (scaled) negative update in the line search routine: X <- X - lambda*Y and evaluate F = function(X) (depends on the line search). */ gnorm = fnorm; ierr = SNESLineSearchApply(linesearch, X, F, &fnorm, Y);CHKERRQ(ierr); ierr = SNESLineSearchGetSuccess(linesearch, &lssucceed);CHKERRQ(ierr); ierr = SNESLineSearchGetNorms(linesearch, &xnorm, &fnorm, &ynorm);CHKERRQ(ierr); ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",(double)gnorm,(double)fnorm,(double)ynorm,(int)lssucceed);CHKERRQ(ierr); if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break; ierr = SNESGetFunctionDomainError(snes, &domainerror);CHKERRQ(ierr); if (domainerror) { snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; PetscFunctionReturn(0); } if (!lssucceed) { if (snes->stol*xnorm > ynorm) { snes->reason = SNES_CONVERGED_SNORM_RELATIVE; PetscFunctionReturn(0); } if (++snes->numFailures >= snes->maxFailures) { PetscBool ismin; snes->reason = SNES_DIVERGED_LINE_SEARCH; ierr = SNESNEWTONLSCheckLocalMin_Private(snes,snes->jacobian,F,W,fnorm,&ismin);CHKERRQ(ierr); if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN; break; } } /* 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 */ ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); if (snes->reason) break; } if (i == maxits) { ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr); if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; } PetscFunctionReturn(0); }
/* SNESMatrixFreeMult2_Private - Default matrix-free form for Jacobian-vector product, y = F'(u)*a: y = (F(u + ha) - F(u)) /h, where F = nonlinear function, as set by SNESSetFunction() u = current iterate h = difference interval */ PetscErrorCode SNESMatrixFreeMult2_Private(Mat mat,Vec a,Vec y) { MFCtx_Private *ctx; SNES snes; PetscReal h,norm,sum,umin,noise; PetscScalar hs,dot; Vec w,U,F; PetscErrorCode ierr,(*eval_fct)(SNES,Vec,Vec); MPI_Comm comm; PetscInt iter; PetscFunctionBegin; /* We log matrix-free matrix-vector products separately, so that we can separate the performance monitoring from the cases that use conventional storage. We may eventually modify event logging to associate events with particular objects, hence alleviating the more general problem. */ ierr = PetscLogEventBegin(MATMFFD_Mult,a,y,0,0);CHKERRQ(ierr); ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr); ierr = MatShellGetContext(mat,(void**)&ctx);CHKERRQ(ierr); snes = ctx->snes; w = ctx->w; umin = ctx->umin; ierr = SNESGetSolution(snes,&U);CHKERRQ(ierr); eval_fct = SNESComputeFunction; ierr = SNESGetFunction(snes,&F,NULL,NULL);CHKERRQ(ierr); /* Determine a "good" step size, h */ if (ctx->need_h) { /* Use Jorge's method to compute h */ if (ctx->jorge) { ierr = SNESDiffParameterCompute_More(snes,ctx->data,U,a,&noise,&h);CHKERRQ(ierr); /* Use the Brown/Saad method to compute h */ } else { /* Compute error if desired */ ierr = SNESGetIterationNumber(snes,&iter);CHKERRQ(ierr); if ((ctx->need_err) || ((ctx->compute_err_freq) && (ctx->compute_err_iter != iter) && (!((iter-1)%ctx->compute_err_freq)))) { /* Use Jorge's method to compute noise */ ierr = SNESDiffParameterCompute_More(snes,ctx->data,U,a,&noise,&h);CHKERRQ(ierr); ctx->error_rel = PetscSqrtReal(noise); ierr = PetscInfo3(snes,"Using Jorge's noise: noise=%g, sqrt(noise)=%g, h_more=%g\n",(double)noise,(double)ctx->error_rel,(double)h);CHKERRQ(ierr); ctx->compute_err_iter = iter; ctx->need_err = PETSC_FALSE; } ierr = VecDotBegin(U,a,&dot);CHKERRQ(ierr); ierr = VecNormBegin(a,NORM_1,&sum);CHKERRQ(ierr); ierr = VecNormBegin(a,NORM_2,&norm);CHKERRQ(ierr); ierr = VecDotEnd(U,a,&dot);CHKERRQ(ierr); ierr = VecNormEnd(a,NORM_1,&sum);CHKERRQ(ierr); ierr = VecNormEnd(a,NORM_2,&norm);CHKERRQ(ierr); /* Safeguard for step sizes too small */ if (sum == 0.0) { dot = 1.0; norm = 1.0; } else if (PetscAbsScalar(dot) < umin*sum && PetscRealPart(dot) >= 0.0) dot = umin*sum; else if (PetscAbsScalar(dot) < 0.0 && PetscRealPart(dot) > -umin*sum) dot = -umin*sum; h = PetscRealPart(ctx->error_rel*dot/(norm*norm)); } } else h = ctx->h; if (!ctx->jorge || !ctx->need_h) {ierr = PetscInfo1(snes,"h = %g\n",(double)h);CHKERRQ(ierr);} /* Evaluate function at F(u + ha) */ hs = h; ierr = VecWAXPY(w,hs,a,U);CHKERRQ(ierr); ierr = eval_fct(snes,w,y);CHKERRQ(ierr); ierr = VecAXPY(y,-1.0,F);CHKERRQ(ierr); ierr = VecScale(y,1.0/hs);CHKERRQ(ierr); if (ctx->sp) {ierr = MatNullSpaceRemove(ctx->sp,y);CHKERRQ(ierr);} ierr = PetscLogEventEnd(MATMFFD_Mult,a,y,0,0);CHKERRQ(ierr); PetscFunctionReturn(0); }
static PetscErrorCode assembled_system(void) { 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; PetscScalar pfive = .5,*xx; PetscBool flg; PetscFunctionBegin; PetscPrintf( PETSC_COMM_WORLD, "\n\n========================= Assembled system =========================\n\n" ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 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 = VecCreateSeq(PETSC_COMM_SELF,2,&x); CHKERRQ(ierr); ierr = VecDuplicate(x,&r); CHKERRQ(ierr); /* Create Jacobian matrix data structure */ ierr = MatCreate(PETSC_COMM_SELF,&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,PETSC_NULL); CHKERRQ(ierr); /* Set Jacobian matrix data structure and Jacobian evaluation routine */ ierr = SNESSetJacobian(snes,J,J,FormJacobian1,PETSC_NULL); CHKERRQ(ierr); } else { 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_SELF,"number of SNES iterations = %D\n\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); PetscFunctionReturn(0); }
std::pair<unsigned int, Real> PetscDMNonlinearSolver<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 libmesh_cast_ptr<PetscMatrix<T>*>(&jac_in); libmesh_cast_ptr<PetscVector<T>*>(&r_in); // Extract solution vector PetscVector<T>* x = libmesh_cast_ptr<PetscVector<T>*>(&x_in); PetscErrorCode ierr=0; PetscInt n_iterations =0; PetscReal final_residual_norm=0.; if (this->user_presolve) this->user_presolve(this->system()); //Set the preconditioning matrix if (this->_preconditioner) this->_preconditioner->set_matrix(jac_in); ierr = SNESSolve (this->_snes, PETSC_NULL, x->vec()); LIBMESH_CHKERRABORT(ierr); ierr = SNESGetIterationNumber(this->_snes,&n_iterations); LIBMESH_CHKERRABORT(ierr); ierr = SNESGetLinearSolveIterations(this->_snes, &this->_n_linear_iterations); LIBMESH_CHKERRABORT(ierr); #if PETSC_VERSION_LESS_THAN(3,5,0) // SNESGetFunctionNorm was removed in PETSc 3.5.0 ierr = SNESGetFunctionNorm(this->_snes,&final_residual_norm); LIBMESH_CHKERRABORT(ierr); #else { /* PB: Not sure where r_in is coming from and it's not used here, so we'll just get the residual from PETSc */ Vec r; ierr = SNESGetFunction(this->_snes,&r,NULL,NULL);LIBMESH_CHKERRABORT(ierr); ierr = VecNorm(r,NORM_2,&final_residual_norm);LIBMESH_CHKERRABORT(ierr); } #endif // Get and store the reason for convergence SNESGetConvergedReason(this->_snes, &this->_reason); //Based on Petsc 2.3.3 documentation all diverged reasons are negative this->converged = (this->_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); }
static PetscErrorCode SNESSetUp_Composite(SNES snes) { PetscErrorCode ierr; DM dm; SNES_Composite *jac = (SNES_Composite*)snes->data; SNES_CompositeLink next = jac->head; PetscInt n=0,i; Vec F; PetscFunctionBegin; ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); if (snes->ops->computevariablebounds) { /* SNESVI only ever calls computevariablebounds once, so calling it once here is justified */ if (!snes->xl) {ierr = VecDuplicate(snes->vec_sol,&snes->xl);CHKERRQ(ierr);} if (!snes->xu) {ierr = VecDuplicate(snes->vec_sol,&snes->xu);CHKERRQ(ierr);} ierr = (*snes->ops->computevariablebounds)(snes,snes->xl,snes->xu);CHKERRQ(ierr); } while (next) { n++; ierr = SNESSetDM(next->snes,dm);CHKERRQ(ierr); ierr = SNESSetApplicationContext(next->snes, snes->user);CHKERRQ(ierr); if (snes->xl && snes->xu) { if (snes->ops->computevariablebounds) { ierr = SNESVISetComputeVariableBounds(next->snes, snes->ops->computevariablebounds);CHKERRQ(ierr); } else { ierr = SNESVISetVariableBounds(next->snes,snes->xl,snes->xu);CHKERRQ(ierr); } } next = next->next; } jac->nsnes = n; ierr = SNESGetFunction(snes,&F,NULL,NULL);CHKERRQ(ierr); if (jac->type == SNES_COMPOSITE_ADDITIVEOPTIMAL) { ierr = VecDuplicateVecs(F,jac->nsnes,&jac->Xes);CHKERRQ(ierr); ierr = PetscMalloc1(n,&jac->Fes);CHKERRQ(ierr); ierr = PetscMalloc1(n,&jac->fnorms);CHKERRQ(ierr); next = jac->head; i = 0; while (next) { ierr = SNESGetFunction(next->snes,&F,NULL,NULL);CHKERRQ(ierr); jac->Fes[i] = F; ierr = PetscObjectReference((PetscObject)F);CHKERRQ(ierr); next = next->next; i++; } /* allocate the subspace direct solve area */ jac->nrhs = 1; jac->lda = jac->nsnes; jac->ldb = jac->nsnes; jac->n = jac->nsnes; ierr = PetscMalloc1(jac->n*jac->n,&jac->h);CHKERRQ(ierr); ierr = PetscMalloc1(jac->n,&jac->beta);CHKERRQ(ierr); ierr = PetscMalloc1(jac->n,&jac->s);CHKERRQ(ierr); ierr = PetscMalloc1(jac->n,&jac->g);CHKERRQ(ierr); jac->lwork = 12*jac->n; #if PETSC_USE_COMPLEX ierr = PetscMalloc1(jac->lwork,&jac->rwork);CHKERRQ(ierr); #endif ierr = PetscMalloc1(jac->lwork,&jac->work);CHKERRQ(ierr); } PetscFunctionReturn(0); }
PetscErrorCode SNESSolve_Test(SNES snes) { Mat A = snes->jacobian,B; Vec x = snes->vec_sol,f = snes->vec_func,f1 = snes->vec_sol_update; PetscErrorCode ierr; PetscInt i; PetscReal nrm,gnorm; SNES_Test *neP = (SNES_Test*)snes->data; PetscErrorCode (*objective)(SNES,Vec,PetscReal*,void*); void *ctx; PetscReal fnorm,f1norm,dnorm; PetscFunctionBegin; if (A != snes->jacobian_pre) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Cannot test with alternative preconditioner"); ierr = PetscPrintf(PetscObjectComm((PetscObject)snes),"Testing hand-coded Jacobian, if the ratio is\n");CHKERRQ(ierr); ierr = PetscPrintf(PetscObjectComm((PetscObject)snes),"O(1.e-8), the hand-coded Jacobian is probably correct.\n");CHKERRQ(ierr); if (!neP->complete_print) { ierr = PetscPrintf(PetscObjectComm((PetscObject)snes),"Run with -snes_test_display to show difference\n");CHKERRQ(ierr); ierr = PetscPrintf(PetscObjectComm((PetscObject)snes),"of hand-coded and finite difference Jacobian.\n");CHKERRQ(ierr); } for (i=0; i<3; i++) { void *functx; static const char *const loc[] = {"user-defined state","constant state -1.0","constant state 1.0"}; PetscInt m,n,M,N; if (i == 1) { ierr = VecSet(x,-1.0);CHKERRQ(ierr); } else if (i == 2) { ierr = VecSet(x,1.0);CHKERRQ(ierr); } /* evaluate the function at this point because SNESComputeJacobianDefaultColor() assumes that the function has been evaluated and put into snes->vec_func */ ierr = SNESComputeFunction(snes,x,f);CHKERRQ(ierr); if (snes->domainerror) { ierr = PetscPrintf(PetscObjectComm((PetscObject)snes),"Domain error at %s\n",loc[i]);CHKERRQ(ierr); snes->domainerror = PETSC_FALSE; continue; } /* compute both versions of Jacobian */ ierr = SNESComputeJacobian(snes,x,A,A);CHKERRQ(ierr); ierr = MatCreate(PetscObjectComm((PetscObject)A),&B);CHKERRQ(ierr); ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr); ierr = MatGetLocalSize(A,&m,&n);CHKERRQ(ierr); ierr = MatSetSizes(B,m,n,M,N);CHKERRQ(ierr); ierr = MatSetType(B,((PetscObject)A)->type_name);CHKERRQ(ierr); ierr = MatSetUp(B);CHKERRQ(ierr); ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr); ierr = SNESGetFunction(snes,NULL,NULL,&functx);CHKERRQ(ierr); ierr = SNESComputeJacobianDefault(snes,x,B,B,functx);CHKERRQ(ierr); if (neP->complete_print) { MPI_Comm comm; PetscViewer viewer; ierr = PetscPrintf(PetscObjectComm((PetscObject)snes),"Finite difference Jacobian (%s)\n",loc[i]);CHKERRQ(ierr); ierr = PetscObjectGetComm((PetscObject)B,&comm);CHKERRQ(ierr); ierr = PetscViewerASCIIGetStdout(comm,&viewer);CHKERRQ(ierr); ierr = MatView(B,viewer);CHKERRQ(ierr); } /* compare */ ierr = MatAYPX(B,-1.0,A,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); ierr = MatNorm(B,NORM_FROBENIUS,&nrm);CHKERRQ(ierr); ierr = MatNorm(A,NORM_FROBENIUS,&gnorm);CHKERRQ(ierr); if (neP->complete_print) { MPI_Comm comm; PetscViewer viewer; ierr = PetscPrintf(PetscObjectComm((PetscObject)snes),"Hand-coded Jacobian (%s)\n",loc[i]);CHKERRQ(ierr); ierr = PetscObjectGetComm((PetscObject)B,&comm);CHKERRQ(ierr); ierr = PetscViewerASCIIGetStdout(comm,&viewer);CHKERRQ(ierr); ierr = MatView(A,viewer);CHKERRQ(ierr); ierr = PetscPrintf(PetscObjectComm((PetscObject)snes),"Hand-coded minus finite difference Jacobian (%s)\n",loc[i]);CHKERRQ(ierr); ierr = MatView(B,viewer);CHKERRQ(ierr); } if (!gnorm) gnorm = 1; /* just in case */ ierr = PetscPrintf(PetscObjectComm((PetscObject)snes),"Norm of matrix ratio %g difference %g (%s)\n",(double)(nrm/gnorm),(double)nrm,loc[i]);CHKERRQ(ierr); ierr = SNESGetObjective(snes,&objective,&ctx);CHKERRQ(ierr); if (objective) { ierr = SNESComputeFunction(snes,x,f);CHKERRQ(ierr); ierr = VecNorm(f,NORM_2,&fnorm);CHKERRQ(ierr); if (neP->complete_print) { PetscViewer viewer; ierr = PetscPrintf(PetscObjectComm((PetscObject)snes),"Hand-coded Function (%s)\n",loc[i]);CHKERRQ(ierr); ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes),&viewer);CHKERRQ(ierr); ierr = VecView(f,viewer);CHKERRQ(ierr); } ierr = SNESObjectiveComputeFunctionDefaultFD(snes,x,f1,NULL);CHKERRQ(ierr); ierr = VecNorm(f1,NORM_2,&f1norm);CHKERRQ(ierr); if (neP->complete_print) { PetscViewer viewer; ierr = PetscPrintf(PetscObjectComm((PetscObject)snes),"Finite-Difference Function (%s)\n",loc[i]);CHKERRQ(ierr); ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes),&viewer);CHKERRQ(ierr); ierr = VecView(f1,viewer);CHKERRQ(ierr); } /* compare the two */ ierr = VecAXPY(f,-1.0,f1);CHKERRQ(ierr); ierr = VecNorm(f,NORM_2,&dnorm);CHKERRQ(ierr); if (!fnorm) fnorm = 1.; ierr = PetscPrintf(PetscObjectComm((PetscObject)snes),"Norm of function ratio %g difference %g (%s)\n",dnorm/fnorm,dnorm,loc[i]);CHKERRQ(ierr); if (neP->complete_print) { PetscViewer viewer; ierr = PetscPrintf(PetscObjectComm((PetscObject)snes),"Difference (%s)\n",loc[i]);CHKERRQ(ierr); ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes),&viewer);CHKERRQ(ierr); ierr = VecView(f,viewer);CHKERRQ(ierr); } } ierr = MatDestroy(&B);CHKERRQ(ierr); } /* Abort after the first iteration due to the jacobian not being valid. */ SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"SNESTest aborts after Jacobian test"); PetscFunctionReturn(0); }
/*@C SNESUpdateCheckJacobian - Checks each Jacobian computed by the nonlinear solver comparing the users function with a finite difference computation. Options Database: + -snes_check_jacobian - use this every time SNESSolve() is called - -snes_check_jacobian_view - Display difference between approximate and hand-coded Jacobian Level: intermediate .seealso: SNESCreate(), SNES, SNESSetType(), SNESNEWTONLS, SNESNEWTONTR, SNESSolve() @*/ PetscErrorCode SNESUpdateCheckJacobian(SNES snes,PetscInt it) { Mat A = snes->jacobian,B; Vec x = snes->vec_sol,f = snes->vec_func,f1 = snes->vec_sol_update; PetscErrorCode ierr; PetscReal nrm,gnorm; PetscErrorCode (*objective)(SNES,Vec,PetscReal*,void*); void *ctx; PetscReal fnorm,f1norm,dnorm; PetscInt m,n,M,N; PetscBool complete_print = PETSC_FALSE; void *functx; PetscViewer viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)); PetscFunctionBegin; ierr = PetscOptionsHasName(((PetscObject)snes)->prefix,"-snes_check_jacobian_view",&complete_print);CHKERRQ(ierr); if (A != snes->jacobian_pre) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Cannot check Jacobian with alternative preconditioner"); ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); ierr = PetscViewerASCIIPrintf(viewer," Testing hand-coded Jacobian, if the ratio is O(1.e-8), the hand-coded Jacobian is probably correct.\n");CHKERRQ(ierr); if (!complete_print) { ierr = PetscViewerASCIIPrintf(viewer," Run with -snes_check_jacobian_view [viewer][:filename][:format] to show difference of hand-coded and finite difference Jacobian.\n");CHKERRQ(ierr); } /* compute both versions of Jacobian */ ierr = SNESComputeJacobian(snes,x,A,A);CHKERRQ(ierr); ierr = MatCreate(PetscObjectComm((PetscObject)A),&B);CHKERRQ(ierr); ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr); ierr = MatGetLocalSize(A,&m,&n);CHKERRQ(ierr); ierr = MatSetSizes(B,m,n,M,N);CHKERRQ(ierr); ierr = MatSetType(B,((PetscObject)A)->type_name);CHKERRQ(ierr); ierr = MatSetUp(B);CHKERRQ(ierr); ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr); ierr = SNESGetFunction(snes,NULL,NULL,&functx);CHKERRQ(ierr); ierr = SNESComputeJacobianDefault(snes,x,B,B,functx);CHKERRQ(ierr); if (complete_print) { ierr = PetscViewerASCIIPrintf(viewer," Finite difference Jacobian\n");CHKERRQ(ierr); ierr = MatViewFromOptions(B,((PetscObject)snes)->prefix,"-snes_check_jacobian_view");CHKERRQ(ierr); } /* compare */ ierr = MatAYPX(B,-1.0,A,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); ierr = MatNorm(B,NORM_FROBENIUS,&nrm);CHKERRQ(ierr); ierr = MatNorm(A,NORM_FROBENIUS,&gnorm);CHKERRQ(ierr); if (complete_print) { ierr = PetscViewerASCIIPrintf(viewer," Hand-coded Jacobian\n");CHKERRQ(ierr); ierr = MatViewFromOptions(A,((PetscObject)snes)->prefix,"-snes_check_jacobian_view");CHKERRQ(ierr); ierr = PetscViewerASCIIPrintf(viewer," Hand-coded minus finite difference Jacobian\n");CHKERRQ(ierr); ierr = MatViewFromOptions(B,((PetscObject)snes)->prefix,"-snes_check_jacobian_view");CHKERRQ(ierr); } if (!gnorm) gnorm = 1; /* just in case */ ierr = PetscViewerASCIIPrintf(viewer," %g = ||J - Jfd||//J|| %g = ||J - Jfd||\n",(double)(nrm/gnorm),(double)nrm);CHKERRQ(ierr); ierr = SNESGetObjective(snes,&objective,&ctx);CHKERRQ(ierr); if (objective) { ierr = SNESComputeFunction(snes,x,f);CHKERRQ(ierr); ierr = VecNorm(f,NORM_2,&fnorm);CHKERRQ(ierr); if (complete_print) { ierr = PetscViewerASCIIPrintf(viewer," Hand-coded Objective Function \n");CHKERRQ(ierr); ierr = VecView(f,viewer);CHKERRQ(ierr); } ierr = SNESObjectiveComputeFunctionDefaultFD(snes,x,f1,NULL);CHKERRQ(ierr); ierr = VecNorm(f1,NORM_2,&f1norm);CHKERRQ(ierr); if (complete_print) { ierr = PetscViewerASCIIPrintf(viewer," Finite-Difference Objective Function\n");CHKERRQ(ierr); ierr = VecView(f1,viewer);CHKERRQ(ierr); } /* compare the two */ ierr = VecAXPY(f,-1.0,f1);CHKERRQ(ierr); ierr = VecNorm(f,NORM_2,&dnorm);CHKERRQ(ierr); if (!fnorm) fnorm = 1.; ierr = PetscViewerASCIIPrintf(viewer," %g = Norm of objective function ratio %g = difference\n",dnorm/fnorm,dnorm);CHKERRQ(ierr); if (complete_print) { ierr = PetscViewerASCIIPrintf(viewer," Difference\n");CHKERRQ(ierr); ierr = VecView(f,viewer);CHKERRQ(ierr); } } ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); ierr = MatDestroy(&B);CHKERRQ(ierr); PetscFunctionReturn(0); }
PETSC_EXTERN PetscErrorCode SNESComputeNGSDefaultSecant(SNES snes,Vec X,Vec B,void *ctx) { PetscErrorCode ierr; SNES_NGS *gs = (SNES_NGS*)snes->data; PetscInt i,j,k,ncolors; DM dm; PetscBool flg; ISColoring coloring = gs->coloring; MatColoring mc; Vec W,G,F; PetscScalar h=gs->h; IS *coloris; PetscScalar f,g,x,w,d; PetscReal dxt,xt,ft,ft1=0; const PetscInt *idx; PetscInt size,s; PetscReal atol,rtol,stol; PetscInt its; PetscErrorCode (*func)(SNES,Vec,Vec,void*); void *fctx; PetscBool mat = gs->secant_mat,equal,isdone,alldone; PetscScalar *xa,*fa,*wa,*ga; PetscFunctionBegin; if (snes->nwork < 3) { ierr = SNESSetWorkVecs(snes,3);CHKERRQ(ierr); } W = snes->work[0]; G = snes->work[1]; F = snes->work[2]; ierr = VecGetOwnershipRange(X,&s,NULL);CHKERRQ(ierr); ierr = SNESNGSGetTolerances(snes,&atol,&rtol,&stol,&its);CHKERRQ(ierr); ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); ierr = SNESGetFunction(snes,NULL,&func,&fctx);CHKERRQ(ierr); if (!coloring) { /* create the coloring */ ierr = DMHasColoring(dm,&flg);CHKERRQ(ierr); if (flg && !mat) { ierr = DMCreateColoring(dm,IS_COLORING_GLOBAL,&coloring);CHKERRQ(ierr); } else { if (!snes->jacobian) {ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr);} ierr = MatColoringCreate(snes->jacobian,&mc);CHKERRQ(ierr); ierr = MatColoringSetDistance(mc,1);CHKERRQ(ierr); ierr = MatColoringSetFromOptions(mc);CHKERRQ(ierr); ierr = MatColoringApply(mc,&coloring);CHKERRQ(ierr); ierr = MatColoringDestroy(&mc);CHKERRQ(ierr); } gs->coloring = coloring; } ierr = ISColoringGetIS(coloring,&ncolors,&coloris);CHKERRQ(ierr); ierr = VecEqual(X,snes->vec_sol,&equal);CHKERRQ(ierr); if (equal && snes->normschedule == SNES_NORM_ALWAYS) { /* assume that the function is already computed */ ierr = VecCopy(snes->vec_func,F);CHKERRQ(ierr); } else { ierr = PetscLogEventBegin(SNES_NGSFuncEval,snes,X,B,0);CHKERRQ(ierr); ierr = (*func)(snes,X,F,fctx);CHKERRQ(ierr); ierr = PetscLogEventEnd(SNES_NGSFuncEval,snes,X,B,0);CHKERRQ(ierr); if (B) {ierr = VecAXPY(F,-1.0,B);CHKERRQ(ierr);} } ierr = VecGetArray(X,&xa);CHKERRQ(ierr); ierr = VecGetArray(F,&fa);CHKERRQ(ierr); ierr = VecGetArray(G,&ga);CHKERRQ(ierr); ierr = VecGetArray(W,&wa);CHKERRQ(ierr); for (i=0;i<ncolors;i++) { ierr = ISGetIndices(coloris[i],&idx);CHKERRQ(ierr); ierr = ISGetLocalSize(coloris[i],&size);CHKERRQ(ierr); ierr = VecCopy(X,W);CHKERRQ(ierr); for (j=0;j<size;j++) { wa[idx[j]-s] += h; } ierr = PetscLogEventBegin(SNES_NGSFuncEval,snes,X,B,0);CHKERRQ(ierr); ierr = (*func)(snes,W,G,fctx);CHKERRQ(ierr); ierr = PetscLogEventEnd(SNES_NGSFuncEval,snes,X,B,0);CHKERRQ(ierr); if (B) {ierr = VecAXPY(G,-1.0,B);CHKERRQ(ierr);} for (k=0;k<its;k++) { dxt = 0.; xt = 0.; ft = 0.; for (j=0;j<size;j++) { f = fa[idx[j]-s]; x = xa[idx[j]-s]; g = ga[idx[j]-s]; w = wa[idx[j]-s]; if (PetscAbsScalar(g-f) > atol) { /* This is equivalent to d = x - (h*f) / PetscRealPart(g-f) */ d = (x*g-w*f) / PetscRealPart(g-f); } else { d = x; } dxt += PetscRealPart(PetscSqr(d-x)); xt += PetscRealPart(PetscSqr(x)); ft += PetscRealPart(PetscSqr(f)); xa[idx[j]-s] = d; } if (k == 0) ft1 = PetscSqrtReal(ft); if (k<its-1) { isdone = PETSC_FALSE; if (stol*PetscSqrtReal(xt) > PetscSqrtReal(dxt)) isdone = PETSC_TRUE; if (PetscSqrtReal(ft) < atol) isdone = PETSC_TRUE; if (rtol*ft1 > PetscSqrtReal(ft)) isdone = PETSC_TRUE; ierr = MPIU_Allreduce(&isdone,&alldone,1,MPIU_BOOL,MPI_BAND,PetscObjectComm((PetscObject)snes));CHKERRQ(ierr); if (alldone) break; } if (i < ncolors-1 || k < its-1) { ierr = PetscLogEventBegin(SNES_NGSFuncEval,snes,X,B,0);CHKERRQ(ierr); ierr = (*func)(snes,X,F,fctx);CHKERRQ(ierr); ierr = PetscLogEventEnd(SNES_NGSFuncEval,snes,X,B,0);CHKERRQ(ierr); if (B) {ierr = VecAXPY(F,-1.0,B);CHKERRQ(ierr);} } if (k<its-1) { ierr = VecSwap(X,W);CHKERRQ(ierr); ierr = VecSwap(F,G);CHKERRQ(ierr); } } } ierr = VecRestoreArray(X,&xa);CHKERRQ(ierr); ierr = VecRestoreArray(F,&fa);CHKERRQ(ierr); ierr = VecRestoreArray(G,&ga);CHKERRQ(ierr); ierr = VecRestoreArray(W,&wa);CHKERRQ(ierr); ierr = ISColoringRestoreIS(coloring,&coloris);CHKERRQ(ierr); PetscFunctionReturn(0); }