xref: /petsc/src/snes/impls/ksponly/ksponly.c (revision dbbe0bcd3f3a8fbab5a45420dc06f8387e5764c6)
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 
7b79b07cfSJed Brown static PetscErrorCode SNESSolve_KSPONLY(SNES snes)
8b79b07cfSJed Brown {
91ef27442SStefano Zampini   SNES_KSPONLY   *ksponly = (SNES_KSPONLY*)snes->data;
10b79b07cfSJed Brown   PetscInt       lits;
11b79b07cfSJed Brown   Vec            Y,X,F;
12b79b07cfSJed Brown 
13b79b07cfSJed Brown   PetscFunctionBegin;
140b121fc5SBarry 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);
15c579b300SPatrick Farrell 
16b79b07cfSJed Brown   snes->numFailures            = 0;
17b79b07cfSJed Brown   snes->numLinearSolveFailures = 0;
18b79b07cfSJed Brown   snes->reason                 = SNES_CONVERGED_ITERATING;
19b79b07cfSJed Brown   snes->iter                   = 0;
20b79b07cfSJed Brown   snes->norm                   = 0.0;
21b79b07cfSJed Brown 
22b79b07cfSJed Brown   X = snes->vec_sol;
23b79b07cfSJed Brown   F = snes->vec_func;
24b79b07cfSJed Brown   Y = snes->vec_sol_update;
25b79b07cfSJed Brown 
26451891c6SStefano Zampini   if (!snes->vec_func_init_set) {
279566063dSJacob Faibussowitsch     PetscCall(SNESComputeFunction(snes,X,F));
28451891c6SStefano Zampini   } else snes->vec_func_init_set = PETSC_FALSE;
29451891c6SStefano Zampini 
30a5eaddd9SBarry Smith   if (snes->numbermonitors) {
31a5eaddd9SBarry Smith     PetscReal fnorm;
329566063dSJacob Faibussowitsch     PetscCall(VecNorm(F,NORM_2,&fnorm));
339566063dSJacob Faibussowitsch     PetscCall(SNESMonitor(snes,0,fnorm));
34a5eaddd9SBarry Smith   }
35b79b07cfSJed Brown 
365341784dSBarry Smith   /* Call general purpose update function */
37*dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes,update, 0);
385341784dSBarry Smith 
39b79b07cfSJed Brown   /* Solve J Y = F, where J is Jacobian matrix */
409566063dSJacob Faibussowitsch   PetscCall(SNESComputeJacobian(snes,X,snes->jacobian,snes->jacobian_pre));
4107b62357SFande Kong 
4207b62357SFande Kong   SNESCheckJacobianDomainerror(snes);
4307b62357SFande Kong 
449566063dSJacob Faibussowitsch   PetscCall(KSPSetOperators(snes->ksp,snes->jacobian,snes->jacobian_pre));
451ef27442SStefano Zampini   if (ksponly->transpose_solve) {
469566063dSJacob Faibussowitsch     PetscCall(KSPSolveTranspose(snes->ksp,F,Y));
471ef27442SStefano Zampini   } else {
489566063dSJacob Faibussowitsch     PetscCall(KSPSolve(snes->ksp,F,Y));
491ef27442SStefano Zampini   }
50422a814eSBarry Smith   snes->reason = SNES_CONVERGED_ITS;
51422a814eSBarry Smith   SNESCheckKSPSolve(snes);
521aa26658SKarl Rupp 
539566063dSJacob Faibussowitsch   PetscCall(KSPGetIterationNumber(snes->ksp,&lits));
5463a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(snes,"iter=%" PetscInt_FMT ", linear solve iterations=%" PetscInt_FMT "\n",snes->iter,lits));
55b79b07cfSJed Brown   snes->iter++;
56b79b07cfSJed Brown 
57b79b07cfSJed Brown   /* Take the computed step. */
589566063dSJacob Faibussowitsch   PetscCall(VecAXPY(X,-1.0,Y));
59a5eaddd9SBarry Smith   if (snes->numbermonitors) {
60a5eaddd9SBarry Smith     PetscReal fnorm;
619566063dSJacob Faibussowitsch     PetscCall(SNESComputeFunction(snes,X,F));
629566063dSJacob Faibussowitsch     PetscCall(VecNorm(F,NORM_2,&fnorm));
639566063dSJacob Faibussowitsch     PetscCall(SNESMonitor(snes,1,fnorm));
64a5eaddd9SBarry Smith   }
65b79b07cfSJed Brown   PetscFunctionReturn(0);
66b79b07cfSJed Brown }
67b79b07cfSJed Brown 
68b79b07cfSJed Brown static PetscErrorCode SNESSetUp_KSPONLY(SNES snes)
69b79b07cfSJed Brown {
70b79b07cfSJed Brown   PetscFunctionBegin;
719566063dSJacob Faibussowitsch   PetscCall(SNESSetUpMatrices(snes));
72b79b07cfSJed Brown   PetscFunctionReturn(0);
73b79b07cfSJed Brown }
74b79b07cfSJed Brown 
75b79b07cfSJed Brown static PetscErrorCode SNESDestroy_KSPONLY(SNES snes)
76b79b07cfSJed Brown {
77b79b07cfSJed Brown   PetscFunctionBegin;
789566063dSJacob Faibussowitsch   PetscCall(PetscFree(snes->data));
79b79b07cfSJed Brown   PetscFunctionReturn(0);
80b79b07cfSJed Brown }
81b79b07cfSJed Brown 
82b79b07cfSJed Brown /* -------------------------------------------------------------------------- */
83b79b07cfSJed Brown /*MC
84b79b07cfSJed Brown       SNESKSPONLY - Nonlinear solver that only performs one Newton step and does not compute any norms.
85b79b07cfSJed Brown       The main purpose of this solver is to solve linear problems using the SNES interface, without
86b79b07cfSJed Brown       any additional overhead in the form of vector operations.
87b79b07cfSJed Brown 
88b79b07cfSJed Brown    Level: beginner
89b79b07cfSJed Brown 
90db781477SPatrick Sanan .seealso: `SNESCreate()`, `SNES`, `SNESSetType()`, `SNESNEWTONLS`, `SNESNEWTONTR`
91b79b07cfSJed Brown M*/
928cc058d9SJed Brown PETSC_EXTERN PetscErrorCode SNESCreate_KSPONLY(SNES snes)
93b79b07cfSJed Brown {
941ef27442SStefano Zampini   SNES_KSPONLY   *ksponly;
95b79b07cfSJed Brown 
96b79b07cfSJed Brown   PetscFunctionBegin;
97b79b07cfSJed Brown   snes->ops->setup          = SNESSetUp_KSPONLY;
98b79b07cfSJed Brown   snes->ops->solve          = SNESSolve_KSPONLY;
99b79b07cfSJed Brown   snes->ops->destroy        = SNESDestroy_KSPONLY;
1009e5d0892SLisandro Dalcin   snes->ops->setfromoptions = NULL;
1019e5d0892SLisandro Dalcin   snes->ops->view           = NULL;
1029e5d0892SLisandro Dalcin   snes->ops->reset          = NULL;
103b79b07cfSJed Brown 
10442f4f86dSBarry Smith   snes->usesksp = PETSC_TRUE;
105efd4aadfSBarry Smith   snes->usesnpc = PETSC_FALSE;
10642f4f86dSBarry Smith 
1074fc747eaSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
1084fc747eaSLawrence Mitchell 
1099566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(snes,&ksponly));
1101ef27442SStefano Zampini   snes->data = (void*)ksponly;
1111ef27442SStefano Zampini   PetscFunctionReturn(0);
1121ef27442SStefano Zampini }
1131ef27442SStefano Zampini 
1141ef27442SStefano Zampini /*MC
1151ef27442SStefano Zampini       SNESKSPTRANSPOSEONLY - Nonlinear solver that only performs one Newton step and does not compute any norms.
1161ef27442SStefano Zampini       The main purpose of this solver is to solve transposed linear problems using the SNES interface, without
1171ef27442SStefano Zampini       any additional overhead in the form of vector operations within adjoint solvers.
1181ef27442SStefano Zampini 
1191ef27442SStefano Zampini    Level: beginner
1201ef27442SStefano Zampini 
121db781477SPatrick Sanan .seealso: `SNESCreate()`, `SNES`, `SNESSetType()`, `SNESKSPTRANSPOSEONLY`, `SNESNEWTONLS`, `SNESNEWTONTR`
1221ef27442SStefano Zampini M*/
1231ef27442SStefano Zampini PETSC_EXTERN PetscErrorCode SNESCreate_KSPTRANSPOSEONLY(SNES snes)
1241ef27442SStefano Zampini {
1251ef27442SStefano Zampini   SNES_KSPONLY   *kspo;
1261ef27442SStefano Zampini 
1271ef27442SStefano Zampini   PetscFunctionBegin;
1289566063dSJacob Faibussowitsch   PetscCall(SNESCreate_KSPONLY(snes));
1299566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)snes,SNESKSPTRANSPOSEONLY));
1301ef27442SStefano Zampini   kspo = (SNES_KSPONLY*)snes->data;
1311ef27442SStefano Zampini   kspo->transpose_solve = PETSC_TRUE;
132b79b07cfSJed Brown   PetscFunctionReturn(0);
133b79b07cfSJed Brown }
134