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 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; 12*a3e9d663SJames 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 27451891c6SStefano Zampini if (!snes->vec_func_init_set) { 289566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, X, F)); 29451891c6SStefano Zampini } else snes->vec_func_init_set = PETSC_FALSE; 30451891c6SStefano Zampini 31*a3e9d663SJames Wright PetscCall(SNESGetNormSchedule(snes, &normschedule)); 32*a3e9d663SJames Wright if (snes->numbermonitors && (normschedule == SNES_NORM_ALWAYS || normschedule == SNES_NORM_INITIAL_ONLY || normschedule == SNES_NORM_INITIAL_FINAL_ONLY)) { 33a5eaddd9SBarry Smith PetscReal fnorm; 349566063dSJacob Faibussowitsch PetscCall(VecNorm(F, NORM_2, &fnorm)); 355f3c5e7aSBarry Smith SNESCheckFunctionNorm(snes, fnorm); 369566063dSJacob Faibussowitsch PetscCall(SNESMonitor(snes, 0, fnorm)); 37a5eaddd9SBarry Smith } 38b79b07cfSJed Brown 395341784dSBarry Smith /* Call general purpose update function */ 40dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, update, 0); 415341784dSBarry Smith 42b79b07cfSJed Brown /* Solve J Y = F, where J is Jacobian matrix */ 439566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobian(snes, X, snes->jacobian, snes->jacobian_pre)); 4407b62357SFande Kong 4507b62357SFande Kong SNESCheckJacobianDomainerror(snes); 4607b62357SFande Kong 479566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(snes->ksp, snes->jacobian, snes->jacobian_pre)); 481ef27442SStefano Zampini if (ksponly->transpose_solve) { 499566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(snes->ksp, F, Y)); 501ef27442SStefano Zampini } else { 519566063dSJacob Faibussowitsch PetscCall(KSPSolve(snes->ksp, F, Y)); 521ef27442SStefano Zampini } 53422a814eSBarry Smith snes->reason = SNES_CONVERGED_ITS; 54422a814eSBarry Smith SNESCheckKSPSolve(snes); 551aa26658SKarl Rupp 569566063dSJacob Faibussowitsch PetscCall(KSPGetIterationNumber(snes->ksp, &lits)); 5763a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "iter=%" PetscInt_FMT ", linear solve iterations=%" PetscInt_FMT "\n", snes->iter, lits)); 58b79b07cfSJed Brown snes->iter++; 59b79b07cfSJed Brown 60b79b07cfSJed Brown /* Take the computed step. */ 619566063dSJacob Faibussowitsch PetscCall(VecAXPY(X, -1.0, Y)); 62*a3e9d663SJames Wright 63*a3e9d663SJames Wright if (snes->numbermonitors && (normschedule == SNES_NORM_ALWAYS || normschedule == SNES_NORM_FINAL_ONLY || normschedule == SNES_NORM_INITIAL_FINAL_ONLY)) { 64a5eaddd9SBarry Smith PetscReal fnorm; 659566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, X, F)); 669566063dSJacob Faibussowitsch PetscCall(VecNorm(F, NORM_2, &fnorm)); 675f3c5e7aSBarry Smith SNESCheckFunctionNorm(snes, fnorm); 689566063dSJacob Faibussowitsch PetscCall(SNESMonitor(snes, 1, fnorm)); 69a5eaddd9SBarry Smith } 703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 71b79b07cfSJed Brown } 72b79b07cfSJed Brown 73d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetUp_KSPONLY(SNES snes) 74d71ae5a4SJacob Faibussowitsch { 75b79b07cfSJed Brown PetscFunctionBegin; 769566063dSJacob Faibussowitsch PetscCall(SNESSetUpMatrices(snes)); 773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 78b79b07cfSJed Brown } 79b79b07cfSJed Brown 80d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESDestroy_KSPONLY(SNES snes) 81d71ae5a4SJacob Faibussowitsch { 82b79b07cfSJed Brown PetscFunctionBegin; 839566063dSJacob Faibussowitsch PetscCall(PetscFree(snes->data)); 843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 85b79b07cfSJed Brown } 86b79b07cfSJed Brown 87b79b07cfSJed Brown /*MC 88420bcc1bSBarry Smith SNESKSPONLY - Nonlinear solver that performs one Newton step with `KSPSolve()` and does not compute any norms. 89b79b07cfSJed Brown 90b79b07cfSJed Brown Level: beginner 91b79b07cfSJed Brown 92420bcc1bSBarry Smith Note: 93420bcc1bSBarry Smith The main purpose of this solver is to solve linear problems using the `SNES` interface, without 94420bcc1bSBarry Smith any additional overhead in the form of vector norm operations. 95420bcc1bSBarry Smith 96420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESType`, `SNESCreate()`, `SNES`, `SNESSetType()`, `SNESNEWTONLS`, `SNESNEWTONTR`, `SNESKSPTRANSPOSEONLY` 97b79b07cfSJed Brown M*/ 98d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode SNESCreate_KSPONLY(SNES snes) 99d71ae5a4SJacob Faibussowitsch { 1001ef27442SStefano Zampini SNES_KSPONLY *ksponly; 101b79b07cfSJed Brown 102b79b07cfSJed Brown PetscFunctionBegin; 103b79b07cfSJed Brown snes->ops->setup = SNESSetUp_KSPONLY; 104b79b07cfSJed Brown snes->ops->solve = SNESSolve_KSPONLY; 105b79b07cfSJed Brown snes->ops->destroy = SNESDestroy_KSPONLY; 1069e5d0892SLisandro Dalcin snes->ops->setfromoptions = NULL; 1079e5d0892SLisandro Dalcin snes->ops->view = NULL; 1089e5d0892SLisandro Dalcin snes->ops->reset = NULL; 109b79b07cfSJed Brown 11042f4f86dSBarry Smith snes->usesksp = PETSC_TRUE; 111efd4aadfSBarry Smith snes->usesnpc = PETSC_FALSE; 11242f4f86dSBarry Smith 1134fc747eaSLawrence Mitchell snes->alwayscomputesfinalresidual = PETSC_FALSE; 1144fc747eaSLawrence Mitchell 11577e5a1f9SBarry Smith PetscCall(SNESParametersInitialize(snes)); 11677e5a1f9SBarry Smith 1174dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&ksponly)); 1181ef27442SStefano Zampini snes->data = (void *)ksponly; 1193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1201ef27442SStefano Zampini } 1211ef27442SStefano Zampini 1221ef27442SStefano Zampini /*MC 123420bcc1bSBarry Smith SNESKSPTRANSPOSEONLY - Nonlinear solver that performs one Newton step with `KSPSolveTranspose()` and does not compute any norms. 1241ef27442SStefano Zampini 1251ef27442SStefano Zampini Level: beginner 1261ef27442SStefano Zampini 127420bcc1bSBarry Smith Note: 128420bcc1bSBarry Smith The main purpose of this solver is to solve transposed linear problems using the `SNES` interface, without 129420bcc1bSBarry Smith any additional overhead in the form of vector operations within adjoint solvers. 130420bcc1bSBarry Smith 131420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESType`, `SNESCreate()`, `SNES`, `SNESSetType()`, `SNESKS`, `SNESNEWTONLS`, `SNESNEWTONTR` 1321ef27442SStefano Zampini M*/ 133d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode SNESCreate_KSPTRANSPOSEONLY(SNES snes) 134d71ae5a4SJacob Faibussowitsch { 1351ef27442SStefano Zampini SNES_KSPONLY *kspo; 1361ef27442SStefano Zampini 1371ef27442SStefano Zampini PetscFunctionBegin; 1389566063dSJacob Faibussowitsch PetscCall(SNESCreate_KSPONLY(snes)); 1399566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)snes, SNESKSPTRANSPOSEONLY)); 1401ef27442SStefano Zampini kspo = (SNES_KSPONLY *)snes->data; 1411ef27442SStefano Zampini kspo->transpose_solve = PETSC_TRUE; 1423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 143b79b07cfSJed Brown } 144