xref: /petsc/src/snes/impls/ksponly/ksponly.c (revision 7d0a6c19129e7069c8a40e210b34ed62989173db)
1 
2 #include "private/snesimpl.h"
3 
4 #undef __FUNCT__
5 #define __FUNCT__ "SNESSolve_KSPONLY"
6 static PetscErrorCode SNESSolve_KSPONLY(SNES snes)
7 {
8   PetscErrorCode     ierr;
9   PetscInt           lits;
10   MatStructure       flg = DIFFERENT_NONZERO_PATTERN;
11   Vec                Y,X,F;
12   KSPConvergedReason kspreason;
13 
14   PetscFunctionBegin;
15   snes->numFailures            = 0;
16   snes->numLinearSolveFailures = 0;
17   snes->reason                 = SNES_CONVERGED_ITERATING;
18   snes->iter                   = 0;
19   snes->norm                   = 0.0;
20 
21   X = snes->vec_sol;
22   F = snes->vec_func;
23   Y = snes->vec_sol_update;
24 
25   ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);
26   if (snes->domainerror) {
27     snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
28     PetscFunctionReturn(0);
29   }
30 
31   /* Solve J Y = F, where J is Jacobian matrix */
32   ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr);
33   ierr = KSPSetOperators(snes->ksp,snes->jacobian,snes->jacobian_pre,flg);CHKERRQ(ierr);
34   ierr = KSPSolve(snes->ksp,F,Y);CHKERRQ(ierr);
35   ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr);
36   if (kspreason < 0 && ++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) {
37     ierr = PetscInfo2(snes,"iter=%D, number linear solve failures %D greater than current SNES allowed, stopping solve\n",snes->iter,snes->numLinearSolveFailures);CHKERRQ(ierr);
38     snes->reason = SNES_DIVERGED_LINEAR_SOLVE;
39   } else {
40     snes->reason = SNES_CONVERGED_ITS;
41   }
42   ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr);
43   snes->linear_its += lits;
44   ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr);
45   snes->iter++;
46 
47   /* Take the computed step. */
48   ierr = VecAXPY(X,-1.0,Y);CHKERRQ(ierr);
49   PetscFunctionReturn(0);
50 }
51 
52 #undef __FUNCT__
53 #define __FUNCT__ "SNESSetUp_KSPONLY"
54 static PetscErrorCode SNESSetUp_KSPONLY(SNES snes)
55 {
56   PetscErrorCode ierr;
57 
58   PetscFunctionBegin;
59   if (!snes->vec_sol_update) {
60     ierr = VecDuplicate(snes->vec_sol,&snes->vec_sol_update);CHKERRQ(ierr);
61     ierr = PetscLogObjectParent(snes,snes->vec_sol_update);CHKERRQ(ierr);
62   }
63   PetscFunctionReturn(0);
64 }
65 
66 #undef __FUNCT__
67 #define __FUNCT__ "SNESDestroy_KSPONLY"
68 static PetscErrorCode SNESDestroy_KSPONLY(SNES snes)
69 {
70   PetscErrorCode ierr;
71 
72   PetscFunctionBegin;
73   if (snes->vec_sol_update) {
74     ierr = VecDestroy(snes->vec_sol_update);CHKERRQ(ierr);
75     snes->vec_sol_update = PETSC_NULL;
76   }
77   PetscFunctionReturn(0);
78 }
79 
80 /* -------------------------------------------------------------------------- */
81 /*MC
82       SNESKSPONLY - Nonlinear solver that only performs one Newton step and does not compute any norms.
83       The main purpose of this solver is to solve linear problems using the SNES interface, without
84       any additional overhead in the form of vector operations.
85 
86    Level: beginner
87 
88 .seealso:  SNESCreate(), SNES, SNESSetType(), SNESLS, SNESTR
89 M*/
90 EXTERN_C_BEGIN
91 #undef __FUNCT__
92 #define __FUNCT__ "SNESCreate_KSPONLY"
93 PetscErrorCode  SNESCreate_KSPONLY(SNES snes)
94 {
95 
96   PetscFunctionBegin;
97   snes->ops->setup   = SNESSetUp_KSPONLY;
98   snes->ops->solve   = SNESSolve_KSPONLY;
99   snes->ops->destroy = SNESDestroy_KSPONLY;
100 
101   snes->data = 0;
102   PetscFunctionReturn(0);
103 }
104 EXTERN_C_END
105