Actual source code: ksponly.c

  1: #include <petsc/private/snesimpl.h>

  3: typedef struct {
  4:   PetscBool transpose_solve;
  5: } SNES_KSPONLY;

  7: static PetscErrorCode SNESSolve_KSPONLY(SNES snes)
  8: {
  9:   SNES_KSPONLY *ksponly = (SNES_KSPONLY *)snes->data;
 10:   PetscInt      lits;
 11:   Vec           Y, X, F;


 15:   snes->numFailures            = 0;
 16:   snes->numLinearSolveFailures = 0;
 17:   snes->reason                 = SNES_CONVERGED_ITERATING;
 18:   snes->iter                   = 0;
 19:   snes->norm                   = 0.0;

 21:   X = snes->vec_sol;
 22:   F = snes->vec_func;
 23:   Y = snes->vec_sol_update;

 25:   if (!snes->vec_func_init_set) {
 26:     SNESComputeFunction(snes, X, F);
 27:   } else snes->vec_func_init_set = PETSC_FALSE;

 29:   if (snes->numbermonitors) {
 30:     PetscReal fnorm;
 31:     VecNorm(F, NORM_2, &fnorm);
 32:     SNESMonitor(snes, 0, fnorm);
 33:   }

 35:   /* Call general purpose update function */
 36:   PetscTryTypeMethod(snes, update, 0);

 38:   /* Solve J Y = F, where J is Jacobian matrix */
 39:   SNESComputeJacobian(snes, X, snes->jacobian, snes->jacobian_pre);

 41:   SNESCheckJacobianDomainerror(snes);

 43:   KSPSetOperators(snes->ksp, snes->jacobian, snes->jacobian_pre);
 44:   if (ksponly->transpose_solve) {
 45:     KSPSolveTranspose(snes->ksp, F, Y);
 46:   } else {
 47:     KSPSolve(snes->ksp, F, Y);
 48:   }
 49:   snes->reason = SNES_CONVERGED_ITS;
 50:   SNESCheckKSPSolve(snes);

 52:   KSPGetIterationNumber(snes->ksp, &lits);
 53:   PetscInfo(snes, "iter=%" PetscInt_FMT ", linear solve iterations=%" PetscInt_FMT "\n", snes->iter, lits);
 54:   snes->iter++;

 56:   /* Take the computed step. */
 57:   VecAXPY(X, -1.0, Y);
 58:   if (snes->numbermonitors) {
 59:     PetscReal fnorm;
 60:     SNESComputeFunction(snes, X, F);
 61:     VecNorm(F, NORM_2, &fnorm);
 62:     SNESMonitor(snes, 1, fnorm);
 63:   }
 64:   return 0;
 65: }

 67: static PetscErrorCode SNESSetUp_KSPONLY(SNES snes)
 68: {
 69:   SNESSetUpMatrices(snes);
 70:   return 0;
 71: }

 73: static PetscErrorCode SNESDestroy_KSPONLY(SNES snes)
 74: {
 75:   PetscFree(snes->data);
 76:   return 0;
 77: }

 79: /*MC
 80:       SNESKSPONLY - Nonlinear solver that performs one Newton step and does not compute any norms.
 81:       The main purpose of this solver is to solve linear problems using the `SNES` interface, without
 82:       any additional overhead in the form of vector operations.

 84:    Level: beginner

 86: .seealso: `SNES`, `SNESType`, `SNESCreate()`, `SNES`, `SNESSetType()`, `SNESNEWTONLS`, `SNESNEWTONTR`
 87: M*/
 88: PETSC_EXTERN PetscErrorCode SNESCreate_KSPONLY(SNES snes)
 89: {
 90:   SNES_KSPONLY *ksponly;

 92:   snes->ops->setup          = SNESSetUp_KSPONLY;
 93:   snes->ops->solve          = SNESSolve_KSPONLY;
 94:   snes->ops->destroy        = SNESDestroy_KSPONLY;
 95:   snes->ops->setfromoptions = NULL;
 96:   snes->ops->view           = NULL;
 97:   snes->ops->reset          = NULL;

 99:   snes->usesksp = PETSC_TRUE;
100:   snes->usesnpc = PETSC_FALSE;

102:   snes->alwayscomputesfinalresidual = PETSC_FALSE;

104:   PetscNew(&ksponly);
105:   snes->data = (void *)ksponly;
106:   return 0;
107: }

109: /*MC
110:       SNESKSPTRANSPOSEONLY - Nonlinear solver that performs one Newton step and does not compute any norms.
111:       The main purpose of this solver is to solve transposed linear problems using the `SNES` interface, without
112:       any additional overhead in the form of vector operations within adjoint solvers.

114:    Level: beginner

116: .seealso: `SNES`, `SNESType`, `SNESCreate()`, `SNES`, `SNESSetType()`, `SNESKSPTRANSPOSEONLY`, `SNESNEWTONLS`, `SNESNEWTONTR`
117: M*/
118: PETSC_EXTERN PetscErrorCode SNESCreate_KSPTRANSPOSEONLY(SNES snes)
119: {
120:   SNES_KSPONLY *kspo;

122:   SNESCreate_KSPONLY(snes);
123:   PetscObjectChangeTypeName((PetscObject)snes, SNESKSPTRANSPOSEONLY);
124:   kspo                  = (SNES_KSPONLY *)snes->data;
125:   kspo->transpose_solve = PETSC_TRUE;
126:   return 0;
127: }