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
SNESSolve_KSPONLY(SNES snes)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;
12a3e9d663SJames 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
27ac530a7eSPierre Jolivet if (!snes->vec_func_init_set) PetscCall(SNESComputeFunction(snes, X, F));
28ac530a7eSPierre Jolivet else snes->vec_func_init_set = PETSC_FALSE;
29451891c6SStefano Zampini
30a3e9d663SJames Wright PetscCall(SNESGetNormSchedule(snes, &normschedule));
31a3e9d663SJames Wright if (snes->numbermonitors && (normschedule == SNES_NORM_ALWAYS || normschedule == SNES_NORM_INITIAL_ONLY || normschedule == SNES_NORM_INITIAL_FINAL_ONLY)) {
32a5eaddd9SBarry Smith PetscReal fnorm;
339566063dSJacob Faibussowitsch PetscCall(VecNorm(F, NORM_2, &fnorm));
34*76c63389SBarry Smith SNESCheckFunctionDomainError(snes, fnorm);
359566063dSJacob Faibussowitsch PetscCall(SNESMonitor(snes, 0, fnorm));
36a5eaddd9SBarry Smith }
37b79b07cfSJed Brown
385341784dSBarry Smith /* Call general purpose update function */
39dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, update, 0);
405341784dSBarry Smith
41b79b07cfSJed Brown /* Solve J Y = F, where J is Jacobian matrix */
429566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobian(snes, X, snes->jacobian, snes->jacobian_pre));
43*76c63389SBarry Smith SNESCheckJacobianDomainError(snes);
4407b62357SFande Kong
459566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(snes->ksp, snes->jacobian, snes->jacobian_pre));
461ef27442SStefano Zampini if (ksponly->transpose_solve) {
479566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(snes->ksp, F, Y));
481ef27442SStefano Zampini } else {
499566063dSJacob Faibussowitsch PetscCall(KSPSolve(snes->ksp, F, Y));
501ef27442SStefano Zampini }
51422a814eSBarry Smith snes->reason = SNES_CONVERGED_ITS;
52422a814eSBarry Smith SNESCheckKSPSolve(snes);
531aa26658SKarl Rupp
549566063dSJacob Faibussowitsch PetscCall(KSPGetIterationNumber(snes->ksp, &lits));
5563a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "iter=%" PetscInt_FMT ", linear solve iterations=%" PetscInt_FMT "\n", snes->iter, lits));
56b79b07cfSJed Brown snes->iter++;
57b79b07cfSJed Brown
58b79b07cfSJed Brown /* Take the computed step. */
599566063dSJacob Faibussowitsch PetscCall(VecAXPY(X, -1.0, Y));
60a3e9d663SJames Wright
61a3e9d663SJames Wright if (snes->numbermonitors && (normschedule == SNES_NORM_ALWAYS || normschedule == SNES_NORM_FINAL_ONLY || normschedule == SNES_NORM_INITIAL_FINAL_ONLY)) {
62a5eaddd9SBarry Smith PetscReal fnorm;
639566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, X, F));
649566063dSJacob Faibussowitsch PetscCall(VecNorm(F, NORM_2, &fnorm));
65*76c63389SBarry Smith SNESCheckFunctionDomainError(snes, fnorm);
669566063dSJacob Faibussowitsch PetscCall(SNESMonitor(snes, 1, fnorm));
67a5eaddd9SBarry Smith }
683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
69b79b07cfSJed Brown }
70b79b07cfSJed Brown
SNESSetUp_KSPONLY(SNES snes)71d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetUp_KSPONLY(SNES snes)
72d71ae5a4SJacob Faibussowitsch {
73b79b07cfSJed Brown PetscFunctionBegin;
749566063dSJacob Faibussowitsch PetscCall(SNESSetUpMatrices(snes));
753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
76b79b07cfSJed Brown }
77b79b07cfSJed Brown
SNESDestroy_KSPONLY(SNES snes)78d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESDestroy_KSPONLY(SNES snes)
79d71ae5a4SJacob Faibussowitsch {
80b79b07cfSJed Brown PetscFunctionBegin;
819566063dSJacob Faibussowitsch PetscCall(PetscFree(snes->data));
823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
83b79b07cfSJed Brown }
84b79b07cfSJed Brown
85b79b07cfSJed Brown /*MC
86420bcc1bSBarry Smith SNESKSPONLY - Nonlinear solver that performs one Newton step with `KSPSolve()` and does not compute any norms.
87b79b07cfSJed Brown
88b79b07cfSJed Brown Level: beginner
89b79b07cfSJed Brown
90420bcc1bSBarry Smith Note:
91420bcc1bSBarry Smith The main purpose of this solver is to solve linear problems using the `SNES` interface, without
92420bcc1bSBarry Smith any additional overhead in the form of vector norm operations.
93420bcc1bSBarry Smith
94420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESType`, `SNESCreate()`, `SNES`, `SNESSetType()`, `SNESNEWTONLS`, `SNESNEWTONTR`, `SNESKSPTRANSPOSEONLY`
95b79b07cfSJed Brown M*/
SNESCreate_KSPONLY(SNES snes)96d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode SNESCreate_KSPONLY(SNES snes)
97d71ae5a4SJacob Faibussowitsch {
981ef27442SStefano Zampini SNES_KSPONLY *ksponly;
99b79b07cfSJed Brown
100b79b07cfSJed Brown PetscFunctionBegin;
101b79b07cfSJed Brown snes->ops->setup = SNESSetUp_KSPONLY;
102b79b07cfSJed Brown snes->ops->solve = SNESSolve_KSPONLY;
103b79b07cfSJed Brown snes->ops->destroy = SNESDestroy_KSPONLY;
1049e5d0892SLisandro Dalcin snes->ops->setfromoptions = NULL;
1059e5d0892SLisandro Dalcin snes->ops->view = NULL;
1069e5d0892SLisandro Dalcin snes->ops->reset = NULL;
107b79b07cfSJed Brown
10842f4f86dSBarry Smith snes->usesksp = PETSC_TRUE;
109efd4aadfSBarry Smith snes->usesnpc = PETSC_FALSE;
11042f4f86dSBarry Smith
1114fc747eaSLawrence Mitchell snes->alwayscomputesfinalresidual = PETSC_FALSE;
1124fc747eaSLawrence Mitchell
11377e5a1f9SBarry Smith PetscCall(SNESParametersInitialize(snes));
11477e5a1f9SBarry Smith
1154dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&ksponly));
1161ef27442SStefano Zampini snes->data = (void *)ksponly;
1173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1181ef27442SStefano Zampini }
1191ef27442SStefano Zampini
1201ef27442SStefano Zampini /*MC
121420bcc1bSBarry Smith SNESKSPTRANSPOSEONLY - Nonlinear solver that performs one Newton step with `KSPSolveTranspose()` and does not compute any norms.
1221ef27442SStefano Zampini
1231ef27442SStefano Zampini Level: beginner
1241ef27442SStefano Zampini
125420bcc1bSBarry Smith Note:
126420bcc1bSBarry Smith The main purpose of this solver is to solve transposed linear problems using the `SNES` interface, without
127420bcc1bSBarry Smith any additional overhead in the form of vector operations within adjoint solvers.
128420bcc1bSBarry Smith
129420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESType`, `SNESCreate()`, `SNES`, `SNESSetType()`, `SNESKS`, `SNESNEWTONLS`, `SNESNEWTONTR`
1301ef27442SStefano Zampini M*/
SNESCreate_KSPTRANSPOSEONLY(SNES snes)131d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode SNESCreate_KSPTRANSPOSEONLY(SNES snes)
132d71ae5a4SJacob Faibussowitsch {
1331ef27442SStefano Zampini SNES_KSPONLY *kspo;
1341ef27442SStefano Zampini
1351ef27442SStefano Zampini PetscFunctionBegin;
1369566063dSJacob Faibussowitsch PetscCall(SNESCreate_KSPONLY(snes));
1379566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)snes, SNESKSPTRANSPOSEONLY));
1381ef27442SStefano Zampini kspo = (SNES_KSPONLY *)snes->data;
1391ef27442SStefano Zampini kspo->transpose_solve = PETSC_TRUE;
1403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
141b79b07cfSJed Brown }
142