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 SNES_KSPONLY *ksponly = (SNES_KSPONLY *)snes->data; 9 PetscInt lits; 10 Vec Y, X, F; 11 12 PetscFunctionBegin; 13 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); 14 15 snes->numFailures = 0; 16 snes->numLinearSolveFailures = 0; 17 snes->reason = SNES_CONVERGED_ITERATING; 18 snes->iter = 0; 19 snes->norm = 0.0; 20 21 X = snes->vec_sol; 22 F = snes->vec_func; 23 Y = snes->vec_sol_update; 24 25 if (!snes->vec_func_init_set) { 26 PetscCall(SNESComputeFunction(snes, X, F)); 27 } else snes->vec_func_init_set = PETSC_FALSE; 28 29 if (snes->numbermonitors) { 30 PetscReal fnorm; 31 PetscCall(VecNorm(F, NORM_2, &fnorm)); 32 PetscCall(SNESMonitor(snes, 0, fnorm)); 33 } 34 35 /* Call general purpose update function */ 36 PetscTryTypeMethod(snes, update, 0); 37 38 /* Solve J Y = F, where J is Jacobian matrix */ 39 PetscCall(SNESComputeJacobian(snes, X, snes->jacobian, snes->jacobian_pre)); 40 41 SNESCheckJacobianDomainerror(snes); 42 43 PetscCall(KSPSetOperators(snes->ksp, snes->jacobian, snes->jacobian_pre)); 44 if (ksponly->transpose_solve) { 45 PetscCall(KSPSolveTranspose(snes->ksp, F, Y)); 46 } else { 47 PetscCall(KSPSolve(snes->ksp, F, Y)); 48 } 49 snes->reason = SNES_CONVERGED_ITS; 50 SNESCheckKSPSolve(snes); 51 52 PetscCall(KSPGetIterationNumber(snes->ksp, &lits)); 53 PetscCall(PetscInfo(snes, "iter=%" PetscInt_FMT ", linear solve iterations=%" PetscInt_FMT "\n", snes->iter, lits)); 54 snes->iter++; 55 56 /* Take the computed step. */ 57 PetscCall(VecAXPY(X, -1.0, Y)); 58 if (snes->numbermonitors) { 59 PetscReal fnorm; 60 PetscCall(SNESComputeFunction(snes, X, F)); 61 PetscCall(VecNorm(F, NORM_2, &fnorm)); 62 PetscCall(SNESMonitor(snes, 1, fnorm)); 63 } 64 PetscFunctionReturn(0); 65 } 66 67 static PetscErrorCode SNESSetUp_KSPONLY(SNES snes) { 68 PetscFunctionBegin; 69 PetscCall(SNESSetUpMatrices(snes)); 70 PetscFunctionReturn(0); 71 } 72 73 static PetscErrorCode SNESDestroy_KSPONLY(SNES snes) { 74 PetscFunctionBegin; 75 PetscCall(PetscFree(snes->data)); 76 PetscFunctionReturn(0); 77 } 78 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. 83 84 Level: beginner 85 86 .seealso: `SNES`, `SNESType`, `SNESCreate()`, `SNES`, `SNESSetType()`, `SNESNEWTONLS`, `SNESNEWTONTR` 87 M*/ 88 PETSC_EXTERN PetscErrorCode SNESCreate_KSPONLY(SNES snes) { 89 SNES_KSPONLY *ksponly; 90 91 PetscFunctionBegin; 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; 98 99 snes->usesksp = PETSC_TRUE; 100 snes->usesnpc = PETSC_FALSE; 101 102 snes->alwayscomputesfinalresidual = PETSC_FALSE; 103 104 PetscCall(PetscNewLog(snes, &ksponly)); 105 snes->data = (void *)ksponly; 106 PetscFunctionReturn(0); 107 } 108 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. 113 114 Level: beginner 115 116 .seealso: `SNES`, `SNESType`, `SNESCreate()`, `SNES`, `SNESSetType()`, `SNESKSPTRANSPOSEONLY`, `SNESNEWTONLS`, `SNESNEWTONTR` 117 M*/ 118 PETSC_EXTERN PetscErrorCode SNESCreate_KSPTRANSPOSEONLY(SNES snes) { 119 SNES_KSPONLY *kspo; 120 121 PetscFunctionBegin; 122 PetscCall(SNESCreate_KSPONLY(snes)); 123 PetscCall(PetscObjectChangeTypeName((PetscObject)snes, SNESKSPTRANSPOSEONLY)); 124 kspo = (SNES_KSPONLY *)snes->data; 125 kspo->transpose_solve = PETSC_TRUE; 126 PetscFunctionReturn(0); 127 } 128