xref: /petsc/src/snes/impls/ksponly/ksponly.c (revision a4e35b1925eceef64945ea472b84f2bf06a67b5e)
1 #include <petsc/private/snesimpl.h> /*I   "petscsnes.h"   I*/
2 
3 typedef struct {
4   PetscBool transpose_solve;
5 } SNES_KSPONLY;
6 
7 static PetscErrorCode SNESSolve_KSPONLY(SNES snes)
8 {
9   SNES_KSPONLY *ksponly = (SNES_KSPONLY *)snes->data;
10   PetscInt      lits;
11   Vec           Y, X, F;
12 
13   PetscFunctionBegin;
14   PetscCheck(!snes->xl && !snes->xu && !snes->ops->computevariablebounds, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONGSTATE, "SNES solver %s does not support bounds", ((PetscObject)snes)->type_name);
15 
16   snes->numFailures            = 0;
17   snes->numLinearSolveFailures = 0;
18   snes->reason                 = SNES_CONVERGED_ITERATING;
19   snes->iter                   = 0;
20   snes->norm                   = 0.0;
21 
22   X = snes->vec_sol;
23   F = snes->vec_func;
24   Y = snes->vec_sol_update;
25 
26   if (!snes->vec_func_init_set) {
27     PetscCall(SNESComputeFunction(snes, X, F));
28   } else snes->vec_func_init_set = PETSC_FALSE;
29 
30   if (snes->numbermonitors) {
31     PetscReal fnorm;
32     PetscCall(VecNorm(F, NORM_2, &fnorm));
33     SNESCheckFunctionNorm(snes, fnorm);
34     PetscCall(SNESMonitor(snes, 0, fnorm));
35   }
36 
37   /* Call general purpose update function */
38   PetscTryTypeMethod(snes, update, 0);
39 
40   /* Solve J Y = F, where J is Jacobian matrix */
41   PetscCall(SNESComputeJacobian(snes, X, snes->jacobian, snes->jacobian_pre));
42 
43   SNESCheckJacobianDomainerror(snes);
44 
45   PetscCall(KSPSetOperators(snes->ksp, snes->jacobian, snes->jacobian_pre));
46   if (ksponly->transpose_solve) {
47     PetscCall(KSPSolveTranspose(snes->ksp, F, Y));
48   } else {
49     PetscCall(KSPSolve(snes->ksp, F, Y));
50   }
51   snes->reason = SNES_CONVERGED_ITS;
52   SNESCheckKSPSolve(snes);
53 
54   PetscCall(KSPGetIterationNumber(snes->ksp, &lits));
55   PetscCall(PetscInfo(snes, "iter=%" PetscInt_FMT ", linear solve iterations=%" PetscInt_FMT "\n", snes->iter, lits));
56   snes->iter++;
57 
58   /* Take the computed step. */
59   PetscCall(VecAXPY(X, -1.0, Y));
60   if (snes->numbermonitors) {
61     PetscReal fnorm;
62     PetscCall(SNESComputeFunction(snes, X, F));
63     PetscCall(VecNorm(F, NORM_2, &fnorm));
64     SNESCheckFunctionNorm(snes, fnorm);
65     PetscCall(SNESMonitor(snes, 1, fnorm));
66   }
67   PetscFunctionReturn(PETSC_SUCCESS);
68 }
69 
70 static PetscErrorCode SNESSetUp_KSPONLY(SNES snes)
71 {
72   PetscFunctionBegin;
73   PetscCall(SNESSetUpMatrices(snes));
74   PetscFunctionReturn(PETSC_SUCCESS);
75 }
76 
77 static PetscErrorCode SNESDestroy_KSPONLY(SNES snes)
78 {
79   PetscFunctionBegin;
80   PetscCall(PetscFree(snes->data));
81   PetscFunctionReturn(PETSC_SUCCESS);
82 }
83 
84 /*MC
85       SNESKSPONLY - Nonlinear solver that performs one Newton step and does not compute any norms.
86       The main purpose of this solver is to solve linear problems using the `SNES` interface, without
87       any additional overhead in the form of vector operations.
88 
89    Level: beginner
90 
91 .seealso: `SNES`, `SNESType`, `SNESCreate()`, `SNES`, `SNESSetType()`, `SNESNEWTONLS`, `SNESNEWTONTR`
92 M*/
93 PETSC_EXTERN PetscErrorCode SNESCreate_KSPONLY(SNES snes)
94 {
95   SNES_KSPONLY *ksponly;
96 
97   PetscFunctionBegin;
98   snes->ops->setup          = SNESSetUp_KSPONLY;
99   snes->ops->solve          = SNESSolve_KSPONLY;
100   snes->ops->destroy        = SNESDestroy_KSPONLY;
101   snes->ops->setfromoptions = NULL;
102   snes->ops->view           = NULL;
103   snes->ops->reset          = NULL;
104 
105   snes->usesksp = PETSC_TRUE;
106   snes->usesnpc = PETSC_FALSE;
107 
108   snes->alwayscomputesfinalresidual = PETSC_FALSE;
109 
110   PetscCall(PetscNew(&ksponly));
111   snes->data = (void *)ksponly;
112   PetscFunctionReturn(PETSC_SUCCESS);
113 }
114 
115 /*MC
116       SNESKSPTRANSPOSEONLY - Nonlinear solver that performs one Newton step and does not compute any norms.
117       The main purpose of this solver is to solve transposed linear problems using the `SNES` interface, without
118       any additional overhead in the form of vector operations within adjoint solvers.
119 
120    Level: beginner
121 
122 .seealso: `SNES`, `SNESType`, `SNESCreate()`, `SNES`, `SNESSetType()`, `SNESKSPTRANSPOSEONLY`, `SNESNEWTONLS`, `SNESNEWTONTR`
123 M*/
124 PETSC_EXTERN PetscErrorCode SNESCreate_KSPTRANSPOSEONLY(SNES snes)
125 {
126   SNES_KSPONLY *kspo;
127 
128   PetscFunctionBegin;
129   PetscCall(SNESCreate_KSPONLY(snes));
130   PetscCall(PetscObjectChangeTypeName((PetscObject)snes, SNESKSPTRANSPOSEONLY));
131   kspo                  = (SNES_KSPONLY *)snes->data;
132   kspo->transpose_solve = PETSC_TRUE;
133   PetscFunctionReturn(PETSC_SUCCESS);
134 }
135