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 79371c9d4SSatish Balay static PetscErrorCode SNESSolve_KSPONLY(SNES snes) { 81ef27442SStefano Zampini SNES_KSPONLY *ksponly = (SNES_KSPONLY *)snes->data; 9b79b07cfSJed Brown PetscInt lits; 10b79b07cfSJed Brown Vec Y, X, F; 11b79b07cfSJed Brown 12b79b07cfSJed Brown PetscFunctionBegin; 130b121fc5SBarry 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); 14c579b300SPatrick Farrell 15b79b07cfSJed Brown snes->numFailures = 0; 16b79b07cfSJed Brown snes->numLinearSolveFailures = 0; 17b79b07cfSJed Brown snes->reason = SNES_CONVERGED_ITERATING; 18b79b07cfSJed Brown snes->iter = 0; 19b79b07cfSJed Brown snes->norm = 0.0; 20b79b07cfSJed Brown 21b79b07cfSJed Brown X = snes->vec_sol; 22b79b07cfSJed Brown F = snes->vec_func; 23b79b07cfSJed Brown Y = snes->vec_sol_update; 24b79b07cfSJed Brown 25451891c6SStefano Zampini if (!snes->vec_func_init_set) { 269566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, X, F)); 27451891c6SStefano Zampini } else snes->vec_func_init_set = PETSC_FALSE; 28451891c6SStefano Zampini 29a5eaddd9SBarry Smith if (snes->numbermonitors) { 30a5eaddd9SBarry Smith PetscReal fnorm; 319566063dSJacob Faibussowitsch PetscCall(VecNorm(F, NORM_2, &fnorm)); 329566063dSJacob Faibussowitsch PetscCall(SNESMonitor(snes, 0, fnorm)); 33a5eaddd9SBarry Smith } 34b79b07cfSJed Brown 355341784dSBarry Smith /* Call general purpose update function */ 36dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, update, 0); 375341784dSBarry Smith 38b79b07cfSJed Brown /* Solve J Y = F, where J is Jacobian matrix */ 399566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobian(snes, X, snes->jacobian, snes->jacobian_pre)); 4007b62357SFande Kong 4107b62357SFande Kong SNESCheckJacobianDomainerror(snes); 4207b62357SFande Kong 439566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(snes->ksp, snes->jacobian, snes->jacobian_pre)); 441ef27442SStefano Zampini if (ksponly->transpose_solve) { 459566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(snes->ksp, F, Y)); 461ef27442SStefano Zampini } else { 479566063dSJacob Faibussowitsch PetscCall(KSPSolve(snes->ksp, F, Y)); 481ef27442SStefano Zampini } 49422a814eSBarry Smith snes->reason = SNES_CONVERGED_ITS; 50422a814eSBarry Smith SNESCheckKSPSolve(snes); 511aa26658SKarl Rupp 529566063dSJacob Faibussowitsch PetscCall(KSPGetIterationNumber(snes->ksp, &lits)); 5363a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "iter=%" PetscInt_FMT ", linear solve iterations=%" PetscInt_FMT "\n", snes->iter, lits)); 54b79b07cfSJed Brown snes->iter++; 55b79b07cfSJed Brown 56b79b07cfSJed Brown /* Take the computed step. */ 579566063dSJacob Faibussowitsch PetscCall(VecAXPY(X, -1.0, Y)); 58a5eaddd9SBarry Smith if (snes->numbermonitors) { 59a5eaddd9SBarry Smith PetscReal fnorm; 609566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, X, F)); 619566063dSJacob Faibussowitsch PetscCall(VecNorm(F, NORM_2, &fnorm)); 629566063dSJacob Faibussowitsch PetscCall(SNESMonitor(snes, 1, fnorm)); 63a5eaddd9SBarry Smith } 64b79b07cfSJed Brown PetscFunctionReturn(0); 65b79b07cfSJed Brown } 66b79b07cfSJed Brown 679371c9d4SSatish Balay static PetscErrorCode SNESSetUp_KSPONLY(SNES snes) { 68b79b07cfSJed Brown PetscFunctionBegin; 699566063dSJacob Faibussowitsch PetscCall(SNESSetUpMatrices(snes)); 70b79b07cfSJed Brown PetscFunctionReturn(0); 71b79b07cfSJed Brown } 72b79b07cfSJed Brown 739371c9d4SSatish Balay static PetscErrorCode SNESDestroy_KSPONLY(SNES snes) { 74b79b07cfSJed Brown PetscFunctionBegin; 759566063dSJacob Faibussowitsch PetscCall(PetscFree(snes->data)); 76b79b07cfSJed Brown PetscFunctionReturn(0); 77b79b07cfSJed Brown } 78b79b07cfSJed Brown 79b79b07cfSJed Brown /*MC 80f6dfbefdSBarry Smith SNESKSPONLY - Nonlinear solver that performs one Newton step and does not compute any norms. 81f6dfbefdSBarry Smith The main purpose of this solver is to solve linear problems using the `SNES` interface, without 82b79b07cfSJed Brown any additional overhead in the form of vector operations. 83b79b07cfSJed Brown 84b79b07cfSJed Brown Level: beginner 85b79b07cfSJed Brown 86f6dfbefdSBarry Smith .seealso: `SNES`, `SNESType`, `SNESCreate()`, `SNES`, `SNESSetType()`, `SNESNEWTONLS`, `SNESNEWTONTR` 87b79b07cfSJed Brown M*/ 889371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode SNESCreate_KSPONLY(SNES snes) { 891ef27442SStefano Zampini SNES_KSPONLY *ksponly; 90b79b07cfSJed Brown 91b79b07cfSJed Brown PetscFunctionBegin; 92b79b07cfSJed Brown snes->ops->setup = SNESSetUp_KSPONLY; 93b79b07cfSJed Brown snes->ops->solve = SNESSolve_KSPONLY; 94b79b07cfSJed Brown snes->ops->destroy = SNESDestroy_KSPONLY; 959e5d0892SLisandro Dalcin snes->ops->setfromoptions = NULL; 969e5d0892SLisandro Dalcin snes->ops->view = NULL; 979e5d0892SLisandro Dalcin snes->ops->reset = NULL; 98b79b07cfSJed Brown 9942f4f86dSBarry Smith snes->usesksp = PETSC_TRUE; 100efd4aadfSBarry Smith snes->usesnpc = PETSC_FALSE; 10142f4f86dSBarry Smith 1024fc747eaSLawrence Mitchell snes->alwayscomputesfinalresidual = PETSC_FALSE; 1034fc747eaSLawrence Mitchell 104*4dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&ksponly)); 1051ef27442SStefano Zampini snes->data = (void *)ksponly; 1061ef27442SStefano Zampini PetscFunctionReturn(0); 1071ef27442SStefano Zampini } 1081ef27442SStefano Zampini 1091ef27442SStefano Zampini /*MC 110f6dfbefdSBarry Smith SNESKSPTRANSPOSEONLY - Nonlinear solver that performs one Newton step and does not compute any norms. 111f6dfbefdSBarry Smith The main purpose of this solver is to solve transposed linear problems using the `SNES` interface, without 1121ef27442SStefano Zampini any additional overhead in the form of vector operations within adjoint solvers. 1131ef27442SStefano Zampini 1141ef27442SStefano Zampini Level: beginner 1151ef27442SStefano Zampini 116f6dfbefdSBarry Smith .seealso: `SNES`, `SNESType`, `SNESCreate()`, `SNES`, `SNESSetType()`, `SNESKSPTRANSPOSEONLY`, `SNESNEWTONLS`, `SNESNEWTONTR` 1171ef27442SStefano Zampini M*/ 1189371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode SNESCreate_KSPTRANSPOSEONLY(SNES snes) { 1191ef27442SStefano Zampini SNES_KSPONLY *kspo; 1201ef27442SStefano Zampini 1211ef27442SStefano Zampini PetscFunctionBegin; 1229566063dSJacob Faibussowitsch PetscCall(SNESCreate_KSPONLY(snes)); 1239566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)snes, SNESKSPTRANSPOSEONLY)); 1241ef27442SStefano Zampini kspo = (SNES_KSPONLY *)snes->data; 1251ef27442SStefano Zampini kspo->transpose_solve = PETSC_TRUE; 126b79b07cfSJed Brown PetscFunctionReturn(0); 127b79b07cfSJed Brown } 128