xref: /petsc/src/snes/impls/ksponly/ksponly.c (revision a3e9d6632d9bda87d274e9884e941190278421bd)
11ef27442SStefano Zampini #include <petsc/private/snesimpl.h> /*I   "petscsnes.h"   I*/
2b79b07cfSJed Brown 
31ef27442SStefano Zampini typedef struct {
41ef27442SStefano Zampini   PetscBool transpose_solve;
51ef27442SStefano Zampini } SNES_KSPONLY;
6b79b07cfSJed Brown 
7d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSolve_KSPONLY(SNES snes)
8d71ae5a4SJacob Faibussowitsch {
91ef27442SStefano Zampini   SNES_KSPONLY    *ksponly = (SNES_KSPONLY *)snes->data;
10b79b07cfSJed Brown   PetscInt         lits;
11b79b07cfSJed Brown   Vec              Y, X, F;
12*a3e9d663SJames Wright   SNESNormSchedule normschedule;
13b79b07cfSJed Brown 
14b79b07cfSJed Brown   PetscFunctionBegin;
150b121fc5SBarry Smith   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);
16c579b300SPatrick Farrell 
17b79b07cfSJed Brown   snes->numFailures            = 0;
18b79b07cfSJed Brown   snes->numLinearSolveFailures = 0;
19b79b07cfSJed Brown   snes->reason                 = SNES_CONVERGED_ITERATING;
20b79b07cfSJed Brown   snes->iter                   = 0;
21b79b07cfSJed Brown   snes->norm                   = 0.0;
22b79b07cfSJed Brown 
23b79b07cfSJed Brown   X = snes->vec_sol;
24b79b07cfSJed Brown   F = snes->vec_func;
25b79b07cfSJed Brown   Y = snes->vec_sol_update;
26b79b07cfSJed Brown 
27451891c6SStefano Zampini   if (!snes->vec_func_init_set) {
289566063dSJacob Faibussowitsch     PetscCall(SNESComputeFunction(snes, X, F));
29451891c6SStefano Zampini   } else snes->vec_func_init_set = PETSC_FALSE;
30451891c6SStefano Zampini 
31*a3e9d663SJames Wright   PetscCall(SNESGetNormSchedule(snes, &normschedule));
32*a3e9d663SJames Wright   if (snes->numbermonitors && (normschedule == SNES_NORM_ALWAYS || normschedule == SNES_NORM_INITIAL_ONLY || normschedule == SNES_NORM_INITIAL_FINAL_ONLY)) {
33a5eaddd9SBarry Smith     PetscReal fnorm;
349566063dSJacob Faibussowitsch     PetscCall(VecNorm(F, NORM_2, &fnorm));
355f3c5e7aSBarry Smith     SNESCheckFunctionNorm(snes, fnorm);
369566063dSJacob Faibussowitsch     PetscCall(SNESMonitor(snes, 0, fnorm));
37a5eaddd9SBarry Smith   }
38b79b07cfSJed Brown 
395341784dSBarry Smith   /* Call general purpose update function */
40dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, update, 0);
415341784dSBarry Smith 
42b79b07cfSJed Brown   /* Solve J Y = F, where J is Jacobian matrix */
439566063dSJacob Faibussowitsch   PetscCall(SNESComputeJacobian(snes, X, snes->jacobian, snes->jacobian_pre));
4407b62357SFande Kong 
4507b62357SFande Kong   SNESCheckJacobianDomainerror(snes);
4607b62357SFande Kong 
479566063dSJacob Faibussowitsch   PetscCall(KSPSetOperators(snes->ksp, snes->jacobian, snes->jacobian_pre));
481ef27442SStefano Zampini   if (ksponly->transpose_solve) {
499566063dSJacob Faibussowitsch     PetscCall(KSPSolveTranspose(snes->ksp, F, Y));
501ef27442SStefano Zampini   } else {
519566063dSJacob Faibussowitsch     PetscCall(KSPSolve(snes->ksp, F, Y));
521ef27442SStefano Zampini   }
53422a814eSBarry Smith   snes->reason = SNES_CONVERGED_ITS;
54422a814eSBarry Smith   SNESCheckKSPSolve(snes);
551aa26658SKarl Rupp 
569566063dSJacob Faibussowitsch   PetscCall(KSPGetIterationNumber(snes->ksp, &lits));
5763a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(snes, "iter=%" PetscInt_FMT ", linear solve iterations=%" PetscInt_FMT "\n", snes->iter, lits));
58b79b07cfSJed Brown   snes->iter++;
59b79b07cfSJed Brown 
60b79b07cfSJed Brown   /* Take the computed step. */
619566063dSJacob Faibussowitsch   PetscCall(VecAXPY(X, -1.0, Y));
62*a3e9d663SJames Wright 
63*a3e9d663SJames Wright   if (snes->numbermonitors && (normschedule == SNES_NORM_ALWAYS || normschedule == SNES_NORM_FINAL_ONLY || normschedule == SNES_NORM_INITIAL_FINAL_ONLY)) {
64a5eaddd9SBarry Smith     PetscReal fnorm;
659566063dSJacob Faibussowitsch     PetscCall(SNESComputeFunction(snes, X, F));
669566063dSJacob Faibussowitsch     PetscCall(VecNorm(F, NORM_2, &fnorm));
675f3c5e7aSBarry Smith     SNESCheckFunctionNorm(snes, fnorm);
689566063dSJacob Faibussowitsch     PetscCall(SNESMonitor(snes, 1, fnorm));
69a5eaddd9SBarry Smith   }
703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
71b79b07cfSJed Brown }
72b79b07cfSJed Brown 
73d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetUp_KSPONLY(SNES snes)
74d71ae5a4SJacob Faibussowitsch {
75b79b07cfSJed Brown   PetscFunctionBegin;
769566063dSJacob Faibussowitsch   PetscCall(SNESSetUpMatrices(snes));
773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
78b79b07cfSJed Brown }
79b79b07cfSJed Brown 
80d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESDestroy_KSPONLY(SNES snes)
81d71ae5a4SJacob Faibussowitsch {
82b79b07cfSJed Brown   PetscFunctionBegin;
839566063dSJacob Faibussowitsch   PetscCall(PetscFree(snes->data));
843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
85b79b07cfSJed Brown }
86b79b07cfSJed Brown 
87b79b07cfSJed Brown /*MC
88420bcc1bSBarry Smith    SNESKSPONLY - Nonlinear solver that performs one Newton step with `KSPSolve()` and does not compute any norms.
89b79b07cfSJed Brown 
90b79b07cfSJed Brown    Level: beginner
91b79b07cfSJed Brown 
92420bcc1bSBarry Smith    Note:
93420bcc1bSBarry Smith    The main purpose of this solver is to solve linear problems using the `SNES` interface, without
94420bcc1bSBarry Smith    any additional overhead in the form of vector norm operations.
95420bcc1bSBarry Smith 
96420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESType`, `SNESCreate()`, `SNES`, `SNESSetType()`, `SNESNEWTONLS`, `SNESNEWTONTR`, `SNESKSPTRANSPOSEONLY`
97b79b07cfSJed Brown M*/
98d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode SNESCreate_KSPONLY(SNES snes)
99d71ae5a4SJacob Faibussowitsch {
1001ef27442SStefano Zampini   SNES_KSPONLY *ksponly;
101b79b07cfSJed Brown 
102b79b07cfSJed Brown   PetscFunctionBegin;
103b79b07cfSJed Brown   snes->ops->setup          = SNESSetUp_KSPONLY;
104b79b07cfSJed Brown   snes->ops->solve          = SNESSolve_KSPONLY;
105b79b07cfSJed Brown   snes->ops->destroy        = SNESDestroy_KSPONLY;
1069e5d0892SLisandro Dalcin   snes->ops->setfromoptions = NULL;
1079e5d0892SLisandro Dalcin   snes->ops->view           = NULL;
1089e5d0892SLisandro Dalcin   snes->ops->reset          = NULL;
109b79b07cfSJed Brown 
11042f4f86dSBarry Smith   snes->usesksp = PETSC_TRUE;
111efd4aadfSBarry Smith   snes->usesnpc = PETSC_FALSE;
11242f4f86dSBarry Smith 
1134fc747eaSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
1144fc747eaSLawrence Mitchell 
11577e5a1f9SBarry Smith   PetscCall(SNESParametersInitialize(snes));
11677e5a1f9SBarry Smith 
1174dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&ksponly));
1181ef27442SStefano Zampini   snes->data = (void *)ksponly;
1193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1201ef27442SStefano Zampini }
1211ef27442SStefano Zampini 
1221ef27442SStefano Zampini /*MC
123420bcc1bSBarry Smith    SNESKSPTRANSPOSEONLY - Nonlinear solver that performs one Newton step with `KSPSolveTranspose()` and does not compute any norms.
1241ef27442SStefano Zampini 
1251ef27442SStefano Zampini    Level: beginner
1261ef27442SStefano Zampini 
127420bcc1bSBarry Smith    Note:
128420bcc1bSBarry Smith    The main purpose of this solver is to solve transposed linear problems using the `SNES` interface, without
129420bcc1bSBarry Smith    any additional overhead in the form of vector operations within adjoint solvers.
130420bcc1bSBarry Smith 
131420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESType`, `SNESCreate()`, `SNES`, `SNESSetType()`, `SNESKS`, `SNESNEWTONLS`, `SNESNEWTONTR`
1321ef27442SStefano Zampini M*/
133d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode SNESCreate_KSPTRANSPOSEONLY(SNES snes)
134d71ae5a4SJacob Faibussowitsch {
1351ef27442SStefano Zampini   SNES_KSPONLY *kspo;
1361ef27442SStefano Zampini 
1371ef27442SStefano Zampini   PetscFunctionBegin;
1389566063dSJacob Faibussowitsch   PetscCall(SNESCreate_KSPONLY(snes));
1399566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)snes, SNESKSPTRANSPOSEONLY));
1401ef27442SStefano Zampini   kspo                  = (SNES_KSPONLY *)snes->data;
1411ef27442SStefano Zampini   kspo->transpose_solve = PETSC_TRUE;
1423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
143b79b07cfSJed Brown }
144