xref: /petsc/src/snes/impls/ksponly/ksponly.c (revision 63a3b9bc7a1f24f247904ccba9383635fe6abade)
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;
142c71b3e2SJacob Faibussowitsch   PetscCheckFalse(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 */
375341784dSBarry Smith   if (snes->ops->update) {
389566063dSJacob Faibussowitsch     PetscCall((*snes->ops->update)(snes, 0));
395341784dSBarry Smith   }
405341784dSBarry Smith 
41b79b07cfSJed Brown   /* Solve J Y = F, where J is Jacobian matrix */
429566063dSJacob Faibussowitsch   PetscCall(SNESComputeJacobian(snes,X,snes->jacobian,snes->jacobian_pre));
4307b62357SFande Kong 
4407b62357SFande Kong   SNESCheckJacobianDomainerror(snes);
4507b62357SFande Kong 
469566063dSJacob Faibussowitsch   PetscCall(KSPSetOperators(snes->ksp,snes->jacobian,snes->jacobian_pre));
471ef27442SStefano Zampini   if (ksponly->transpose_solve) {
489566063dSJacob Faibussowitsch     PetscCall(KSPSolveTranspose(snes->ksp,F,Y));
491ef27442SStefano Zampini   } else {
509566063dSJacob Faibussowitsch     PetscCall(KSPSolve(snes->ksp,F,Y));
511ef27442SStefano Zampini   }
52422a814eSBarry Smith   snes->reason = SNES_CONVERGED_ITS;
53422a814eSBarry Smith   SNESCheckKSPSolve(snes);
541aa26658SKarl Rupp 
559566063dSJacob Faibussowitsch   PetscCall(KSPGetIterationNumber(snes->ksp,&lits));
56*63a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(snes,"iter=%" PetscInt_FMT ", linear solve iterations=%" PetscInt_FMT "\n",snes->iter,lits));
57b79b07cfSJed Brown   snes->iter++;
58b79b07cfSJed Brown 
59b79b07cfSJed Brown   /* Take the computed step. */
609566063dSJacob Faibussowitsch   PetscCall(VecAXPY(X,-1.0,Y));
61a5eaddd9SBarry Smith   if (snes->numbermonitors) {
62a5eaddd9SBarry Smith     PetscReal fnorm;
639566063dSJacob Faibussowitsch     PetscCall(SNESComputeFunction(snes,X,F));
649566063dSJacob Faibussowitsch     PetscCall(VecNorm(F,NORM_2,&fnorm));
659566063dSJacob Faibussowitsch     PetscCall(SNESMonitor(snes,1,fnorm));
66a5eaddd9SBarry Smith   }
67b79b07cfSJed Brown   PetscFunctionReturn(0);
68b79b07cfSJed Brown }
69b79b07cfSJed Brown 
70b79b07cfSJed Brown static PetscErrorCode SNESSetUp_KSPONLY(SNES snes)
71b79b07cfSJed Brown {
72b79b07cfSJed Brown   PetscFunctionBegin;
739566063dSJacob Faibussowitsch   PetscCall(SNESSetUpMatrices(snes));
74b79b07cfSJed Brown   PetscFunctionReturn(0);
75b79b07cfSJed Brown }
76b79b07cfSJed Brown 
77b79b07cfSJed Brown static PetscErrorCode SNESDestroy_KSPONLY(SNES snes)
78b79b07cfSJed Brown {
79b79b07cfSJed Brown   PetscFunctionBegin;
809566063dSJacob Faibussowitsch   PetscCall(PetscFree(snes->data));
81b79b07cfSJed Brown   PetscFunctionReturn(0);
82b79b07cfSJed Brown }
83b79b07cfSJed Brown 
84b79b07cfSJed Brown /* -------------------------------------------------------------------------- */
85b79b07cfSJed Brown /*MC
86b79b07cfSJed Brown       SNESKSPONLY - Nonlinear solver that only performs one Newton step and does not compute any norms.
87b79b07cfSJed Brown       The main purpose of this solver is to solve linear problems using the SNES interface, without
88b79b07cfSJed Brown       any additional overhead in the form of vector operations.
89b79b07cfSJed Brown 
90b79b07cfSJed Brown    Level: beginner
91b79b07cfSJed Brown 
9204d7464bSBarry Smith .seealso:  SNESCreate(), SNES, SNESSetType(), SNESNEWTONLS, SNESNEWTONTR
93b79b07cfSJed Brown M*/
948cc058d9SJed Brown PETSC_EXTERN PetscErrorCode SNESCreate_KSPONLY(SNES snes)
95b79b07cfSJed Brown {
961ef27442SStefano Zampini   SNES_KSPONLY   *ksponly;
97b79b07cfSJed Brown 
98b79b07cfSJed Brown   PetscFunctionBegin;
99b79b07cfSJed Brown   snes->ops->setup          = SNESSetUp_KSPONLY;
100b79b07cfSJed Brown   snes->ops->solve          = SNESSolve_KSPONLY;
101b79b07cfSJed Brown   snes->ops->destroy        = SNESDestroy_KSPONLY;
1029e5d0892SLisandro Dalcin   snes->ops->setfromoptions = NULL;
1039e5d0892SLisandro Dalcin   snes->ops->view           = NULL;
1049e5d0892SLisandro Dalcin   snes->ops->reset          = NULL;
105b79b07cfSJed Brown 
10642f4f86dSBarry Smith   snes->usesksp = PETSC_TRUE;
107efd4aadfSBarry Smith   snes->usesnpc = PETSC_FALSE;
10842f4f86dSBarry Smith 
1094fc747eaSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
1104fc747eaSLawrence Mitchell 
1119566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(snes,&ksponly));
1121ef27442SStefano Zampini   snes->data = (void*)ksponly;
1131ef27442SStefano Zampini   PetscFunctionReturn(0);
1141ef27442SStefano Zampini }
1151ef27442SStefano Zampini 
1161ef27442SStefano Zampini /*MC
1171ef27442SStefano Zampini       SNESKSPTRANSPOSEONLY - Nonlinear solver that only performs one Newton step and does not compute any norms.
1181ef27442SStefano Zampini       The main purpose of this solver is to solve transposed linear problems using the SNES interface, without
1191ef27442SStefano Zampini       any additional overhead in the form of vector operations within adjoint solvers.
1201ef27442SStefano Zampini 
1211ef27442SStefano Zampini    Level: beginner
1221ef27442SStefano Zampini 
1231ef27442SStefano Zampini .seealso:  SNESCreate(), SNES, SNESSetType(), SNESKSPTRANSPOSEONLY, SNESNEWTONLS, SNESNEWTONTR
1241ef27442SStefano Zampini M*/
1251ef27442SStefano Zampini PETSC_EXTERN PetscErrorCode SNESCreate_KSPTRANSPOSEONLY(SNES snes)
1261ef27442SStefano Zampini {
1271ef27442SStefano Zampini   SNES_KSPONLY   *kspo;
1281ef27442SStefano Zampini 
1291ef27442SStefano Zampini   PetscFunctionBegin;
1309566063dSJacob Faibussowitsch   PetscCall(SNESCreate_KSPONLY(snes));
1319566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)snes,SNESKSPTRANSPOSEONLY));
1321ef27442SStefano Zampini   kspo = (SNES_KSPONLY*)snes->data;
1331ef27442SStefano Zampini   kspo->transpose_solve = PETSC_TRUE;
134b79b07cfSJed Brown   PetscFunctionReturn(0);
135b79b07cfSJed Brown }
136