1af0996ceSBarry Smith #include <petsc/private/snesimpl.h> /*I "petscsnes.h" I*/ 2*76c63389SBarry Smith #include <petsc/private/linesearchimpl.h> /*I "petscsnes.h" I*/ 307475bc1SBarry Smith #include <petscdmshell.h> 4d96771aaSLisandro Dalcin #include <petscdraw.h> 5a01aa210SMatthew G. Knepley #include <petscds.h> 634b4d3a8SMatthew G. Knepley #include <petscdmadaptor.h> 706fc46c8SMatthew G. Knepley #include <petscconvest.h> 89b94acceSBarry Smith 9ace3abfcSBarry Smith PetscBool SNESRegisterAllCalled = PETSC_FALSE; 100298fd71SBarry Smith PetscFunctionList SNESList = NULL; 118ba1e511SMatthew Knepley 128ba1e511SMatthew Knepley /* Logging support */ 1322c6f798SBarry Smith PetscClassId SNES_CLASSID, DMSNES_CLASSID; 1497276fddSZach Atkins PetscLogEvent SNES_Solve, SNES_SetUp, SNES_FunctionEval, SNES_JacobianEval, SNES_NGSEval, SNES_NGSFuncEval, SNES_NewtonALEval, SNES_NPCSolve, SNES_ObjectiveEval; 15a09944afSBarry Smith 16e113a28aSBarry Smith /*@ 17dc4c0fb0SBarry Smith SNESSetErrorIfNotConverged - Causes `SNESSolve()` to generate an error immediately if the solver has not converged. 18e113a28aSBarry Smith 19c3339decSBarry Smith Logically Collective 20e113a28aSBarry Smith 21e113a28aSBarry Smith Input Parameters: 22f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 23f6dfbefdSBarry Smith - flg - `PETSC_TRUE` indicates you want the error generated 24e113a28aSBarry Smith 2520f4b53cSBarry Smith Options Database Key: 2667b8a455SSatish Balay . -snes_error_if_not_converged <true,false> - cause an immediate error condition and stop the program if the solver does not converge 27e113a28aSBarry Smith 28e113a28aSBarry Smith Level: intermediate 29e113a28aSBarry Smith 30f6dfbefdSBarry Smith Note: 31f6dfbefdSBarry Smith Normally PETSc continues if a solver fails to converge, you can call `SNESGetConvergedReason()` after a `SNESSolve()` 32f6dfbefdSBarry Smith to determine if it has converged. Otherwise the solution may be inaccurate or wrong 33e113a28aSBarry Smith 341cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetErrorIfNotConverged()`, `KSPGetErrorIfNotConverged()`, `KSPSetErrorIfNotConverged()` 35e113a28aSBarry Smith @*/ 36d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetErrorIfNotConverged(SNES snes, PetscBool flg) 37d71ae5a4SJacob Faibussowitsch { 38e113a28aSBarry Smith PetscFunctionBegin; 39e113a28aSBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 40acfcf0e5SJed Brown PetscValidLogicalCollectiveBool(snes, flg, 2); 41e113a28aSBarry Smith snes->errorifnotconverged = flg; 423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 43e113a28aSBarry Smith } 44e113a28aSBarry Smith 45e113a28aSBarry Smith /*@ 46f6dfbefdSBarry Smith SNESGetErrorIfNotConverged - Indicates if `SNESSolve()` will generate an error if the solver does not converge? 47e113a28aSBarry Smith 48e113a28aSBarry Smith Not Collective 49e113a28aSBarry Smith 50e113a28aSBarry Smith Input Parameter: 51f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 52e113a28aSBarry Smith 53e113a28aSBarry Smith Output Parameter: 54f6dfbefdSBarry Smith . flag - `PETSC_TRUE` if it will generate an error, else `PETSC_FALSE` 55e113a28aSBarry Smith 56e113a28aSBarry Smith Level: intermediate 57e113a28aSBarry Smith 581cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetErrorIfNotConverged()`, `KSPGetErrorIfNotConverged()`, `KSPSetErrorIfNotConverged()` 59e113a28aSBarry Smith @*/ 60d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetErrorIfNotConverged(SNES snes, PetscBool *flag) 61d71ae5a4SJacob Faibussowitsch { 62e113a28aSBarry Smith PetscFunctionBegin; 63e113a28aSBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 644f572ea9SToby Isaac PetscAssertPointer(flag, 2); 65e113a28aSBarry Smith *flag = snes->errorifnotconverged; 663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 67e113a28aSBarry Smith } 68e113a28aSBarry Smith 694fc747eaSLawrence Mitchell /*@ 70dc4c0fb0SBarry Smith SNESSetAlwaysComputesFinalResidual - tells the `SNES` to always compute the residual (nonlinear function value) at the final solution 714fc747eaSLawrence Mitchell 72c3339decSBarry Smith Logically Collective 734fc747eaSLawrence Mitchell 744fc747eaSLawrence Mitchell Input Parameters: 75f6dfbefdSBarry Smith + snes - the shell `SNES` 76f6dfbefdSBarry Smith - flg - `PETSC_TRUE` to always compute the residual 774fc747eaSLawrence Mitchell 784fc747eaSLawrence Mitchell Level: advanced 794fc747eaSLawrence Mitchell 80f6dfbefdSBarry Smith Note: 81f6dfbefdSBarry Smith Some solvers (such as smoothers in a `SNESFAS`) do not need the residual computed at the final solution so skip computing it 82f6dfbefdSBarry Smith to save time. 83f6dfbefdSBarry Smith 84420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSolve()`, `SNESGetAlwaysComputesFinalResidual()` 854fc747eaSLawrence Mitchell @*/ 86d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetAlwaysComputesFinalResidual(SNES snes, PetscBool flg) 87d71ae5a4SJacob Faibussowitsch { 884fc747eaSLawrence Mitchell PetscFunctionBegin; 894fc747eaSLawrence Mitchell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 904fc747eaSLawrence Mitchell snes->alwayscomputesfinalresidual = flg; 913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 924fc747eaSLawrence Mitchell } 934fc747eaSLawrence Mitchell 944fc747eaSLawrence Mitchell /*@ 95f6dfbefdSBarry Smith SNESGetAlwaysComputesFinalResidual - checks if the `SNES` always computes the residual at the final solution 964fc747eaSLawrence Mitchell 97c3339decSBarry Smith Logically Collective 984fc747eaSLawrence Mitchell 994fc747eaSLawrence Mitchell Input Parameter: 100f6dfbefdSBarry Smith . snes - the `SNES` context 1014fc747eaSLawrence Mitchell 1024fc747eaSLawrence Mitchell Output Parameter: 103f6dfbefdSBarry Smith . flg - `PETSC_TRUE` if the residual is computed 1044fc747eaSLawrence Mitchell 1054fc747eaSLawrence Mitchell Level: advanced 1064fc747eaSLawrence Mitchell 107420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSolve()`, `SNESSetAlwaysComputesFinalResidual()` 1084fc747eaSLawrence Mitchell @*/ 109d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetAlwaysComputesFinalResidual(SNES snes, PetscBool *flg) 110d71ae5a4SJacob Faibussowitsch { 1114fc747eaSLawrence Mitchell PetscFunctionBegin; 1124fc747eaSLawrence Mitchell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1134fc747eaSLawrence Mitchell *flg = snes->alwayscomputesfinalresidual; 1143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1154fc747eaSLawrence Mitchell } 1164fc747eaSLawrence Mitchell 117e725d27bSBarry Smith /*@ 118f6dfbefdSBarry Smith SNESSetFunctionDomainError - tells `SNES` that the input vector, a proposed new solution, to your function you provided to `SNESSetFunction()` is not 119*76c63389SBarry Smith in the function's domain. For example, a step with negative pressure. 1204936397dSBarry Smith 1216b1535e8SBarry Smith Not Collective 1224936397dSBarry Smith 1232fe279fdSBarry Smith Input Parameter: 124f6dfbefdSBarry Smith . snes - the `SNES` context 1254936397dSBarry Smith 12628529972SSatish Balay Level: advanced 1274936397dSBarry Smith 128ced0f3aeSBarry Smith Notes: 1296b1535e8SBarry Smith This does not need to be called by all processes in the `SNES` MPI communicator. 1306b1535e8SBarry Smith 131*76c63389SBarry Smith A few solvers will try to cut the step size to avoid the domain error but for other solvers `SNESSolve()` stops iterating and and 132*76c63389SBarry Smith returns with a `SNESConvergedReason` of `SNES_DIVERGED_FUNCTION_DOMAIN` 133ced0f3aeSBarry Smith 134f0b84518SBarry Smith You can direct `SNES` to avoid certain steps by using `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()` or 135f0b84518SBarry Smith `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()` 136f0b84518SBarry Smith 137*76c63389SBarry Smith You should always call `SNESGetConvergedReason()` after each `SNESSolve()` and verify if the iteration converged (positive result) or diverged (negative result). 138*76c63389SBarry Smith 1396b1535e8SBarry Smith You can call `SNESSetJacobianDomainError()` during a Jacobian computation to indicate the proposed solution is not in the domain. 1406b1535e8SBarry Smith 1416b1535e8SBarry Smith Developer Note: 142*76c63389SBarry Smith This value is used by `SNESCheckFunctionDomainError()` to determine if the `SNESConvergedReason` is set to `SNES_DIVERGED_FUNCTION_DOMAIN` 1436b1535e8SBarry Smith 1448434afd1SBarry Smith .seealso: [](ch_snes), `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetJacobianDomainError()`, `SNESVISetVariableBounds()`, 1456b1535e8SBarry Smith `SNESVISetComputeVariableBounds()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, 146*76c63389SBarry Smith `SNES_DIVERGED_FUNCTION_DOMAIN`, `SNESSetObjectiveDomainError()` 1474936397dSBarry Smith @*/ 148d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionDomainError(SNES snes) 149d71ae5a4SJacob Faibussowitsch { 1504936397dSBarry Smith PetscFunctionBegin; 1510700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 152*76c63389SBarry Smith snes->functiondomainerror = PETSC_TRUE; 153*76c63389SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 154*76c63389SBarry Smith } 155*76c63389SBarry Smith 156*76c63389SBarry Smith /*@ 157*76c63389SBarry Smith SNESSetObjectiveDomainError - tells `SNES` that the input vector, a proposed new solution, to your function you provided to `SNESSetObjective()` is not 158*76c63389SBarry Smith in the function's domain. For example, a step with negative pressure. 159*76c63389SBarry Smith 160*76c63389SBarry Smith Not Collective 161*76c63389SBarry Smith 162*76c63389SBarry Smith Input Parameter: 163*76c63389SBarry Smith . snes - the `SNES` context 164*76c63389SBarry Smith 165*76c63389SBarry Smith Level: advanced 166*76c63389SBarry Smith 167*76c63389SBarry Smith Notes: 168*76c63389SBarry Smith This does not need to be called by all processes in the `SNES` MPI communicator. 169*76c63389SBarry Smith 170*76c63389SBarry Smith A few solvers will try to cut the step size to avoid the domain error but for other solvers `SNESSolve()` stops iterating and and 171*76c63389SBarry Smith returns with a `SNESConvergedReason` of `SNES_DIVERGED_FUNCTION_DOMAIN` 172*76c63389SBarry Smith 173*76c63389SBarry Smith You can direct `SNES` to avoid certain steps by using `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()` or 174*76c63389SBarry Smith `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()` 175*76c63389SBarry Smith 176*76c63389SBarry Smith You should always call `SNESGetConvergedReason()` after each `SNESSolve()` and verify if the iteration converged (positive result) or diverged (negative result). 177*76c63389SBarry Smith 178*76c63389SBarry Smith You can call `SNESSetJacobianDomainError()` during a Jacobian computation to indicate the proposed solution is not in the domain. 179*76c63389SBarry Smith 180*76c63389SBarry Smith Developer Note: 181*76c63389SBarry Smith This value is used by `SNESCheckFunctionDomainError()` to determine if the `SNESConvergedReason` is set to `SNES_DIVERGED_FUNCTION_DOMAIN` 182*76c63389SBarry Smith 183*76c63389SBarry Smith .seealso: [](ch_snes), `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetJacobianDomainError()`, `SNESVISetVariableBounds()`, 184*76c63389SBarry Smith `SNESVISetComputeVariableBounds()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, 185*76c63389SBarry Smith `SNES_DIVERGED_FUNCTION_DOMAIN`, `SNESSetFunctionDomainError()` 186*76c63389SBarry Smith @*/ 187*76c63389SBarry Smith PetscErrorCode SNESSetObjectiveDomainError(SNES snes) 188*76c63389SBarry Smith { 189*76c63389SBarry Smith PetscFunctionBegin; 190*76c63389SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 191*76c63389SBarry Smith snes->objectivedomainerror = PETSC_TRUE; 1923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1934936397dSBarry Smith } 1944936397dSBarry Smith 1956a388c36SPeter Brune /*@ 196f6dfbefdSBarry Smith SNESSetJacobianDomainError - tells `SNES` that the function you provided to `SNESSetJacobian()` at the proposed step. For example there is a negative element transformation. 19707b62357SFande Kong 198c3339decSBarry Smith Logically Collective 19907b62357SFande Kong 2002fe279fdSBarry Smith Input Parameter: 201f6dfbefdSBarry Smith . snes - the `SNES` context 20207b62357SFande Kong 20307b62357SFande Kong Level: advanced 20407b62357SFande Kong 205ced0f3aeSBarry Smith Notes: 206ced0f3aeSBarry Smith If this is called the `SNESSolve()` stops iterating and returns with a `SNESConvergedReason` of `SNES_DIVERGED_FUNCTION_DOMAIN` 207ced0f3aeSBarry Smith 208ced0f3aeSBarry Smith You should always call `SNESGetConvergedReason()` after each `SNESSolve()` and verify if the iteration converged (positive result) or diverged (negative result). 209ced0f3aeSBarry Smith 210f0b84518SBarry Smith You can direct `SNES` to avoid certain steps by using `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()` or 211f0b84518SBarry Smith `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()` 212f0b84518SBarry Smith 2138434afd1SBarry Smith .seealso: [](ch_snes), `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetFunctionDomainError()`, `SNESVISetVariableBounds()`, 214ced0f3aeSBarry Smith `SNESVISetComputeVariableBounds()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESConvergedReason`, `SNESGetConvergedReason()` 21507b62357SFande Kong @*/ 216d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetJacobianDomainError(SNES snes) 217d71ae5a4SJacob Faibussowitsch { 21807b62357SFande Kong PetscFunctionBegin; 21907b62357SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2205f80ce2aSJacob Faibussowitsch PetscCheck(!snes->errorifnotconverged, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "User code indicates computeJacobian does not make sense"); 22107b62357SFande Kong snes->jacobiandomainerror = PETSC_TRUE; 2223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22307b62357SFande Kong } 22407b62357SFande Kong 22507b62357SFande Kong /*@ 226*76c63389SBarry Smith SNESSetCheckJacobianDomainError - tells `SNESSolve()` whether to check if the user called `SNESSetJacobianDomainError()` to indicate a Jacobian domain error after 227*76c63389SBarry Smith each Jacobian evaluation. 228b351a90bSFande Kong 229c3339decSBarry Smith Logically Collective 230b351a90bSFande Kong 231b351a90bSFande Kong Input Parameters: 23220f4b53cSBarry Smith + snes - the `SNES` context 233f6dfbefdSBarry Smith - flg - indicates if or not to check Jacobian domain error after each Jacobian evaluation 234b351a90bSFande Kong 235b351a90bSFande Kong Level: advanced 236b351a90bSFande Kong 237*76c63389SBarry Smith Notes: 238*76c63389SBarry Smith By default, it checks for the Jacobian domain error in the debug mode, and does not check it in the optimized mode. 239*76c63389SBarry Smith 240f6dfbefdSBarry Smith Checks require one extra parallel synchronization for each Jacobian evaluation 241f6dfbefdSBarry Smith 2428434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetFunctionDomainError()`, `SNESGetCheckJacobianDomainError()` 243b351a90bSFande Kong @*/ 244d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCheckJacobianDomainError(SNES snes, PetscBool flg) 245d71ae5a4SJacob Faibussowitsch { 246b351a90bSFande Kong PetscFunctionBegin; 247b351a90bSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 248b351a90bSFande Kong snes->checkjacdomainerror = flg; 2493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 250b351a90bSFande Kong } 251b351a90bSFande Kong 252b351a90bSFande Kong /*@ 253420bcc1bSBarry Smith SNESGetCheckJacobianDomainError - Get an indicator whether or not `SNES` is checking Jacobian domain errors after each Jacobian evaluation. 2548383d7d7SFande Kong 255c3339decSBarry Smith Logically Collective 2568383d7d7SFande Kong 2572fe279fdSBarry Smith Input Parameter: 258f6dfbefdSBarry Smith . snes - the `SNES` context 2598383d7d7SFande Kong 2602fe279fdSBarry Smith Output Parameter: 261420bcc1bSBarry Smith . flg - `PETSC_FALSE` indicates that it is not checking Jacobian domain errors after each Jacobian evaluation 2628383d7d7SFande Kong 2638383d7d7SFande Kong Level: advanced 2648383d7d7SFande Kong 2658434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetFunctionDomainError()`, `SNESSetCheckJacobianDomainError()` 2668383d7d7SFande Kong @*/ 267d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetCheckJacobianDomainError(SNES snes, PetscBool *flg) 268d71ae5a4SJacob Faibussowitsch { 2698383d7d7SFande Kong PetscFunctionBegin; 2708383d7d7SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2714f572ea9SToby Isaac PetscAssertPointer(flg, 2); 2728383d7d7SFande Kong *flg = snes->checkjacdomainerror; 2733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2748383d7d7SFande Kong } 2758383d7d7SFande Kong 2768383d7d7SFande Kong /*@ 277f6dfbefdSBarry Smith SNESLoad - Loads a `SNES` that has been stored in `PETSCVIEWERBINARY` with `SNESView()`. 27855849f57SBarry Smith 279c3339decSBarry Smith Collective 28055849f57SBarry Smith 28155849f57SBarry Smith Input Parameters: 282e4094ef1SJacob Faibussowitsch + snes - the newly loaded `SNES`, this needs to have been created with `SNESCreate()` or 283f6dfbefdSBarry Smith some related function before a call to `SNESLoad()`. 284f6dfbefdSBarry Smith - viewer - binary file viewer, obtained from `PetscViewerBinaryOpen()` 28555849f57SBarry Smith 28655849f57SBarry Smith Level: intermediate 28755849f57SBarry Smith 288f6dfbefdSBarry Smith Note: 289420bcc1bSBarry Smith The `SNESType` is determined by the data in the file, any type set into the `SNES` before this call is ignored. 29055849f57SBarry Smith 2911cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `PetscViewer`, `SNESCreate()`, `SNESType`, `PetscViewerBinaryOpen()`, `SNESView()`, `MatLoad()`, `VecLoad()` 29255849f57SBarry Smith @*/ 293d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESLoad(SNES snes, PetscViewer viewer) 294d71ae5a4SJacob Faibussowitsch { 29555849f57SBarry Smith PetscBool isbinary; 296060da220SMatthew G. Knepley PetscInt classid; 29755849f57SBarry Smith char type[256]; 29855849f57SBarry Smith KSP ksp; 2992d53ad75SBarry Smith DM dm; 3002d53ad75SBarry Smith DMSNES dmsnes; 30155849f57SBarry Smith 30255849f57SBarry Smith PetscFunctionBegin; 3032d53ad75SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 30455849f57SBarry Smith PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 3059566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 3065f80ce2aSJacob Faibussowitsch PetscCheck(isbinary, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerBinaryOpen()"); 30755849f57SBarry Smith 3089566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer, &classid, 1, NULL, PETSC_INT)); 3095f80ce2aSJacob Faibussowitsch PetscCheck(classid == SNES_FILE_CLASSID, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Not SNES next in file"); 3109566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer, type, 256, NULL, PETSC_CHAR)); 3119566063dSJacob Faibussowitsch PetscCall(SNESSetType(snes, type)); 312dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, load, viewer); 3139566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 3149566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &dmsnes)); 3159566063dSJacob Faibussowitsch PetscCall(DMSNESLoad(dmsnes, viewer)); 3169566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 3179566063dSJacob Faibussowitsch PetscCall(KSPLoad(ksp, viewer)); 3183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 31955849f57SBarry Smith } 3206a388c36SPeter Brune 3219804daf3SBarry Smith #include <petscdraw.h> 322e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS) 323e04113cfSBarry Smith #include <petscviewersaws.h> 324bfb97211SBarry Smith #endif 3258404b7f3SBarry Smith 326ffeef943SBarry Smith /*@ 327dc4c0fb0SBarry Smith SNESViewFromOptions - View a `SNES` based on values in the options database 328fe2efc57SMark 329c3339decSBarry Smith Collective 330fe2efc57SMark 331fe2efc57SMark Input Parameters: 332f6dfbefdSBarry Smith + A - the `SNES` context 333dc4c0fb0SBarry Smith . obj - Optional object that provides the options prefix for the checks 334736c3998SJose E. Roman - name - command line option 335fe2efc57SMark 336fe2efc57SMark Level: intermediate 337f6dfbefdSBarry Smith 3381cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESView`, `PetscObjectViewFromOptions()`, `SNESCreate()` 339fe2efc57SMark @*/ 340d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESViewFromOptions(SNES A, PetscObject obj, const char name[]) 341d71ae5a4SJacob Faibussowitsch { 342fe2efc57SMark PetscFunctionBegin; 343fe2efc57SMark PetscValidHeaderSpecific(A, SNES_CLASSID, 1); 3449566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 3453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 346fe2efc57SMark } 347fe2efc57SMark 348789d8953SBarry Smith PETSC_EXTERN PetscErrorCode SNESComputeJacobian_DMDA(SNES, Vec, Mat, Mat, void *); 349789d8953SBarry Smith 350ffeef943SBarry Smith /*@ 351dc4c0fb0SBarry Smith SNESView - Prints or visualizes the `SNES` data structure. 3529b94acceSBarry Smith 353c3339decSBarry Smith Collective 354fee21e36SBarry Smith 355c7afd0dbSLois Curfman McInnes Input Parameters: 356f6dfbefdSBarry Smith + snes - the `SNES` context 357f6dfbefdSBarry Smith - viewer - the `PetscViewer` 358c7afd0dbSLois Curfman McInnes 3599b94acceSBarry Smith Options Database Key: 360f6dfbefdSBarry Smith . -snes_view - Calls `SNESView()` at end of `SNESSolve()` 3619b94acceSBarry Smith 362dc4c0fb0SBarry Smith Level: beginner 363dc4c0fb0SBarry Smith 3649b94acceSBarry Smith Notes: 3659b94acceSBarry Smith The available visualization contexts include 366f6dfbefdSBarry Smith + `PETSC_VIEWER_STDOUT_SELF` - standard output (default) 367f6dfbefdSBarry Smith - `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard 368c8a8ba5cSLois Curfman McInnes output where only the first processor opens 369c8a8ba5cSLois Curfman McInnes the file. All other processors send their 370c8a8ba5cSLois Curfman McInnes data to the first processor to print. 3719b94acceSBarry Smith 372052bf0daSPierre Jolivet The available formats include 373f6dfbefdSBarry Smith + `PETSC_VIEWER_DEFAULT` - standard output (default) 374f6dfbefdSBarry Smith - `PETSC_VIEWER_ASCII_INFO_DETAIL` - more verbose output for `SNESNASM` 375052bf0daSPierre Jolivet 3763e081fefSLois Curfman McInnes The user can open an alternative visualization context with 377f6dfbefdSBarry Smith `PetscViewerASCIIOpen()` - output to a specified file. 3789b94acceSBarry Smith 379f6dfbefdSBarry Smith In the debugger you can do "call `SNESView`(snes,0)" to display the `SNES` solver. (The same holds for any PETSc object viewer). 380595c91d4SBarry Smith 3811cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESLoad()`, `SNESCreate()`, `PetscViewerASCIIOpen()` 3829b94acceSBarry Smith @*/ 383d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESView(SNES snes, PetscViewer viewer) 384d71ae5a4SJacob Faibussowitsch { 385fa9f3622SBarry Smith SNESKSPEW *kctx; 38694b7f48cSBarry Smith KSP ksp; 3877f1410a3SPeter Brune SNESLineSearch linesearch; 3889f196a02SMartin Diehl PetscBool isascii, isstring, isbinary, isdraw; 3892d53ad75SBarry Smith DMSNES dmsnes; 390e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS) 391536b137fSBarry Smith PetscBool issaws; 392bfb97211SBarry Smith #endif 3939b94acceSBarry Smith 3943a40ed3dSBarry Smith PetscFunctionBegin; 3950700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 39648a46eb9SPierre Jolivet if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &viewer)); 3970700a824SBarry Smith PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 398c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, viewer, 2); 39974679c65SBarry Smith 4009f196a02SMartin Diehl PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 4019566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 4029566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 4039566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 404e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS) 4059566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 406bfb97211SBarry Smith #endif 4079f196a02SMartin Diehl if (isascii) { 408dc0571f2SMatthew G. Knepley SNESNormSchedule normschedule; 4098404b7f3SBarry Smith DM dm; 4108434afd1SBarry Smith SNESJacobianFn *cJ; 4118404b7f3SBarry Smith void *ctx; 412789d8953SBarry Smith const char *pre = ""; 413dc0571f2SMatthew G. Knepley 4149566063dSJacob Faibussowitsch PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)snes, viewer)); 41548a46eb9SPierre Jolivet if (!snes->setupcalled) PetscCall(PetscViewerASCIIPrintf(viewer, " SNES has not been set up so information may be incomplete\n")); 416e7788613SBarry Smith if (snes->ops->view) { 4179566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 418dbbe0bcdSBarry Smith PetscUseTypeMethod(snes, view, viewer); 4199566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 4200ef38995SBarry Smith } 42177e5a1f9SBarry Smith if (snes->max_funcs == PETSC_UNLIMITED) { 42277e5a1f9SBarry Smith PetscCall(PetscViewerASCIIPrintf(viewer, " maximum iterations=%" PetscInt_FMT ", maximum function evaluations=unlimited\n", snes->max_its)); 42377e5a1f9SBarry Smith } else { 42463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " maximum iterations=%" PetscInt_FMT ", maximum function evaluations=%" PetscInt_FMT "\n", snes->max_its, snes->max_funcs)); 42577e5a1f9SBarry Smith } 4269566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " tolerances: relative=%g, absolute=%g, solution=%g\n", (double)snes->rtol, (double)snes->abstol, (double)snes->stol)); 42748a46eb9SPierre Jolivet if (snes->usesksp) PetscCall(PetscViewerASCIIPrintf(viewer, " total number of linear solver iterations=%" PetscInt_FMT "\n", snes->linear_its)); 42863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " total number of function evaluations=%" PetscInt_FMT "\n", snes->nfuncs)); 4299566063dSJacob Faibussowitsch PetscCall(SNESGetNormSchedule(snes, &normschedule)); 4309566063dSJacob Faibussowitsch if (normschedule > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " norm schedule %s\n", SNESNormSchedules[normschedule])); 43148a46eb9SPierre Jolivet if (snes->gridsequence) PetscCall(PetscViewerASCIIPrintf(viewer, " total number of grid sequence refinements=%" PetscInt_FMT "\n", snes->gridsequence)); 4329b94acceSBarry Smith if (snes->ksp_ewconv) { 433fa9f3622SBarry Smith kctx = (SNESKSPEW *)snes->kspconvctx; 4349b94acceSBarry Smith if (kctx) { 43563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Eisenstat-Walker computation of KSP relative tolerance (version %" PetscInt_FMT ")\n", kctx->version)); 4369566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " rtol_0=%g, rtol_max=%g, threshold=%g\n", (double)kctx->rtol_0, (double)kctx->rtol_max, (double)kctx->threshold)); 4379566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " gamma=%g, alpha=%g, alpha2=%g\n", (double)kctx->gamma, (double)kctx->alpha, (double)kctx->alpha2)); 4389b94acceSBarry Smith } 4399b94acceSBarry Smith } 440eb1f6c34SBarry Smith if (snes->lagpreconditioner == -1) { 4419566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Preconditioned is never rebuilt\n")); 442eb1f6c34SBarry Smith } else if (snes->lagpreconditioner > 1) { 44363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Preconditioned is rebuilt every %" PetscInt_FMT " new Jacobians\n", snes->lagpreconditioner)); 444eb1f6c34SBarry Smith } 445eb1f6c34SBarry Smith if (snes->lagjacobian == -1) { 4469566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Jacobian is never rebuilt\n")); 447eb1f6c34SBarry Smith } else if (snes->lagjacobian > 1) { 44863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Jacobian is rebuilt every %" PetscInt_FMT " SNES iterations\n", snes->lagjacobian)); 449eb1f6c34SBarry Smith } 4509566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 4519566063dSJacob Faibussowitsch PetscCall(DMSNESGetJacobian(dm, &cJ, &ctx)); 452789d8953SBarry Smith if (snes->mf_operator) { 4539566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Jacobian is applied matrix-free with differencing\n")); 454789d8953SBarry Smith pre = "Preconditioning "; 455789d8953SBarry Smith } 4568404b7f3SBarry Smith if (cJ == SNESComputeJacobianDefault) { 4579566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %sJacobian is built using finite differences one column at a time\n", pre)); 4588404b7f3SBarry Smith } else if (cJ == SNESComputeJacobianDefaultColor) { 4599566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %sJacobian is built using finite differences with coloring\n", pre)); 460789d8953SBarry Smith /* it slightly breaks data encapsulation for access the DMDA information directly */ 461789d8953SBarry Smith } else if (cJ == SNESComputeJacobian_DMDA) { 462789d8953SBarry Smith MatFDColoring fdcoloring; 4639566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)dm, "DMDASNES_FDCOLORING", (PetscObject *)&fdcoloring)); 464789d8953SBarry Smith if (fdcoloring) { 4659566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %sJacobian is built using colored finite differences on a DMDA\n", pre)); 466789d8953SBarry Smith } else { 4679566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %sJacobian is built using a DMDA local Jacobian\n", pre)); 468789d8953SBarry Smith } 469996e1cbcSBarry Smith } else if (snes->mf && !snes->mf_operator) { 4709566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Jacobian is applied matrix-free with differencing, no explicit Jacobian\n")); 4718404b7f3SBarry Smith } 4720f5bd95cSBarry Smith } else if (isstring) { 473317d6ea6SBarry Smith const char *type; 4749566063dSJacob Faibussowitsch PetscCall(SNESGetType(snes, &type)); 4759566063dSJacob Faibussowitsch PetscCall(PetscViewerStringSPrintf(viewer, " SNESType: %-7.7s", type)); 476dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, view, viewer); 47755849f57SBarry Smith } else if (isbinary) { 47855849f57SBarry Smith PetscInt classid = SNES_FILE_CLASSID; 47955849f57SBarry Smith MPI_Comm comm; 48055849f57SBarry Smith PetscMPIInt rank; 48155849f57SBarry Smith char type[256]; 48255849f57SBarry Smith 4839566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 4849566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 485dd400576SPatrick Sanan if (rank == 0) { 4869566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryWrite(viewer, &classid, 1, PETSC_INT)); 4879566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(type, ((PetscObject)snes)->type_name, sizeof(type))); 4889566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryWrite(viewer, type, sizeof(type), PETSC_CHAR)); 48955849f57SBarry Smith } 490dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, view, viewer); 49172a02f06SBarry Smith } else if (isdraw) { 49272a02f06SBarry Smith PetscDraw draw; 49372a02f06SBarry Smith char str[36]; 49489fd9fafSBarry Smith PetscReal x, y, bottom, h; 49572a02f06SBarry Smith 4969566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 4979566063dSJacob Faibussowitsch PetscCall(PetscDrawGetCurrentPoint(draw, &x, &y)); 4989566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(str, "SNES: ", sizeof(str))); 4999566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(str, ((PetscObject)snes)->type_name, sizeof(str))); 5009566063dSJacob Faibussowitsch PetscCall(PetscDrawStringBoxed(draw, x, y, PETSC_DRAW_BLUE, PETSC_DRAW_BLACK, str, NULL, &h)); 50189fd9fafSBarry Smith bottom = y - h; 5029566063dSJacob Faibussowitsch PetscCall(PetscDrawPushCurrentPoint(draw, x, bottom)); 503dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, view, viewer); 504e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS) 505536b137fSBarry Smith } else if (issaws) { 506d45a07a7SBarry Smith PetscMPIInt rank; 5072657e9d9SBarry Smith const char *name; 508d45a07a7SBarry Smith 5099566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)snes, &name)); 5109566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 511dd400576SPatrick Sanan if (!((PetscObject)snes)->amsmem && rank == 0) { 512d45a07a7SBarry Smith char dir[1024]; 513d45a07a7SBarry Smith 5149566063dSJacob Faibussowitsch PetscCall(PetscObjectViewSAWs((PetscObject)snes, viewer)); 5159566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/its", name)); 516792fecdfSBarry Smith PetscCallSAWs(SAWs_Register, (dir, &snes->iter, 1, SAWs_READ, SAWs_INT)); 51748a46eb9SPierre Jolivet if (!snes->conv_hist) PetscCall(SNESSetConvergenceHistory(snes, NULL, NULL, PETSC_DECIDE, PETSC_TRUE)); 5189566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/conv_hist", name)); 519792fecdfSBarry Smith PetscCallSAWs(SAWs_Register, (dir, snes->conv_hist, 10, SAWs_READ, SAWs_DOUBLE)); 520f05ece33SBarry Smith } 521bfb97211SBarry Smith #endif 52272a02f06SBarry Smith } 52372a02f06SBarry Smith if (snes->linesearch) { 5249566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &linesearch)); 5259566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 5269566063dSJacob Faibussowitsch PetscCall(SNESLineSearchView(linesearch, viewer)); 5279566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 52819bcc07fSBarry Smith } 529efd4aadfSBarry Smith if (snes->npc && snes->usesnpc) { 5309566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 5319566063dSJacob Faibussowitsch PetscCall(SNESView(snes->npc, viewer)); 5329566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 5334a0c5b0cSMatthew G Knepley } 5349566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 5359566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(snes->dm, &dmsnes)); 5369566063dSJacob Faibussowitsch PetscCall(DMSNESView(dmsnes, viewer)); 5379566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 5382c155ee1SBarry Smith if (snes->usesksp) { 5399566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 5409566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 5419566063dSJacob Faibussowitsch PetscCall(KSPView(ksp, viewer)); 5429566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 5432c155ee1SBarry Smith } 54472a02f06SBarry Smith if (isdraw) { 54572a02f06SBarry Smith PetscDraw draw; 5469566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 5479566063dSJacob Faibussowitsch PetscCall(PetscDrawPopCurrentPoint(draw)); 5487f1410a3SPeter Brune } 5493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5509b94acceSBarry Smith } 5519b94acceSBarry Smith 55276b2cf59SMatthew Knepley /* 55376b2cf59SMatthew Knepley We retain a list of functions that also take SNES command 55476b2cf59SMatthew Knepley line options. These are called at the end SNESSetFromOptions() 55576b2cf59SMatthew Knepley */ 55676b2cf59SMatthew Knepley #define MAXSETFROMOPTIONS 5 557a7cc72afSBarry Smith static PetscInt numberofsetfromoptions; 5586849ba73SBarry Smith static PetscErrorCode (*othersetfromoptions[MAXSETFROMOPTIONS])(SNES); 55976b2cf59SMatthew Knepley 560ac226902SBarry Smith /*@C 561f6dfbefdSBarry Smith SNESAddOptionsChecker - Adds an additional function to check for `SNES` options. 56276b2cf59SMatthew Knepley 56376b2cf59SMatthew Knepley Not Collective 56476b2cf59SMatthew Knepley 56576b2cf59SMatthew Knepley Input Parameter: 56676b2cf59SMatthew Knepley . snescheck - function that checks for options 56776b2cf59SMatthew Knepley 568420bcc1bSBarry Smith Calling sequence of `snescheck`: 569420bcc1bSBarry Smith . snes - the `SNES` object for which it is checking options 570420bcc1bSBarry Smith 57176b2cf59SMatthew Knepley Level: developer 57276b2cf59SMatthew Knepley 5731cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()` 57476b2cf59SMatthew Knepley @*/ 575420bcc1bSBarry Smith PetscErrorCode SNESAddOptionsChecker(PetscErrorCode (*snescheck)(SNES snes)) 576d71ae5a4SJacob Faibussowitsch { 57776b2cf59SMatthew Knepley PetscFunctionBegin; 57863a3b9bcSJacob Faibussowitsch PetscCheck(numberofsetfromoptions < MAXSETFROMOPTIONS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many options checkers, only %d allowed", MAXSETFROMOPTIONS); 57976b2cf59SMatthew Knepley othersetfromoptions[numberofsetfromoptions++] = snescheck; 5803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 58176b2cf59SMatthew Knepley } 58276b2cf59SMatthew Knepley 583d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetUpMatrixFree_Private(SNES snes, PetscBool hasOperator, PetscInt version) 584d71ae5a4SJacob Faibussowitsch { 585aa3661deSLisandro Dalcin Mat J; 586895c21f2SBarry Smith MatNullSpace nullsp; 587aa3661deSLisandro Dalcin 588aa3661deSLisandro Dalcin PetscFunctionBegin; 5890700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 590aa3661deSLisandro Dalcin 59198613b67SLisandro Dalcin if (!snes->vec_func && (snes->jacobian || snes->jacobian_pre)) { 59298613b67SLisandro Dalcin Mat A = snes->jacobian, B = snes->jacobian_pre; 5939566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A ? A : B, NULL, &snes->vec_func)); 59498613b67SLisandro Dalcin } 59598613b67SLisandro Dalcin 5960fdf79fbSJacob Faibussowitsch PetscCheck(version == 1 || version == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "matrix-free operator routines, only version 1 and 2"); 597aa3661deSLisandro Dalcin if (version == 1) { 5989566063dSJacob Faibussowitsch PetscCall(MatCreateSNESMF(snes, &J)); 5999566063dSJacob Faibussowitsch PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix)); 6009566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(J)); 6011e2ae407SBarry Smith /* TODO: the version 2 code should be merged into the MatCreateSNESMF() and MatCreateMFFD() infrastructure and then removed */ 6020fdf79fbSJacob Faibussowitsch } else /* if (version == 2) */ { 6035f80ce2aSJacob Faibussowitsch PetscCheck(snes->vec_func, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "SNESSetFunction() must be called first"); 604570b7f6dSBarry Smith #if !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_REAL_SINGLE) && !defined(PETSC_USE_REAL___FLOAT128) && !defined(PETSC_USE_REAL___FP16) 605f6dfbefdSBarry Smith PetscCall(MatCreateSNESMFMore(snes, snes->vec_func, &J)); 606aa3661deSLisandro Dalcin #else 6072479783cSJose E. Roman SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "matrix-free operator routines (version 2)"); 608aa3661deSLisandro Dalcin #endif 6090fdf79fbSJacob Faibussowitsch } 610aa3661deSLisandro Dalcin 61101c1178eSBarry Smith /* attach any user provided null space that was on Amat to the newly created matrix-free matrix */ 612895c21f2SBarry Smith if (snes->jacobian) { 6139566063dSJacob Faibussowitsch PetscCall(MatGetNullSpace(snes->jacobian, &nullsp)); 6141baa6e33SBarry Smith if (nullsp) PetscCall(MatSetNullSpace(J, nullsp)); 615895c21f2SBarry Smith } 616895c21f2SBarry Smith 61763a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Setting default matrix-free operator routines (version %" PetscInt_FMT ")\n", version)); 618d3462f78SMatthew Knepley if (hasOperator) { 619aa3661deSLisandro Dalcin /* This version replaces the user provided Jacobian matrix with a 6207addb90fSBarry Smith matrix-free version but still employs the user-provided matrix used for computing the preconditioner. */ 6219566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL)); 622aa3661deSLisandro Dalcin } else { 623aa3661deSLisandro Dalcin /* This version replaces both the user-provided Jacobian and the user- 62401c1178eSBarry Smith provided preconditioner Jacobian with the default matrix-free version. */ 625b552625fSStefano Zampini if (snes->npcside == PC_LEFT && snes->npc) { 6269566063dSJacob Faibussowitsch if (!snes->jacobian) PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL)); 627172a4300SPeter Brune } else { 628789d8953SBarry Smith KSP ksp; 629789d8953SBarry Smith PC pc; 630789d8953SBarry Smith PetscBool match; 631789d8953SBarry Smith 6329566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J, J, MatMFFDComputeJacobian, NULL)); 633aa3661deSLisandro Dalcin /* Force no preconditioner */ 6349566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 6359566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksp, &pc)); 6362698c518SLisandro Dalcin PetscCall(PetscObjectTypeCompareAny((PetscObject)pc, &match, PCSHELL, PCH2OPUS, "")); 637aa3661deSLisandro Dalcin if (!match) { 6389566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Setting default matrix-free preconditioner routines\nThat is no preconditioner is being used\n")); 6399566063dSJacob Faibussowitsch PetscCall(PCSetType(pc, PCNONE)); 640aa3661deSLisandro Dalcin } 641aa3661deSLisandro Dalcin } 642789d8953SBarry Smith } 6439566063dSJacob Faibussowitsch PetscCall(MatDestroy(&J)); 6443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 645aa3661deSLisandro Dalcin } 646aa3661deSLisandro Dalcin 647d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMRestrictHook_SNESVecSol(DM dmfine, Mat Restrict, Vec Rscale, Mat Inject, DM dmcoarse, void *ctx) 648d71ae5a4SJacob Faibussowitsch { 649dfe15315SJed Brown SNES snes = (SNES)ctx; 6500298fd71SBarry Smith Vec Xfine, Xfine_named = NULL, Xcoarse; 651dfe15315SJed Brown 652dfe15315SJed Brown PetscFunctionBegin; 65316ebb321SJed Brown if (PetscLogPrintInfo) { 65416ebb321SJed Brown PetscInt finelevel, coarselevel, fineclevel, coarseclevel; 6559566063dSJacob Faibussowitsch PetscCall(DMGetRefineLevel(dmfine, &finelevel)); 6569566063dSJacob Faibussowitsch PetscCall(DMGetCoarsenLevel(dmfine, &fineclevel)); 6579566063dSJacob Faibussowitsch PetscCall(DMGetRefineLevel(dmcoarse, &coarselevel)); 6589566063dSJacob Faibussowitsch PetscCall(DMGetCoarsenLevel(dmcoarse, &coarseclevel)); 65963a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dmfine, "Restricting SNES solution vector from level %" PetscInt_FMT "-%" PetscInt_FMT " to level %" PetscInt_FMT "-%" PetscInt_FMT "\n", finelevel, fineclevel, coarselevel, coarseclevel)); 66016ebb321SJed Brown } 661dfe15315SJed Brown if (dmfine == snes->dm) Xfine = snes->vec_sol; 662dfe15315SJed Brown else { 6639566063dSJacob Faibussowitsch PetscCall(DMGetNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named)); 664dfe15315SJed Brown Xfine = Xfine_named; 665dfe15315SJed Brown } 6669566063dSJacob Faibussowitsch PetscCall(DMGetNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse)); 667907f5c5aSLawrence Mitchell if (Inject) { 6689566063dSJacob Faibussowitsch PetscCall(MatRestrict(Inject, Xfine, Xcoarse)); 669907f5c5aSLawrence Mitchell } else { 6709566063dSJacob Faibussowitsch PetscCall(MatRestrict(Restrict, Xfine, Xcoarse)); 6719566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(Xcoarse, Xcoarse, Rscale)); 672907f5c5aSLawrence Mitchell } 6739566063dSJacob Faibussowitsch PetscCall(DMRestoreNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse)); 6749566063dSJacob Faibussowitsch if (Xfine_named) PetscCall(DMRestoreNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named)); 6753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 676dfe15315SJed Brown } 677dfe15315SJed Brown 678d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCoarsenHook_SNESVecSol(DM dm, DM dmc, void *ctx) 679d71ae5a4SJacob Faibussowitsch { 68016ebb321SJed Brown PetscFunctionBegin; 6819566063dSJacob Faibussowitsch PetscCall(DMCoarsenHookAdd(dmc, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, ctx)); 6823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 68316ebb321SJed Brown } 68416ebb321SJed Brown 685a6950cb2SJed Brown /* This may be called to rediscretize the operator on levels of linear multigrid. The DM shuffle is so the user can 686a6950cb2SJed Brown * safely call SNESGetDM() in their residual evaluation routine. */ 687d71ae5a4SJacob Faibussowitsch static PetscErrorCode KSPComputeOperators_SNES(KSP ksp, Mat A, Mat B, void *ctx) 688d71ae5a4SJacob Faibussowitsch { 689caa4e7f2SJed Brown SNES snes = (SNES)ctx; 69097d931d1SStefano Zampini DMSNES sdm; 6910298fd71SBarry Smith Vec X, Xnamed = NULL; 692dfe15315SJed Brown DM dmsave; 6934e269d77SPeter Brune void *ctxsave; 6948434afd1SBarry Smith SNESJacobianFn *jac = NULL; 695caa4e7f2SJed Brown 696caa4e7f2SJed Brown PetscFunctionBegin; 697dfe15315SJed Brown dmsave = snes->dm; 6989566063dSJacob Faibussowitsch PetscCall(KSPGetDM(ksp, &snes->dm)); 699dfe15315SJed Brown if (dmsave == snes->dm) X = snes->vec_sol; /* We are on the finest level */ 70097d931d1SStefano Zampini else { 701309d62e6SStefano Zampini PetscBool has; 702309d62e6SStefano Zampini 70397d931d1SStefano Zampini /* We are on a coarser level, this vec was initialized using a DM restrict hook */ 704309d62e6SStefano Zampini PetscCall(DMHasNamedGlobalVector(snes->dm, "SNESVecSol", &has)); 705309d62e6SStefano Zampini PetscCheck(has, PetscObjectComm((PetscObject)snes->dm), PETSC_ERR_PLIB, "Missing SNESVecSol"); 70697d931d1SStefano Zampini PetscCall(DMGetNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed)); 707dfe15315SJed Brown X = Xnamed; 7089566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, NULL, NULL, &jac, &ctxsave)); 7094e269d77SPeter Brune /* If the DM's don't match up, the MatFDColoring context needed for the jacobian won't match up either -- fixit. */ 71048a46eb9SPierre Jolivet if (jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, SNESComputeJacobianDefaultColor, NULL)); 7114e269d77SPeter Brune } 7124e269d77SPeter Brune 7132b93b426SMatthew G. Knepley /* Compute the operators */ 71497d931d1SStefano Zampini PetscCall(DMGetDMSNES(snes->dm, &sdm)); 71597d931d1SStefano Zampini if (Xnamed && sdm->ops->computefunction) { 71697d931d1SStefano Zampini /* The SNES contract with the user is that ComputeFunction is always called before ComputeJacobian. 71797d931d1SStefano Zampini We make sure of this here. Disable affine shift since it is for the finest level */ 71897d931d1SStefano Zampini Vec F, saverhs = snes->vec_rhs; 71997d931d1SStefano Zampini 72097d931d1SStefano Zampini snes->vec_rhs = NULL; 72197d931d1SStefano Zampini PetscCall(DMGetGlobalVector(snes->dm, &F)); 72297d931d1SStefano Zampini PetscCall(SNESComputeFunction(snes, X, F)); 72397d931d1SStefano Zampini PetscCall(DMRestoreGlobalVector(snes->dm, &F)); 72497d931d1SStefano Zampini snes->vec_rhs = saverhs; 72597d931d1SStefano Zampini snes->nfuncs--; /* Do not log coarser level evaluations */ 72697d931d1SStefano Zampini } 72797d931d1SStefano Zampini /* Make sure KSP DM has the Jacobian computation routine */ 72897d931d1SStefano Zampini if (!sdm->ops->computejacobian) PetscCall(DMCopyDMSNES(dmsave, snes->dm)); 729*76c63389SBarry Smith PetscCall(SNESComputeJacobian(snes, X, A, B)); /* cannot handle previous SNESSetJacobianDomainError() calls */ 73097d931d1SStefano Zampini 7312b93b426SMatthew G. Knepley /* Put the previous context back */ 73248a46eb9SPierre Jolivet if (snes->dm != dmsave && jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, jac, ctxsave)); 7334e269d77SPeter Brune 7349566063dSJacob Faibussowitsch if (Xnamed) PetscCall(DMRestoreNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed)); 735dfe15315SJed Brown snes->dm = dmsave; 7363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 737caa4e7f2SJed Brown } 738caa4e7f2SJed Brown 7396cab3a1bSJed Brown /*@ 740dc4c0fb0SBarry Smith SNESSetUpMatrices - ensures that matrices are available for `SNES` Newton-like methods, this is called by `SNESSetUp_XXX()` 7416cab3a1bSJed Brown 7426cab3a1bSJed Brown Collective 7436cab3a1bSJed Brown 7444165533cSJose E. Roman Input Parameter: 74520f4b53cSBarry Smith . snes - `SNES` object to configure 7466cab3a1bSJed Brown 7476cab3a1bSJed Brown Level: developer 7486cab3a1bSJed Brown 749dc4c0fb0SBarry Smith Note: 750dc4c0fb0SBarry Smith If the matrices do not yet exist it attempts to create them based on options previously set for the `SNES` such as `-snes_mf` 751dc4c0fb0SBarry Smith 75273a84a35SBarry Smith Developer Note: 75373a84a35SBarry Smith The functionality of this routine overlaps in a confusing way with the functionality of `SNESSetUpMatrixFree_Private()` which is called by 75473a84a35SBarry Smith `SNESSetUp()` but sometimes `SNESSetUpMatrices()` is called without `SNESSetUp()` being called. A refactorization to simplify the 75573a84a35SBarry Smith logic that handles the matrix-free case is desirable. 75673a84a35SBarry Smith 7571cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUp()` 7586cab3a1bSJed Brown @*/ 759d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUpMatrices(SNES snes) 760d71ae5a4SJacob Faibussowitsch { 7616cab3a1bSJed Brown DM dm; 762942e3340SBarry Smith DMSNES sdm; 7636cab3a1bSJed Brown 7646cab3a1bSJed Brown PetscFunctionBegin; 7659566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 7669566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 76773a84a35SBarry Smith if (!snes->jacobian && snes->mf && !snes->mf_operator && !snes->jacobian_pre) { 7686cab3a1bSJed Brown Mat J; 7696cab3a1bSJed Brown void *functx; 7709566063dSJacob Faibussowitsch PetscCall(MatCreateSNESMF(snes, &J)); 7719566063dSJacob Faibussowitsch PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix)); 7729566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(J)); 7739566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, NULL, &functx)); 7749566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J, J, NULL, NULL)); 7759566063dSJacob Faibussowitsch PetscCall(MatDestroy(&J)); 776caa4e7f2SJed Brown } else if (snes->mf_operator && !snes->jacobian_pre && !snes->jacobian) { 7776cab3a1bSJed Brown Mat J, B; 7789566063dSJacob Faibussowitsch PetscCall(MatCreateSNESMF(snes, &J)); 7799566063dSJacob Faibussowitsch PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix)); 7809566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(J)); 7819566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(snes->dm, &B)); 78206f20277SJed Brown /* sdm->computejacobian was already set to reach here */ 7839566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J, B, NULL, NULL)); 7849566063dSJacob Faibussowitsch PetscCall(MatDestroy(&J)); 7859566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 786caa4e7f2SJed Brown } else if (!snes->jacobian_pre) { 7871ba9b98eSMatthew G. Knepley PetscDS prob; 7886cab3a1bSJed Brown Mat J, B; 7891ba9b98eSMatthew G. Knepley PetscBool hasPrec = PETSC_FALSE; 7901ba9b98eSMatthew G. Knepley 7916cab3a1bSJed Brown J = snes->jacobian; 7929566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob)); 7939566063dSJacob Faibussowitsch if (prob) PetscCall(PetscDSHasJacobianPreconditioner(prob, &hasPrec)); 7949566063dSJacob Faibussowitsch if (J) PetscCall(PetscObjectReference((PetscObject)J)); 7959566063dSJacob Faibussowitsch else if (hasPrec) PetscCall(DMCreateMatrix(snes->dm, &J)); 7969566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(snes->dm, &B)); 7979566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J ? J : B, B, NULL, NULL)); 7989566063dSJacob Faibussowitsch PetscCall(MatDestroy(&J)); 7999566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 8006cab3a1bSJed Brown } 801caa4e7f2SJed Brown { 802caa4e7f2SJed Brown KSP ksp; 8039566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 8049566063dSJacob Faibussowitsch PetscCall(KSPSetComputeOperators(ksp, KSPComputeOperators_SNES, snes)); 8059566063dSJacob Faibussowitsch PetscCall(DMCoarsenHookAdd(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes)); 806caa4e7f2SJed Brown } 8073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8086cab3a1bSJed Brown } 8096cab3a1bSJed Brown 810d6acfc2dSPierre Jolivet PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode PetscMonitorPauseFinal_Internal(PetscInt, void *); 811ce78bad3SBarry Smith 812d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESMonitorPauseFinal_Internal(SNES snes) 813d71ae5a4SJacob Faibussowitsch { 8145e7c47f3SMatthew G. Knepley PetscFunctionBegin; 8153ba16761SJacob Faibussowitsch if (!snes->pauseFinal) PetscFunctionReturn(PETSC_SUCCESS); 816ce78bad3SBarry Smith PetscCall(PetscMonitorPauseFinal_Internal(snes->numbermonitors, snes->monitorcontext)); 8173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8185e7c47f3SMatthew G. Knepley } 8195e7c47f3SMatthew G. Knepley 820fde5950dSBarry Smith /*@C 821fde5950dSBarry Smith SNESMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user 822fde5950dSBarry Smith 823c3339decSBarry Smith Collective 824fde5950dSBarry Smith 825fde5950dSBarry Smith Input Parameters: 826dc4c0fb0SBarry Smith + snes - `SNES` object you wish to monitor 827fde5950dSBarry Smith . name - the monitor type one is seeking 828fde5950dSBarry Smith . help - message indicating what monitoring is done 829fde5950dSBarry Smith . manual - manual page for the monitor 83049abdd8aSBarry Smith . monitor - the monitor function, this must use a `PetscViewerFormat` as its context 831f6dfbefdSBarry Smith - monitorsetup - a function that is called once ONLY if the user selected this monitor that may set additional features of the `SNES` or `PetscViewer` objects 832fde5950dSBarry Smith 833420bcc1bSBarry Smith Calling sequence of `monitor`: 834420bcc1bSBarry Smith + snes - the nonlinear solver context 835420bcc1bSBarry Smith . it - the current iteration 836420bcc1bSBarry Smith . r - the current function norm 837420bcc1bSBarry Smith - vf - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use 838420bcc1bSBarry Smith 839420bcc1bSBarry Smith Calling sequence of `monitorsetup`: 840420bcc1bSBarry Smith + snes - the nonlinear solver context 841420bcc1bSBarry Smith - vf - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use 842420bcc1bSBarry Smith 843f6dfbefdSBarry Smith Options Database Key: 844f6dfbefdSBarry Smith . -name - trigger the use of this monitor in `SNESSetFromOptions()` 845f6dfbefdSBarry Smith 846f6dfbefdSBarry Smith Level: advanced 847fde5950dSBarry Smith 848648c30bcSBarry Smith .seealso: [](ch_snes), `PetscOptionsCreateViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, 849db781477SPatrick Sanan `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()` 850e4094ef1SJacob Faibussowitsch `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, 851db781477SPatrick Sanan `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`, 852c2e3fba1SPatrick Sanan `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`, 853db781477SPatrick Sanan `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`, 854db781477SPatrick Sanan `PetscOptionsFList()`, `PetscOptionsEList()` 855fde5950dSBarry Smith @*/ 856420bcc1bSBarry Smith PetscErrorCode SNESMonitorSetFromOptions(SNES snes, const char name[], const char help[], const char manual[], PetscErrorCode (*monitor)(SNES snes, PetscInt it, PetscReal r, PetscViewerAndFormat *vf), PetscErrorCode (*monitorsetup)(SNES snes, PetscViewerAndFormat *vf)) 857d71ae5a4SJacob Faibussowitsch { 858fde5950dSBarry Smith PetscViewer viewer; 859fde5950dSBarry Smith PetscViewerFormat format; 860fde5950dSBarry Smith PetscBool flg; 861fde5950dSBarry Smith 862fde5950dSBarry Smith PetscFunctionBegin; 863648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, name, &viewer, &format, &flg)); 864fde5950dSBarry Smith if (flg) { 865d43b4f6eSBarry Smith PetscViewerAndFormat *vf; 8669566063dSJacob Faibussowitsch PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf)); 867648c30bcSBarry Smith PetscCall(PetscViewerDestroy(&viewer)); 8681baa6e33SBarry Smith if (monitorsetup) PetscCall((*monitorsetup)(snes, vf)); 86949abdd8aSBarry Smith PetscCall(SNESMonitorSet(snes, (PetscErrorCode (*)(SNES, PetscInt, PetscReal, void *))monitor, vf, (PetscCtxDestroyFn *)PetscViewerAndFormatDestroy)); 870fde5950dSBarry Smith } 8713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 872fde5950dSBarry Smith } 873fde5950dSBarry Smith 874a4598233SStefano Zampini PetscErrorCode SNESEWSetFromOptions_Private(SNESKSPEW *kctx, PetscBool print_api, MPI_Comm comm, const char *prefix) 875d71ae5a4SJacob Faibussowitsch { 876a4598233SStefano Zampini const char *api = print_api ? "SNESKSPSetParametersEW" : NULL; 877a4598233SStefano Zampini 8780f0abf79SStefano Zampini PetscFunctionBegin; 8790f0abf79SStefano Zampini PetscOptionsBegin(comm, prefix, "Eisenstat and Walker type forcing options", "KSP"); 880a4598233SStefano Zampini PetscCall(PetscOptionsInt("-ksp_ew_version", "Version 1, 2 or 3", api, kctx->version, &kctx->version, NULL)); 881a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_rtol0", "0 <= rtol0 < 1", api, kctx->rtol_0, &kctx->rtol_0, NULL)); 882a4598233SStefano Zampini kctx->rtol_max = PetscMax(kctx->rtol_0, kctx->rtol_max); 883a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_rtolmax", "0 <= rtolmax < 1", api, kctx->rtol_max, &kctx->rtol_max, NULL)); 884a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_gamma", "0 <= gamma <= 1", api, kctx->gamma, &kctx->gamma, NULL)); 885a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_alpha", "1 < alpha <= 2", api, kctx->alpha, &kctx->alpha, NULL)); 8860f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_alpha2", "alpha2", NULL, kctx->alpha2, &kctx->alpha2, NULL)); 887a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_threshold", "0 < threshold < 1", api, kctx->threshold, &kctx->threshold, NULL)); 8880f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_p1", "p1", NULL, kctx->v4_p1, &kctx->v4_p1, NULL)); 8890f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_p2", "p2", NULL, kctx->v4_p2, &kctx->v4_p2, NULL)); 8900f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_p3", "p3", NULL, kctx->v4_p3, &kctx->v4_p3, NULL)); 8910f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_m1", "Scaling when rk-1 in [p2,p3)", NULL, kctx->v4_m1, &kctx->v4_m1, NULL)); 8920f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_m2", "Scaling when rk-1 in [p3,+infty)", NULL, kctx->v4_m2, &kctx->v4_m2, NULL)); 8930f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_m3", "Threshold for successive rtol (0.1 in Eq.7)", NULL, kctx->v4_m3, &kctx->v4_m3, NULL)); 8940f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_m4", "Adaptation scaling (0.5 in Eq.7)", NULL, kctx->v4_m4, &kctx->v4_m4, NULL)); 8950f0abf79SStefano Zampini PetscOptionsEnd(); 8963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8970f0abf79SStefano Zampini } 8980f0abf79SStefano Zampini 8999b94acceSBarry Smith /*@ 900f6dfbefdSBarry Smith SNESSetFromOptions - Sets various `SNES` and `KSP` parameters from user options. 9019b94acceSBarry Smith 902c3339decSBarry Smith Collective 903c7afd0dbSLois Curfman McInnes 9049b94acceSBarry Smith Input Parameter: 905f6dfbefdSBarry Smith . snes - the `SNES` context 9069b94acceSBarry Smith 90736851e7fSLois Curfman McInnes Options Database Keys: 908f6dfbefdSBarry Smith + -snes_type <type> - newtonls, newtontr, ngmres, ncg, nrichardson, qn, vi, fas, `SNESType` for complete list 909b39c3a46SLois Curfman McInnes . -snes_rtol <rtol> - relative decrease in tolerance norm from initial 91077e5a1f9SBarry Smith . -snes_atol <abstol> - absolute tolerance of residual norm 91177e5a1f9SBarry Smith . -snes_stol <stol> - convergence tolerance in terms of the norm of the change in the solution between steps 912e4d06f11SPatrick Farrell . -snes_divergence_tolerance <divtol> - if the residual goes above divtol*rnorm0, exit with divergence 913b39c3a46SLois Curfman McInnes . -snes_max_it <max_it> - maximum number of iterations 914b39c3a46SLois Curfman McInnes . -snes_max_funcs <max_funcs> - maximum number of function evaluations 91577e5a1f9SBarry Smith . -snes_force_iteration <force> - force `SNESSolve()` to take at least one iteration 9164839bfe8SBarry Smith . -snes_max_fail <max_fail> - maximum number of line search failures allowed before stopping, default is none 917ddf469c8SBarry Smith . -snes_max_linear_solve_fail - number of linear solver failures before SNESSolve() stops 918a8054027SBarry Smith . -snes_lag_preconditioner <lag> - how often preconditioner is rebuilt (use -1 to never rebuild) 9193d5a8a6aSBarry Smith . -snes_lag_preconditioner_persists <true,false> - retains the -snes_lag_preconditioner information across multiple SNESSolve() 920e35cf81dSBarry Smith . -snes_lag_jacobian <lag> - how often Jacobian is rebuilt (use -1 to never rebuild) 9213d5a8a6aSBarry Smith . -snes_lag_jacobian_persists <true,false> - retains the -snes_lag_jacobian information across multiple SNESSolve() 922ceaaa498SBarry Smith . -snes_convergence_test <default,skip,correct_pressure> - convergence test in nonlinear solver. default `SNESConvergedDefault()`. skip `SNESConvergedSkip()` means continue iterating until max_it or some other criterion is reached, saving expense of convergence test. correct_pressure `SNESConvergedCorrectPressure()` has special handling of a pressure null space. 923fde5950dSBarry Smith . -snes_monitor [ascii][:filename][:viewer format] - prints residual norm at each iteration. if no filename given prints to stdout 924fde5950dSBarry Smith . -snes_monitor_solution [ascii binary draw][:filename][:viewer format] - plots solution at each iteration 925fde5950dSBarry Smith . -snes_monitor_residual [ascii binary draw][:filename][:viewer format] - plots residual (not its norm) at each iteration 926fde5950dSBarry Smith . -snes_monitor_solution_update [ascii binary draw][:filename][:viewer format] - plots update to solution at each iteration 9274619e776SBarry Smith . -snes_monitor_lg_residualnorm - plots residual norm at each iteration 928459f5d12SBarry Smith . -snes_monitor_lg_range - plots residual norm at each iteration 9295e7c47f3SMatthew G. Knepley . -snes_monitor_pause_final - Pauses all monitor drawing after the solver ends 930e24b481bSBarry Smith . -snes_fd - use finite differences to compute Jacobian; very slow, only for testing 931e2e60de9SPeter Brune . -snes_fd_color - use finite differences with coloring to compute Jacobian 932ceaaa498SBarry Smith . -snes_mf_ksp_monitor - if using matrix-free multiply then print h at each `KSP` iteration 933b5badacbSBarry Smith . -snes_converged_reason - print the reason for convergence/divergence after each solve 934ceaaa498SBarry Smith . -npc_snes_type <type> - the `SNES` type to use as a nonlinear preconditioner 935e62ac41dSBarry Smith . -snes_test_jacobian <optional threshold> - compare the user provided Jacobian with one computed via finite differences to check for errors. If a threshold is given, display only those entries whose difference is greater than the threshold. 936e62ac41dSBarry Smith - -snes_test_jacobian_view - display the user provided Jacobian, the finite difference Jacobian and the difference between them to help users detect the location of errors in the user provided Jacobian. 93782738288SBarry Smith 938f6dfbefdSBarry Smith Options Database Keys for Eisenstat-Walker method: 939fa9f3622SBarry Smith + -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence 9404b27c08aSLois Curfman McInnes . -snes_ksp_ew_version ver - version of Eisenstat-Walker method 94136851e7fSLois Curfman McInnes . -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0 94236851e7fSLois Curfman McInnes . -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax 94336851e7fSLois Curfman McInnes . -snes_ksp_ew_gamma <gamma> - Sets gamma 94436851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha <alpha> - Sets alpha 94536851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2 94636851e7fSLois Curfman McInnes - -snes_ksp_ew_threshold <threshold> - Sets threshold 94782738288SBarry Smith 948dc4c0fb0SBarry Smith Level: beginner 949dc4c0fb0SBarry Smith 95011ca99fdSLois Curfman McInnes Notes: 951ec5066bdSBarry Smith To see all options, run your program with the -help option or consult the users manual 952ec5066bdSBarry Smith 953420bcc1bSBarry Smith `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`, 954420bcc1bSBarry Smith and computing explicitly with 955f6dfbefdSBarry Smith finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object. 95683e2fdc7SBarry Smith 957420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESType`, `SNESSetOptionsPrefix()`, `SNESResetFromOptions()`, `SNES`, `SNESCreate()`, `MatCreateSNESMF()`, `MatFDColoring` 9589b94acceSBarry Smith @*/ 959d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFromOptions(SNES snes) 960d71ae5a4SJacob Faibussowitsch { 9618afaa268SBarry Smith PetscBool flg, pcset, persist, set; 96277e5a1f9SBarry Smith PetscInt i, indx, lag, grids, max_its, max_funcs; 96304d7464bSBarry Smith const char *deft = SNESNEWTONLS; 964649ef022SMatthew Knepley const char *convtests[] = {"default", "skip", "correct_pressure"}; 96585385478SLisandro Dalcin SNESKSPEW *kctx = NULL; 9660f0abf79SStefano Zampini char type[256], monfilename[PETSC_MAX_PATH_LEN], ewprefix[256]; 967c40d0f55SPeter Brune PCSide pcside; 968a64e098fSPeter Brune const char *optionsprefix; 96977e5a1f9SBarry Smith PetscReal rtol, abstol, stol; 9709b94acceSBarry Smith 9713a40ed3dSBarry Smith PetscFunctionBegin; 9720700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 9739566063dSJacob Faibussowitsch PetscCall(SNESRegisterAll()); 974d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)snes); 975639ff905SBarry Smith if (((PetscObject)snes)->type_name) deft = ((PetscObject)snes)->type_name; 9769566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-snes_type", "Nonlinear solver method", "SNESSetType", SNESList, deft, type, 256, &flg)); 977d64ed03dSBarry Smith if (flg) { 9789566063dSJacob Faibussowitsch PetscCall(SNESSetType(snes, type)); 9797adad957SLisandro Dalcin } else if (!((PetscObject)snes)->type_name) { 9809566063dSJacob Faibussowitsch PetscCall(SNESSetType(snes, deft)); 981d64ed03dSBarry Smith } 982186905e3SBarry Smith 98377e5a1f9SBarry Smith abstol = snes->abstol; 98477e5a1f9SBarry Smith rtol = snes->rtol; 98577e5a1f9SBarry Smith stol = snes->stol; 98677e5a1f9SBarry Smith max_its = snes->max_its; 98777e5a1f9SBarry Smith max_funcs = snes->max_funcs; 98877e5a1f9SBarry Smith PetscCall(PetscOptionsReal("-snes_rtol", "Stop if decrease in function norm less than", "SNESSetTolerances", snes->rtol, &rtol, NULL)); 98977e5a1f9SBarry Smith PetscCall(PetscOptionsReal("-snes_atol", "Stop if function norm less than", "SNESSetTolerances", snes->abstol, &abstol, NULL)); 99077e5a1f9SBarry Smith PetscCall(PetscOptionsReal("-snes_stol", "Stop if step length less than", "SNESSetTolerances", snes->stol, &stol, NULL)); 99177e5a1f9SBarry Smith PetscCall(PetscOptionsInt("-snes_max_it", "Maximum iterations", "SNESSetTolerances", snes->max_its, &max_its, NULL)); 99277e5a1f9SBarry Smith PetscCall(PetscOptionsInt("-snes_max_funcs", "Maximum function evaluations", "SNESSetTolerances", snes->max_funcs, &max_funcs, NULL)); 99377e5a1f9SBarry Smith PetscCall(SNESSetTolerances(snes, abstol, rtol, stol, max_its, max_funcs)); 99477e5a1f9SBarry Smith 99577e5a1f9SBarry Smith PetscCall(PetscOptionsReal("-snes_divergence_tolerance", "Stop if residual norm increases by this factor", "SNESSetDivergenceTolerance", snes->divtol, &snes->divtol, &flg)); 99677e5a1f9SBarry Smith if (flg) PetscCall(SNESSetDivergenceTolerance(snes, snes->divtol)); 99777e5a1f9SBarry Smith 99877e5a1f9SBarry Smith PetscCall(PetscOptionsInt("-snes_max_fail", "Maximum nonlinear step failures", "SNESSetMaxNonlinearStepFailures", snes->maxFailures, &snes->maxFailures, &flg)); 99977e5a1f9SBarry Smith if (flg) PetscCall(SNESSetMaxNonlinearStepFailures(snes, snes->maxFailures)); 100077e5a1f9SBarry Smith 100177e5a1f9SBarry Smith PetscCall(PetscOptionsInt("-snes_max_linear_solve_fail", "Maximum failures in linear solves allowed", "SNESSetMaxLinearSolveFailures", snes->maxLinearSolveFailures, &snes->maxLinearSolveFailures, &flg)); 100277e5a1f9SBarry Smith if (flg) PetscCall(SNESSetMaxLinearSolveFailures(snes, snes->maxLinearSolveFailures)); 100377e5a1f9SBarry Smith 10049566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_error_if_not_converged", "Generate error if solver does not converge", "SNESSetErrorIfNotConverged", snes->errorifnotconverged, &snes->errorifnotconverged, NULL)); 10059566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_force_iteration", "Force SNESSolve() to take at least one iteration", "SNESSetForceIteration", snes->forceiteration, &snes->forceiteration, NULL)); 10069566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_check_jacobian_domain_error", "Check Jacobian domain error after Jacobian evaluation", "SNESCheckJacobianDomainError", snes->checkjacdomainerror, &snes->checkjacdomainerror, NULL)); 100785385478SLisandro Dalcin 10089566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_lag_preconditioner", "How often to rebuild preconditioner", "SNESSetLagPreconditioner", snes->lagpreconditioner, &lag, &flg)); 1009a8054027SBarry Smith if (flg) { 10105f80ce2aSJacob Faibussowitsch PetscCheck(lag != -1, PetscObjectComm((PetscObject)snes), PETSC_ERR_USER, "Cannot set the lag to -1 from the command line since the preconditioner must be built as least once, perhaps you mean -2"); 10119566063dSJacob Faibussowitsch PetscCall(SNESSetLagPreconditioner(snes, lag)); 1012a8054027SBarry Smith } 10139566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_lag_preconditioner_persists", "Preconditioner lagging through multiple SNES solves", "SNESSetLagPreconditionerPersists", snes->lagjac_persist, &persist, &flg)); 10141baa6e33SBarry Smith if (flg) PetscCall(SNESSetLagPreconditionerPersists(snes, persist)); 10159566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_lag_jacobian", "How often to rebuild Jacobian", "SNESSetLagJacobian", snes->lagjacobian, &lag, &flg)); 1016e35cf81dSBarry Smith if (flg) { 10175f80ce2aSJacob Faibussowitsch PetscCheck(lag != -1, PetscObjectComm((PetscObject)snes), PETSC_ERR_USER, "Cannot set the lag to -1 from the command line since the Jacobian must be built as least once, perhaps you mean -2"); 10189566063dSJacob Faibussowitsch PetscCall(SNESSetLagJacobian(snes, lag)); 1019e35cf81dSBarry Smith } 10209566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_lag_jacobian_persists", "Jacobian lagging through multiple SNES solves", "SNESSetLagJacobianPersists", snes->lagjac_persist, &persist, &flg)); 10211baa6e33SBarry Smith if (flg) PetscCall(SNESSetLagJacobianPersists(snes, persist)); 102237ec4e1aSPeter Brune 10239566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_grid_sequence", "Use grid sequencing to generate initial guess", "SNESSetGridSequence", snes->gridsequence, &grids, &flg)); 10241baa6e33SBarry Smith if (flg) PetscCall(SNESSetGridSequence(snes, grids)); 1025a8054027SBarry Smith 1026400f6f02SBarry Smith PetscCall(PetscOptionsEList("-snes_convergence_test", "Convergence test", "SNESSetConvergenceTest", convtests, PETSC_STATIC_ARRAY_LENGTH(convtests), "default", &indx, &flg)); 102785385478SLisandro Dalcin if (flg) { 102885385478SLisandro Dalcin switch (indx) { 1029d71ae5a4SJacob Faibussowitsch case 0: 1030d71ae5a4SJacob Faibussowitsch PetscCall(SNESSetConvergenceTest(snes, SNESConvergedDefault, NULL, NULL)); 1031d71ae5a4SJacob Faibussowitsch break; 1032d71ae5a4SJacob Faibussowitsch case 1: 1033d71ae5a4SJacob Faibussowitsch PetscCall(SNESSetConvergenceTest(snes, SNESConvergedSkip, NULL, NULL)); 1034d71ae5a4SJacob Faibussowitsch break; 1035d71ae5a4SJacob Faibussowitsch case 2: 1036d71ae5a4SJacob Faibussowitsch PetscCall(SNESSetConvergenceTest(snes, SNESConvergedCorrectPressure, NULL, NULL)); 1037d71ae5a4SJacob Faibussowitsch break; 103885385478SLisandro Dalcin } 103985385478SLisandro Dalcin } 104085385478SLisandro Dalcin 10419566063dSJacob Faibussowitsch PetscCall(PetscOptionsEList("-snes_norm_schedule", "SNES Norm schedule", "SNESSetNormSchedule", SNESNormSchedules, 5, "function", &indx, &flg)); 10429566063dSJacob Faibussowitsch if (flg) PetscCall(SNESSetNormSchedule(snes, (SNESNormSchedule)indx)); 1043fdacfa88SPeter Brune 10449566063dSJacob Faibussowitsch PetscCall(PetscOptionsEList("-snes_function_type", "SNES Norm schedule", "SNESSetFunctionType", SNESFunctionTypes, 2, "unpreconditioned", &indx, &flg)); 10459566063dSJacob Faibussowitsch if (flg) PetscCall(SNESSetFunctionType(snes, (SNESFunctionType)indx)); 1046186905e3SBarry Smith 104785385478SLisandro Dalcin kctx = (SNESKSPEW *)snes->kspconvctx; 104885385478SLisandro Dalcin 10499566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_ksp_ew", "Use Eisentat-Walker linear system convergence test", "SNESKSPSetUseEW", snes->ksp_ewconv, &snes->ksp_ewconv, NULL)); 1050186905e3SBarry Smith 10510f0abf79SStefano Zampini PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 10520f0abf79SStefano Zampini PetscCall(PetscSNPrintf(ewprefix, sizeof(ewprefix), "%s%s", optionsprefix ? optionsprefix : "", "snes_")); 1053a4598233SStefano Zampini PetscCall(SNESEWSetFromOptions_Private(kctx, PETSC_TRUE, PetscObjectComm((PetscObject)snes), ewprefix)); 1054186905e3SBarry Smith 105590d69ab7SBarry Smith flg = PETSC_FALSE; 10569566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_monitor_cancel", "Remove all monitors", "SNESMonitorCancel", flg, &flg, &set)); 10579566063dSJacob Faibussowitsch if (set && flg) PetscCall(SNESMonitorCancel(snes)); 1058eabae89aSBarry Smith 10599566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor", "Monitor norm of function", "SNESMonitorDefault", SNESMonitorDefault, SNESMonitorDefaultSetUp)); 10609566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_short", "Monitor norm of function with fewer digits", "SNESMonitorDefaultShort", SNESMonitorDefaultShort, NULL)); 10619566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_range", "Monitor range of elements of function", "SNESMonitorRange", SNESMonitorRange, NULL)); 1062eabae89aSBarry Smith 10639566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_ratio", "Monitor ratios of the norm of function for consecutive steps", "SNESMonitorRatio", SNESMonitorRatio, SNESMonitorRatioSetUp)); 10649566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_field", "Monitor norm of function (split into fields)", "SNESMonitorDefaultField", SNESMonitorDefaultField, NULL)); 10659566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution", "View solution at each iteration", "SNESMonitorSolution", SNESMonitorSolution, NULL)); 10669566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution_update", "View correction at each iteration", "SNESMonitorSolutionUpdate", SNESMonitorSolutionUpdate, NULL)); 10679566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_residual", "View residual at each iteration", "SNESMonitorResidual", SNESMonitorResidual, NULL)); 10689566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_jacupdate_spectrum", "Print the change in the spectrum of the Jacobian", "SNESMonitorJacUpdateSpectrum", SNESMonitorJacUpdateSpectrum, NULL)); 10699566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_fields", "Monitor norm of function per field", "SNESMonitorSet", SNESMonitorFields, NULL)); 10709566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_monitor_pause_final", "Pauses all draw monitors at the final iterate", "SNESMonitorPauseFinal_Internal", PETSC_FALSE, &snes->pauseFinal, NULL)); 10712db13446SMatthew G. Knepley 10729566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-snes_monitor_python", "Use Python function", "SNESMonitorSet", NULL, monfilename, sizeof(monfilename), &flg)); 10739566063dSJacob Faibussowitsch if (flg) PetscCall(PetscPythonMonitorSet((PetscObject)snes, monfilename)); 10745180491cSLisandro Dalcin 107590d69ab7SBarry Smith flg = PETSC_FALSE; 10769566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_monitor_lg_range", "Plot function range at each iteration", "SNESMonitorLGRange", flg, &flg, NULL)); 1077459f5d12SBarry Smith if (flg) { 1078459f5d12SBarry Smith PetscViewer ctx; 1079e24b481bSBarry Smith 10809566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &ctx)); 108149abdd8aSBarry Smith PetscCall(SNESMonitorSet(snes, SNESMonitorLGRange, ctx, (PetscCtxDestroyFn *)PetscViewerDestroy)); 1082459f5d12SBarry Smith } 10832e7541e6SPeter Brune 1084648c30bcSBarry Smith PetscCall(PetscViewerDestroy(&snes->convergedreasonviewer)); 1085648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_converged_reason", &snes->convergedreasonviewer, &snes->convergedreasonformat, NULL)); 108690d69ab7SBarry Smith flg = PETSC_FALSE; 10879566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_converged_reason_view_cancel", "Remove all converged reason viewers", "SNESConvergedReasonViewCancel", flg, &flg, &set)); 10889566063dSJacob Faibussowitsch if (set && flg) PetscCall(SNESConvergedReasonViewCancel(snes)); 1089c4421ceaSFande Kong 1090c4421ceaSFande Kong flg = PETSC_FALSE; 10919566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_fd", "Use finite differences (slow) to compute Jacobian", "SNESComputeJacobianDefault", flg, &flg, NULL)); 10924b27c08aSLois Curfman McInnes if (flg) { 10936cab3a1bSJed Brown void *functx; 1094b1f624c7SBarry Smith DM dm; 10959566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 1096800f99ffSJeremy L Thompson PetscCall(DMSNESUnsetJacobianContext_Internal(dm)); 10979566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, NULL, &functx)); 10989566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefault, functx)); 10999566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Setting default finite difference Jacobian matrix\n")); 11009b94acceSBarry Smith } 1101639f9d9dSBarry Smith 110244848bc4SPeter Brune flg = PETSC_FALSE; 11039566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_fd_function", "Use finite differences (slow) to compute function from user objective", "SNESObjectiveComputeFunctionDefaultFD", flg, &flg, NULL)); 11041baa6e33SBarry Smith if (flg) PetscCall(SNESSetFunction(snes, NULL, SNESObjectiveComputeFunctionDefaultFD, NULL)); 110597584545SPeter Brune 110697584545SPeter Brune flg = PETSC_FALSE; 11079566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_fd_color", "Use finite differences with coloring to compute Jacobian", "SNESComputeJacobianDefaultColor", flg, &flg, NULL)); 110844848bc4SPeter Brune if (flg) { 1109c52e227fSPeter Brune DM dm; 11109566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 1111800f99ffSJeremy L Thompson PetscCall(DMSNESUnsetJacobianContext_Internal(dm)); 11129566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefaultColor, NULL)); 11139566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Setting default finite difference coloring Jacobian matrix\n")); 111444848bc4SPeter Brune } 111544848bc4SPeter Brune 1116aa3661deSLisandro Dalcin flg = PETSC_FALSE; 11177addb90fSBarry Smith PetscCall(PetscOptionsBool("-snes_mf_operator", "Use a Matrix-Free Jacobian with user-provided matrix for computing the preconditioner", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf_operator, &flg)); 1118d8f46077SPeter Brune if (flg && snes->mf_operator) { 1119a8248277SBarry Smith snes->mf_operator = PETSC_TRUE; 1120d8f46077SPeter Brune snes->mf = PETSC_TRUE; 1121a8248277SBarry Smith } 1122aa3661deSLisandro Dalcin flg = PETSC_FALSE; 11237addb90fSBarry Smith PetscCall(PetscOptionsBool("-snes_mf", "Use a Matrix-Free Jacobian with no matrix for computing the preconditioner", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf, &flg)); 1124d8f46077SPeter Brune if (!flg && snes->mf_operator) snes->mf = PETSC_TRUE; 11259566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_mf_version", "Matrix-Free routines version 1 or 2", "None", snes->mf_version, &snes->mf_version, NULL)); 1126d28543b3SPeter Brune 11271dfd7622SMatthew Knepley PetscCall(PetscOptionsName("-snes_test_function", "Compare hand-coded and finite difference functions", "None", &snes->testFunc)); 11281dfd7622SMatthew Knepley PetscCall(PetscOptionsName("-snes_test_jacobian", "Compare hand-coded and finite difference Jacobians", "None", &snes->testJac)); 11291dfd7622SMatthew Knepley 1130c40d0f55SPeter Brune flg = PETSC_FALSE; 11319566063dSJacob Faibussowitsch PetscCall(SNESGetNPCSide(snes, &pcside)); 11329566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-snes_npc_side", "SNES nonlinear preconditioner side", "SNESSetNPCSide", PCSides, (PetscEnum)pcside, (PetscEnum *)&pcside, &flg)); 11339566063dSJacob Faibussowitsch if (flg) PetscCall(SNESSetNPCSide(snes, pcside)); 1134c40d0f55SPeter Brune 1135e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS) 11368a70d858SHong Zhang /* 11378a70d858SHong Zhang Publish convergence information using SAWs 11388a70d858SHong Zhang */ 11398a70d858SHong Zhang flg = PETSC_FALSE; 11409566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_monitor_saws", "Publish SNES progress using SAWs", "SNESMonitorSet", flg, &flg, NULL)); 11418a70d858SHong Zhang if (flg) { 11428a70d858SHong Zhang void *ctx; 11439566063dSJacob Faibussowitsch PetscCall(SNESMonitorSAWsCreate(snes, &ctx)); 11449566063dSJacob Faibussowitsch PetscCall(SNESMonitorSet(snes, SNESMonitorSAWs, ctx, SNESMonitorSAWsDestroy)); 11458a70d858SHong Zhang } 11468a70d858SHong Zhang #endif 11478a70d858SHong Zhang #if defined(PETSC_HAVE_SAWS) 1148b90c6cbeSBarry Smith { 1149b90c6cbeSBarry Smith PetscBool set; 1150b90c6cbeSBarry Smith flg = PETSC_FALSE; 11519566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_saws_block", "Block for SAWs at end of SNESSolve", "PetscObjectSAWsBlock", ((PetscObject)snes)->amspublishblock, &flg, &set)); 11521baa6e33SBarry Smith if (set) PetscCall(PetscObjectSAWsSetBlock((PetscObject)snes, flg)); 1153b90c6cbeSBarry Smith } 1154b90c6cbeSBarry Smith #endif 1155b90c6cbeSBarry Smith 115648a46eb9SPierre Jolivet for (i = 0; i < numberofsetfromoptions; i++) PetscCall((*othersetfromoptions[i])(snes)); 115776b2cf59SMatthew Knepley 1158dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, setfromoptions, PetscOptionsObject); 11595d973c19SBarry Smith 11605d973c19SBarry Smith /* process any options handlers added with PetscObjectAddOptionsHandler() */ 1161dbbe0bcdSBarry Smith PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)snes, PetscOptionsObject)); 1162d0609cedSBarry Smith PetscOptionsEnd(); 11634bbc92c1SBarry Smith 1164d8d34be6SBarry Smith if (snes->linesearch) { 11659566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 11669566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetFromOptions(snes->linesearch)); 1167d8d34be6SBarry Smith } 11689e764e56SPeter Brune 11696aa5e7e9SBarry Smith if (snes->usesksp) { 11709566063dSJacob Faibussowitsch if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 11719566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(snes->ksp, snes->jacobian, snes->jacobian_pre)); 11729566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(snes->ksp)); 11736aa5e7e9SBarry Smith } 11746991f827SBarry Smith 1175b5badacbSBarry Smith /* if user has set the SNES NPC type via options database, create it. */ 11769566063dSJacob Faibussowitsch PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 11779566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)snes)->options, optionsprefix, "-npc_snes_type", &pcset)); 117848a46eb9SPierre Jolivet if (pcset && (!snes->npc)) PetscCall(SNESGetNPC(snes, &snes->npc)); 11791baa6e33SBarry Smith if (snes->npc) PetscCall(SNESSetFromOptions(snes->npc)); 1180b3cd9a81SMatthew G. Knepley snes->setfromoptionscalled++; 11813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1182b3cd9a81SMatthew G. Knepley } 1183b3cd9a81SMatthew G. Knepley 1184b3cd9a81SMatthew G. Knepley /*@ 1185420bcc1bSBarry Smith SNESResetFromOptions - Sets various `SNES` and `KSP` parameters from user options ONLY if the `SNESSetFromOptions()` was previously called 1186b3cd9a81SMatthew G. Knepley 1187c3339decSBarry Smith Collective 1188b3cd9a81SMatthew G. Knepley 1189b3cd9a81SMatthew G. Knepley Input Parameter: 1190f6dfbefdSBarry Smith . snes - the `SNES` context 1191b3cd9a81SMatthew G. Knepley 1192420bcc1bSBarry Smith Level: advanced 1193b3cd9a81SMatthew G. Knepley 11941cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESSetOptionsPrefix()` 1195b3cd9a81SMatthew G. Knepley @*/ 1196d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESResetFromOptions(SNES snes) 1197d71ae5a4SJacob Faibussowitsch { 1198b3cd9a81SMatthew G. Knepley PetscFunctionBegin; 11999566063dSJacob Faibussowitsch if (snes->setfromoptionscalled) PetscCall(SNESSetFromOptions(snes)); 12003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12019b94acceSBarry Smith } 12029b94acceSBarry Smith 1203bb9467b5SJed Brown /*@C 1204d25893d9SBarry Smith SNESSetComputeApplicationContext - Sets an optional function to compute a user-defined context for 1205d25893d9SBarry Smith the nonlinear solvers. 1206d25893d9SBarry Smith 1207dc4c0fb0SBarry Smith Logically Collective; No Fortran Support 1208d25893d9SBarry Smith 1209d25893d9SBarry Smith Input Parameters: 1210f6dfbefdSBarry Smith + snes - the `SNES` context 1211d25893d9SBarry Smith . compute - function to compute the context 121249abdd8aSBarry Smith - destroy - function to destroy the context, see `PetscCtxDestroyFn` for the calling sequence 1213d25893d9SBarry Smith 1214420bcc1bSBarry Smith Calling sequence of `compute`: 1215420bcc1bSBarry Smith + snes - the `SNES` context 1216420bcc1bSBarry Smith - ctx - context to be computed 1217420bcc1bSBarry Smith 1218d25893d9SBarry Smith Level: intermediate 1219d25893d9SBarry Smith 1220f6dfbefdSBarry Smith Note: 1221f6dfbefdSBarry Smith This routine is useful if you are performing grid sequencing or using `SNESFAS` and need the appropriate context generated for each level. 1222f6dfbefdSBarry Smith 1223f6dfbefdSBarry Smith Use `SNESSetApplicationContext()` to see the context immediately 1224f6dfbefdSBarry Smith 122549abdd8aSBarry Smith .seealso: [](ch_snes), `SNESGetApplicationContext()`, `SNESSetApplicationContext()`, `PetscCtxDestroyFn` 1226d25893d9SBarry Smith @*/ 122749abdd8aSBarry Smith PetscErrorCode SNESSetComputeApplicationContext(SNES snes, PetscErrorCode (*compute)(SNES snes, void **ctx), PetscCtxDestroyFn *destroy) 1228d71ae5a4SJacob Faibussowitsch { 1229d25893d9SBarry Smith PetscFunctionBegin; 1230d25893d9SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1231d25893d9SBarry Smith snes->ops->usercompute = compute; 123249abdd8aSBarry Smith snes->ops->ctxdestroy = destroy; 12333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1234d25893d9SBarry Smith } 1235a847f771SSatish Balay 1236b07ff414SBarry Smith /*@ 1237f6dfbefdSBarry Smith SNESSetApplicationContext - Sets the optional user-defined context for the nonlinear solvers. 12389b94acceSBarry Smith 1239c3339decSBarry Smith Logically Collective 1240fee21e36SBarry Smith 1241c7afd0dbSLois Curfman McInnes Input Parameters: 1242f6dfbefdSBarry Smith + snes - the `SNES` context 1243ce78bad3SBarry Smith - ctx - the user context 1244c7afd0dbSLois Curfman McInnes 124536851e7fSLois Curfman McInnes Level: intermediate 124636851e7fSLois Curfman McInnes 1247f6dfbefdSBarry Smith Notes: 1248ce78bad3SBarry Smith Users can provide a context when constructing the `SNES` options and then access it inside their function, Jacobian computation, or other evaluation function 1249f6dfbefdSBarry Smith with `SNESGetApplicationContext()` 1250f6dfbefdSBarry Smith 1251f6dfbefdSBarry Smith To provide a function that computes the context for you use `SNESSetComputeApplicationContext()` 1252f6dfbefdSBarry Smith 1253420bcc1bSBarry Smith Fortran Note: 1254ce78bad3SBarry Smith This only works when `ctx` is a Fortran derived type (it cannot be a `PetscObject`), we recommend writing a Fortran interface definition for this 1255ce78bad3SBarry Smith function that tells the Fortran compiler the derived data type that is passed in as the `ctx` argument. See `SNESGetApplicationContext()` for 1256ce78bad3SBarry Smith an example. 1257daf670e6SBarry Smith 12581cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetComputeApplicationContext()`, `SNESGetApplicationContext()` 12599b94acceSBarry Smith @*/ 126049abdd8aSBarry Smith PetscErrorCode SNESSetApplicationContext(SNES snes, void *ctx) 1261d71ae5a4SJacob Faibussowitsch { 1262b07ff414SBarry Smith KSP ksp; 12631b2093e4SBarry Smith 12643a40ed3dSBarry Smith PetscFunctionBegin; 12650700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 12669566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 126749abdd8aSBarry Smith PetscCall(KSPSetApplicationContext(ksp, ctx)); 126849abdd8aSBarry Smith snes->ctx = ctx; 12693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12709b94acceSBarry Smith } 127174679c65SBarry Smith 1272b07ff414SBarry Smith /*@ 12739b94acceSBarry Smith SNESGetApplicationContext - Gets the user-defined context for the 1274420bcc1bSBarry Smith nonlinear solvers set with `SNESGetApplicationContext()` or `SNESSetComputeApplicationContext()` 12759b94acceSBarry Smith 1276c7afd0dbSLois Curfman McInnes Not Collective 1277c7afd0dbSLois Curfman McInnes 12789b94acceSBarry Smith Input Parameter: 1279f6dfbefdSBarry Smith . snes - `SNES` context 12809b94acceSBarry Smith 12819b94acceSBarry Smith Output Parameter: 128249abdd8aSBarry Smith . ctx - user context 12839b94acceSBarry Smith 128436851e7fSLois Curfman McInnes Level: intermediate 128536851e7fSLois Curfman McInnes 1286ce78bad3SBarry Smith Fortran Notes: 1287ce78bad3SBarry Smith This only works when the context is a Fortran derived type (it cannot be a `PetscObject`) and you **must** write a Fortran interface definition for this 1288ce78bad3SBarry Smith function that tells the Fortran compiler the derived data type that is returned as the `ctx` argument. For example, 1289ce78bad3SBarry Smith .vb 1290ce78bad3SBarry Smith Interface SNESGetApplicationContext 1291ce78bad3SBarry Smith Subroutine SNESGetApplicationContext(snes,ctx,ierr) 1292ce78bad3SBarry Smith #include <petsc/finclude/petscsnes.h> 1293ce78bad3SBarry Smith use petscsnes 1294ce78bad3SBarry Smith SNES snes 1295ce78bad3SBarry Smith type(tUsertype), pointer :: ctx 1296ce78bad3SBarry Smith PetscErrorCode ierr 1297ce78bad3SBarry Smith End Subroutine 1298ce78bad3SBarry Smith End Interface SNESGetApplicationContext 1299ce78bad3SBarry Smith .ve 1300ce78bad3SBarry Smith 1301bfe80ac4SPierre Jolivet The prototype for `ctx` must be 1302ce78bad3SBarry Smith .vb 1303ce78bad3SBarry Smith type(tUsertype), pointer :: ctx 1304ce78bad3SBarry Smith .ve 1305dc4c0fb0SBarry Smith 1306420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESSetApplicationContext()`, `SNESSetComputeApplicationContext()` 13079b94acceSBarry Smith @*/ 1308ce78bad3SBarry Smith PetscErrorCode SNESGetApplicationContext(SNES snes, PeCtx ctx) 1309d71ae5a4SJacob Faibussowitsch { 13103a40ed3dSBarry Smith PetscFunctionBegin; 13110700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 131249abdd8aSBarry Smith *(void **)ctx = snes->ctx; 13133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13149b94acceSBarry Smith } 131574679c65SBarry Smith 13169b94acceSBarry Smith /*@ 1317420bcc1bSBarry Smith SNESSetUseMatrixFree - indicates that `SNES` should use matrix-free finite difference matrix-vector products to apply the Jacobian. 13183565c898SBarry Smith 1319dc4c0fb0SBarry Smith Logically Collective 13203565c898SBarry Smith 13213565c898SBarry Smith Input Parameters: 1322f6dfbefdSBarry Smith + snes - `SNES` context 1323f6dfbefdSBarry Smith . mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used 1324f6dfbefdSBarry Smith - mf - use matrix-free for both the Amat and Pmat used by `SNESSetJacobian()`, both the Amat and Pmat set in `SNESSetJacobian()` will be ignored. With 1325420bcc1bSBarry Smith this option no matrix-element based preconditioners can be used in the linear solve since the matrix won't be explicitly available 13263565c898SBarry Smith 1327f6dfbefdSBarry Smith Options Database Keys: 132801c1178eSBarry Smith + -snes_mf_operator - use matrix-free only for the mat operator 1329f6dfbefdSBarry Smith . -snes_mf - use matrix-free for both the mat and pmat operator 1330ec5066bdSBarry Smith . -snes_fd_color - compute the Jacobian via coloring and finite differences. 1331ec5066bdSBarry Smith - -snes_fd - compute the Jacobian via finite differences (slow) 13323565c898SBarry Smith 13333565c898SBarry Smith Level: intermediate 13343565c898SBarry Smith 1335f6dfbefdSBarry Smith Note: 1336420bcc1bSBarry Smith `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`, 1337420bcc1bSBarry Smith and computing explicitly with 1338f6dfbefdSBarry Smith finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object. 1339ec5066bdSBarry Smith 1340420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetUseMatrixFree()`, `MatCreateSNESMF()`, `SNESComputeJacobianDefaultColor()`, `MatFDColoring` 13413565c898SBarry Smith @*/ 1342d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUseMatrixFree(SNES snes, PetscBool mf_operator, PetscBool mf) 1343d71ae5a4SJacob Faibussowitsch { 13443565c898SBarry Smith PetscFunctionBegin; 13453565c898SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 134688b4c220SStefano Zampini PetscValidLogicalCollectiveBool(snes, mf_operator, 2); 134788b4c220SStefano Zampini PetscValidLogicalCollectiveBool(snes, mf, 3); 13484ddffce6SLisandro Dalcin snes->mf = mf_operator ? PETSC_TRUE : mf; 13493565c898SBarry Smith snes->mf_operator = mf_operator; 13503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13513565c898SBarry Smith } 13523565c898SBarry Smith 13533565c898SBarry Smith /*@ 1354dc4c0fb0SBarry Smith SNESGetUseMatrixFree - indicates if the `SNES` uses matrix-free finite difference matrix vector products to apply the Jacobian. 13553565c898SBarry Smith 1356420bcc1bSBarry Smith Not Collective, but the resulting flags will be the same on all MPI processes 13573565c898SBarry Smith 13583565c898SBarry Smith Input Parameter: 1359f6dfbefdSBarry Smith . snes - `SNES` context 13603565c898SBarry Smith 13613565c898SBarry Smith Output Parameters: 1362f6dfbefdSBarry Smith + mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used 1363f6dfbefdSBarry Smith - mf - use matrix-free for both the Amat and Pmat used by `SNESSetJacobian()`, both the Amat and Pmat set in `SNESSetJacobian()` will be ignored 13643565c898SBarry Smith 13653565c898SBarry Smith Level: intermediate 13663565c898SBarry Smith 13671cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUseMatrixFree()`, `MatCreateSNESMF()` 13683565c898SBarry Smith @*/ 1369d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUseMatrixFree(SNES snes, PetscBool *mf_operator, PetscBool *mf) 1370d71ae5a4SJacob Faibussowitsch { 13713565c898SBarry Smith PetscFunctionBegin; 13723565c898SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 13733565c898SBarry Smith if (mf) *mf = snes->mf; 13743565c898SBarry Smith if (mf_operator) *mf_operator = snes->mf_operator; 13753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13763565c898SBarry Smith } 13773565c898SBarry Smith 13783565c898SBarry Smith /*@ 1379420bcc1bSBarry Smith SNESGetIterationNumber - Gets the number of nonlinear iterations completed in the current or most recent `SNESSolve()` 13809b94acceSBarry Smith 1381c7afd0dbSLois Curfman McInnes Not Collective 1382c7afd0dbSLois Curfman McInnes 13839b94acceSBarry Smith Input Parameter: 1384f6dfbefdSBarry Smith . snes - `SNES` context 13859b94acceSBarry Smith 13869b94acceSBarry Smith Output Parameter: 13879b94acceSBarry Smith . iter - iteration number 13889b94acceSBarry Smith 1389dc4c0fb0SBarry Smith Level: intermediate 1390dc4c0fb0SBarry Smith 1391c8228a4eSBarry Smith Notes: 1392c8228a4eSBarry Smith For example, during the computation of iteration 2 this would return 1. 1393c8228a4eSBarry Smith 1394c8228a4eSBarry Smith This is useful for using lagged Jacobians (where one does not recompute the 1395f6dfbefdSBarry Smith Jacobian at each `SNES` iteration). For example, the code 139608405cd6SLois Curfman McInnes .vb 139708405cd6SLois Curfman McInnes ierr = SNESGetIterationNumber(snes,&it); 139808405cd6SLois Curfman McInnes if (!(it % 2)) { 139908405cd6SLois Curfman McInnes [compute Jacobian here] 140008405cd6SLois Curfman McInnes } 140108405cd6SLois Curfman McInnes .ve 1402f6dfbefdSBarry Smith can be used in your function that computes the Jacobian to cause the Jacobian to be 1403f6dfbefdSBarry Smith recomputed every second `SNES` iteration. See also `SNESSetLagJacobian()` 1404c8228a4eSBarry Smith 1405f6dfbefdSBarry Smith After the `SNES` solve is complete this will return the number of nonlinear iterations used. 1406c04deec6SBarry Smith 1407420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetLagJacobian()`, `SNESGetLinearSolveIterations()`, `SNESSetMonitor()` 14089b94acceSBarry Smith @*/ 1409d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetIterationNumber(SNES snes, PetscInt *iter) 1410d71ae5a4SJacob Faibussowitsch { 14113a40ed3dSBarry Smith PetscFunctionBegin; 14120700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 14134f572ea9SToby Isaac PetscAssertPointer(iter, 2); 14149b94acceSBarry Smith *iter = snes->iter; 14153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14169b94acceSBarry Smith } 141774679c65SBarry Smith 1418360c497dSPeter Brune /*@ 1419360c497dSPeter Brune SNESSetIterationNumber - Sets the current iteration number. 1420360c497dSPeter Brune 1421360c497dSPeter Brune Not Collective 1422360c497dSPeter Brune 1423d8d19677SJose E. Roman Input Parameters: 1424f6dfbefdSBarry Smith + snes - `SNES` context 1425a2b725a8SWilliam Gropp - iter - iteration number 1426360c497dSPeter Brune 1427360c497dSPeter Brune Level: developer 1428360c497dSPeter Brune 1429420bcc1bSBarry Smith Note: 1430420bcc1bSBarry Smith This should only be called inside a `SNES` nonlinear solver. 1431420bcc1bSBarry Smith 14321cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetLinearSolveIterations()` 1433360c497dSPeter Brune @*/ 1434d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetIterationNumber(SNES snes, PetscInt iter) 1435d71ae5a4SJacob Faibussowitsch { 1436360c497dSPeter Brune PetscFunctionBegin; 1437360c497dSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 14389566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes)); 1439360c497dSPeter Brune snes->iter = iter; 14409566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes)); 14413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1442360c497dSPeter Brune } 1443360c497dSPeter Brune 14449b94acceSBarry Smith /*@ 1445b850b91aSLisandro Dalcin SNESGetNonlinearStepFailures - Gets the number of unsuccessful steps 1446*76c63389SBarry Smith taken by the nonlinear solver in the current or most recent `SNESSolve()` . 14479b94acceSBarry Smith 1448c7afd0dbSLois Curfman McInnes Not Collective 1449c7afd0dbSLois Curfman McInnes 14509b94acceSBarry Smith Input Parameter: 1451f6dfbefdSBarry Smith . snes - `SNES` context 14529b94acceSBarry Smith 14539b94acceSBarry Smith Output Parameter: 14549b94acceSBarry Smith . nfails - number of unsuccessful steps attempted 14559b94acceSBarry Smith 1456dc4c0fb0SBarry Smith Level: intermediate 1457dc4c0fb0SBarry Smith 1458*76c63389SBarry Smith Notes: 1459*76c63389SBarry Smith A failed step is a step that was generated and taken but did not satisfy the requested step criteria. For example, 1460*76c63389SBarry Smith the `SNESLineSearchApply()` could not generate a sufficient decrease in the function norm (in fact it may have produced an increase). 1461*76c63389SBarry Smith 1462*76c63389SBarry Smith Taken steps that produce a infinity or NaN in the function evaluation or generate a `SNESSetFunctionDomainError()` 1463*76c63389SBarry Smith will always immediately terminate the `SNESSolve()` regardless of the value of `maxFails`. 1464*76c63389SBarry Smith 1465*76c63389SBarry Smith `SNESSetMaxNonlinearStepFailures()` determines how many unsuccessful steps are allowed before the `SNESSolve()` terminates 1466*76c63389SBarry Smith 1467f6dfbefdSBarry Smith This counter is reset to zero for each successive call to `SNESSolve()`. 1468c96a6f78SLois Curfman McInnes 14691cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, 1470db781477SPatrick Sanan `SNESSetMaxNonlinearStepFailures()`, `SNESGetMaxNonlinearStepFailures()` 14719b94acceSBarry Smith @*/ 1472d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNonlinearStepFailures(SNES snes, PetscInt *nfails) 1473d71ae5a4SJacob Faibussowitsch { 14743a40ed3dSBarry Smith PetscFunctionBegin; 14750700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 14764f572ea9SToby Isaac PetscAssertPointer(nfails, 2); 147750ffb88aSMatthew Knepley *nfails = snes->numFailures; 14783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 147950ffb88aSMatthew Knepley } 148050ffb88aSMatthew Knepley 148150ffb88aSMatthew Knepley /*@ 1482b850b91aSLisandro Dalcin SNESSetMaxNonlinearStepFailures - Sets the maximum number of unsuccessful steps 1483420bcc1bSBarry Smith attempted by the nonlinear solver before it gives up and returns unconverged or generates an error 148450ffb88aSMatthew Knepley 148550ffb88aSMatthew Knepley Not Collective 148650ffb88aSMatthew Knepley 148750ffb88aSMatthew Knepley Input Parameters: 1488f6dfbefdSBarry Smith + snes - `SNES` context 148977e5a1f9SBarry Smith - maxFails - maximum of unsuccessful steps allowed, use `PETSC_UNLIMITED` to have no limit on the number of failures 149050ffb88aSMatthew Knepley 1491420bcc1bSBarry Smith Options Database Key: 1492420bcc1bSBarry Smith . -snes_max_fail <n> - maximum number of unsuccessful steps allowed 1493420bcc1bSBarry Smith 149450ffb88aSMatthew Knepley Level: intermediate 149550ffb88aSMatthew Knepley 1496*76c63389SBarry Smith Note: 1497*76c63389SBarry Smith A failed step is a step that was generated and taken but did not satisfy the requested criteria. For example, 1498*76c63389SBarry Smith the `SNESLineSearchApply()` could not generate a sufficient decrease in the function norm (in fact it may have produced an increase). 1499*76c63389SBarry Smith 1500*76c63389SBarry Smith Taken steps that produce a infinity or NaN in the function evaluation or generate a `SNESSetFunctionDomainError()` 1501*76c63389SBarry Smith will always immediately terminate the `SNESSolve()` regardless of the value of `maxFails`. 1502*76c63389SBarry Smith 1503420bcc1bSBarry Smith Developer Note: 1504420bcc1bSBarry Smith The options database key is wrong for this function name 1505420bcc1bSBarry Smith 1506*76c63389SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, 1507*76c63389SBarry Smith `SNESGetLinearSolveFailures()`, `SNESGetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`, `SNESCheckLineSearchFailure()` 150850ffb88aSMatthew Knepley @*/ 1509d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxNonlinearStepFailures(SNES snes, PetscInt maxFails) 1510d71ae5a4SJacob Faibussowitsch { 151150ffb88aSMatthew Knepley PetscFunctionBegin; 15120700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 151377e5a1f9SBarry Smith 151477e5a1f9SBarry Smith if (maxFails == PETSC_UNLIMITED) { 15151690c2aeSBarry Smith snes->maxFailures = PETSC_INT_MAX; 151677e5a1f9SBarry Smith } else { 151777e5a1f9SBarry Smith PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures"); 151850ffb88aSMatthew Knepley snes->maxFailures = maxFails; 151977e5a1f9SBarry Smith } 15203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 152150ffb88aSMatthew Knepley } 152250ffb88aSMatthew Knepley 152350ffb88aSMatthew Knepley /*@ 1524b850b91aSLisandro Dalcin SNESGetMaxNonlinearStepFailures - Gets the maximum number of unsuccessful steps 1525420bcc1bSBarry Smith attempted by the nonlinear solver before it gives up and returns unconverged or generates an error 152650ffb88aSMatthew Knepley 152750ffb88aSMatthew Knepley Not Collective 152850ffb88aSMatthew Knepley 152950ffb88aSMatthew Knepley Input Parameter: 153020f4b53cSBarry Smith . snes - `SNES` context 153150ffb88aSMatthew Knepley 153250ffb88aSMatthew Knepley Output Parameter: 153350ffb88aSMatthew Knepley . maxFails - maximum of unsuccessful steps 153450ffb88aSMatthew Knepley 153550ffb88aSMatthew Knepley Level: intermediate 153650ffb88aSMatthew Knepley 15371cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, 1538db781477SPatrick Sanan `SNESSetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()` 153950ffb88aSMatthew Knepley @*/ 1540d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxNonlinearStepFailures(SNES snes, PetscInt *maxFails) 1541d71ae5a4SJacob Faibussowitsch { 154250ffb88aSMatthew Knepley PetscFunctionBegin; 15430700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 15444f572ea9SToby Isaac PetscAssertPointer(maxFails, 2); 154550ffb88aSMatthew Knepley *maxFails = snes->maxFailures; 15463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15479b94acceSBarry Smith } 1548a847f771SSatish Balay 15492541af92SBarry Smith /*@ 15502541af92SBarry Smith SNESGetNumberFunctionEvals - Gets the number of user provided function evaluations 1551420bcc1bSBarry Smith done by the `SNES` object in the current or most recent `SNESSolve()` 15522541af92SBarry Smith 15532541af92SBarry Smith Not Collective 15542541af92SBarry Smith 15552541af92SBarry Smith Input Parameter: 1556f6dfbefdSBarry Smith . snes - `SNES` context 15572541af92SBarry Smith 15582541af92SBarry Smith Output Parameter: 15592541af92SBarry Smith . nfuncs - number of evaluations 15602541af92SBarry Smith 15612541af92SBarry Smith Level: intermediate 15622541af92SBarry Smith 1563f6dfbefdSBarry Smith Note: 1564f6dfbefdSBarry Smith Reset every time `SNESSolve()` is called unless `SNESSetCountersReset()` is used. 1565971e163fSPeter Brune 15661cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, `SNESSetCountersReset()` 15672541af92SBarry Smith @*/ 1568d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNumberFunctionEvals(SNES snes, PetscInt *nfuncs) 1569d71ae5a4SJacob Faibussowitsch { 15702541af92SBarry Smith PetscFunctionBegin; 15710700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 15724f572ea9SToby Isaac PetscAssertPointer(nfuncs, 2); 15732541af92SBarry Smith *nfuncs = snes->nfuncs; 15743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15752541af92SBarry Smith } 15762541af92SBarry Smith 15773d4c4710SBarry Smith /*@ 15783d4c4710SBarry Smith SNESGetLinearSolveFailures - Gets the number of failed (non-converged) 1579420bcc1bSBarry Smith linear solvers in the current or most recent `SNESSolve()` 15803d4c4710SBarry Smith 15813d4c4710SBarry Smith Not Collective 15823d4c4710SBarry Smith 15833d4c4710SBarry Smith Input Parameter: 1584f6dfbefdSBarry Smith . snes - `SNES` context 15853d4c4710SBarry Smith 15863d4c4710SBarry Smith Output Parameter: 15873d4c4710SBarry Smith . nfails - number of failed solves 15883d4c4710SBarry Smith 1589f6dfbefdSBarry Smith Options Database Key: 15909d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated 15919d85da0cSMatthew G. Knepley 1592f6dfbefdSBarry Smith Level: intermediate 1593f6dfbefdSBarry Smith 1594f6dfbefdSBarry Smith Note: 1595f6dfbefdSBarry Smith This counter is reset to zero for each successive call to `SNESSolve()`. 15963d4c4710SBarry Smith 15971cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()` 15983d4c4710SBarry Smith @*/ 1599d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveFailures(SNES snes, PetscInt *nfails) 1600d71ae5a4SJacob Faibussowitsch { 16013d4c4710SBarry Smith PetscFunctionBegin; 16020700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 16034f572ea9SToby Isaac PetscAssertPointer(nfails, 2); 16043d4c4710SBarry Smith *nfails = snes->numLinearSolveFailures; 16053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16063d4c4710SBarry Smith } 16073d4c4710SBarry Smith 16083d4c4710SBarry Smith /*@ 16093d4c4710SBarry Smith SNESSetMaxLinearSolveFailures - the number of failed linear solve attempts 1610f6dfbefdSBarry Smith allowed before `SNES` returns with a diverged reason of `SNES_DIVERGED_LINEAR_SOLVE` 16113d4c4710SBarry Smith 1612c3339decSBarry Smith Logically Collective 16133d4c4710SBarry Smith 16143d4c4710SBarry Smith Input Parameters: 1615f6dfbefdSBarry Smith + snes - `SNES` context 161677e5a1f9SBarry Smith - maxFails - maximum allowed linear solve failures, use `PETSC_UNLIMITED` to have no limit on the number of failures 16173d4c4710SBarry Smith 1618f6dfbefdSBarry Smith Options Database Key: 16199d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated 16209d85da0cSMatthew G. Knepley 1621dc4c0fb0SBarry Smith Level: intermediate 1622dc4c0fb0SBarry Smith 1623f6dfbefdSBarry Smith Note: 1624f6dfbefdSBarry Smith By default this is 0; that is `SNES` returns on the first failed linear solve 16253d4c4710SBarry Smith 1626420bcc1bSBarry Smith Developer Note: 1627420bcc1bSBarry Smith The options database key is wrong for this function name 1628420bcc1bSBarry Smith 16291cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()` 16303d4c4710SBarry Smith @*/ 1631d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxLinearSolveFailures(SNES snes, PetscInt maxFails) 1632d71ae5a4SJacob Faibussowitsch { 16333d4c4710SBarry Smith PetscFunctionBegin; 16340700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1635c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, maxFails, 2); 163677e5a1f9SBarry Smith 163777e5a1f9SBarry Smith if (maxFails == PETSC_UNLIMITED) { 16381690c2aeSBarry Smith snes->maxLinearSolveFailures = PETSC_INT_MAX; 163977e5a1f9SBarry Smith } else { 164077e5a1f9SBarry Smith PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures"); 16413d4c4710SBarry Smith snes->maxLinearSolveFailures = maxFails; 164277e5a1f9SBarry Smith } 16433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16443d4c4710SBarry Smith } 16453d4c4710SBarry Smith 16463d4c4710SBarry Smith /*@ 16473d4c4710SBarry Smith SNESGetMaxLinearSolveFailures - gets the maximum number of linear solve failures that 1648f6dfbefdSBarry Smith are allowed before `SNES` returns as unsuccessful 16493d4c4710SBarry Smith 16503d4c4710SBarry Smith Not Collective 16513d4c4710SBarry Smith 16523d4c4710SBarry Smith Input Parameter: 1653f6dfbefdSBarry Smith . snes - `SNES` context 16543d4c4710SBarry Smith 16553d4c4710SBarry Smith Output Parameter: 16563d4c4710SBarry Smith . maxFails - maximum of unsuccessful solves allowed 16573d4c4710SBarry Smith 16583d4c4710SBarry Smith Level: intermediate 16593d4c4710SBarry Smith 1660f6dfbefdSBarry Smith Note: 1661f6dfbefdSBarry Smith By default this is 1; that is `SNES` returns on the first failed linear solve 16623d4c4710SBarry Smith 16631cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, 16643d4c4710SBarry Smith @*/ 1665d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxLinearSolveFailures(SNES snes, PetscInt *maxFails) 1666d71ae5a4SJacob Faibussowitsch { 16673d4c4710SBarry Smith PetscFunctionBegin; 16680700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 16694f572ea9SToby Isaac PetscAssertPointer(maxFails, 2); 16703d4c4710SBarry Smith *maxFails = snes->maxLinearSolveFailures; 16713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16723d4c4710SBarry Smith } 16733d4c4710SBarry Smith 1674c96a6f78SLois Curfman McInnes /*@ 1675b850b91aSLisandro Dalcin SNESGetLinearSolveIterations - Gets the total number of linear iterations 1676420bcc1bSBarry Smith used by the nonlinear solver in the most recent `SNESSolve()` 1677c96a6f78SLois Curfman McInnes 1678c7afd0dbSLois Curfman McInnes Not Collective 1679c7afd0dbSLois Curfman McInnes 1680c96a6f78SLois Curfman McInnes Input Parameter: 1681f6dfbefdSBarry Smith . snes - `SNES` context 1682c96a6f78SLois Curfman McInnes 1683c96a6f78SLois Curfman McInnes Output Parameter: 1684c96a6f78SLois Curfman McInnes . lits - number of linear iterations 1685c96a6f78SLois Curfman McInnes 1686dc4c0fb0SBarry Smith Level: intermediate 1687dc4c0fb0SBarry Smith 1688c96a6f78SLois Curfman McInnes Notes: 1689f6dfbefdSBarry Smith This counter is reset to zero for each successive call to `SNESSolve()` unless `SNESSetCountersReset()` is used. 1690c96a6f78SLois Curfman McInnes 1691f6dfbefdSBarry Smith If the linear solver fails inside the `SNESSolve()` the iterations for that call to the linear solver are not included. If you wish to count them 1692f6dfbefdSBarry Smith then call `KSPGetIterationNumber()` after the failed solve. 1693010be392SBarry Smith 16941cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetIterationNumber()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESSetCountersReset()` 1695c96a6f78SLois Curfman McInnes @*/ 1696d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveIterations(SNES snes, PetscInt *lits) 1697d71ae5a4SJacob Faibussowitsch { 16983a40ed3dSBarry Smith PetscFunctionBegin; 16990700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 17004f572ea9SToby Isaac PetscAssertPointer(lits, 2); 1701c96a6f78SLois Curfman McInnes *lits = snes->linear_its; 17023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1703c96a6f78SLois Curfman McInnes } 1704c96a6f78SLois Curfman McInnes 1705971e163fSPeter Brune /*@ 1706971e163fSPeter Brune SNESSetCountersReset - Sets whether or not the counters for linear iterations and function evaluations 1707f6dfbefdSBarry Smith are reset every time `SNESSolve()` is called. 1708971e163fSPeter Brune 1709c3339decSBarry Smith Logically Collective 1710971e163fSPeter Brune 1711d8d19677SJose E. Roman Input Parameters: 1712f6dfbefdSBarry Smith + snes - `SNES` context 1713f6dfbefdSBarry Smith - reset - whether to reset the counters or not, defaults to `PETSC_TRUE` 1714971e163fSPeter Brune 1715971e163fSPeter Brune Level: developer 1716971e163fSPeter Brune 17171cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()` 1718971e163fSPeter Brune @*/ 1719d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCountersReset(SNES snes, PetscBool reset) 1720d71ae5a4SJacob Faibussowitsch { 1721971e163fSPeter Brune PetscFunctionBegin; 1722971e163fSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1723971e163fSPeter Brune PetscValidLogicalCollectiveBool(snes, reset, 2); 1724971e163fSPeter Brune snes->counters_reset = reset; 17253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1726971e163fSPeter Brune } 1727971e163fSPeter Brune 17282999313aSBarry Smith /*@ 172912b1dd1aSStefano Zampini SNESResetCounters - Reset counters for linear iterations and function evaluations. 173012b1dd1aSStefano Zampini 173112b1dd1aSStefano Zampini Logically Collective 173212b1dd1aSStefano Zampini 173312b1dd1aSStefano Zampini Input Parameters: 173412b1dd1aSStefano Zampini . snes - `SNES` context 173512b1dd1aSStefano Zampini 173612b1dd1aSStefano Zampini Level: developer 173712b1dd1aSStefano Zampini 173812b1dd1aSStefano Zampini Note: 173912b1dd1aSStefano Zampini It honors the flag set with `SNESSetCountersReset()` 174012b1dd1aSStefano Zampini 174112b1dd1aSStefano Zampini .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()` 174212b1dd1aSStefano Zampini @*/ 174312b1dd1aSStefano Zampini PetscErrorCode SNESResetCounters(SNES snes) 174412b1dd1aSStefano Zampini { 174512b1dd1aSStefano Zampini PetscFunctionBegin; 174612b1dd1aSStefano Zampini PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 174712b1dd1aSStefano Zampini if (snes->counters_reset) { 174812b1dd1aSStefano Zampini snes->nfuncs = 0; 174912b1dd1aSStefano Zampini snes->linear_its = 0; 175012b1dd1aSStefano Zampini snes->numFailures = 0; 175112b1dd1aSStefano Zampini } 175212b1dd1aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 175312b1dd1aSStefano Zampini } 175412b1dd1aSStefano Zampini 175512b1dd1aSStefano Zampini /*@ 1756f6dfbefdSBarry Smith SNESSetKSP - Sets a `KSP` context for the `SNES` object to use 17572999313aSBarry Smith 1758420bcc1bSBarry Smith Not Collective, but the `SNES` and `KSP` objects must live on the same `MPI_Comm` 17592999313aSBarry Smith 17602999313aSBarry Smith Input Parameters: 1761f6dfbefdSBarry Smith + snes - the `SNES` context 1762f6dfbefdSBarry Smith - ksp - the `KSP` context 17632999313aSBarry Smith 1764dc4c0fb0SBarry Smith Level: developer 1765dc4c0fb0SBarry Smith 17662999313aSBarry Smith Notes: 1767f6dfbefdSBarry Smith The `SNES` object already has its `KSP` object, you can obtain with `SNESGetKSP()` 17682999313aSBarry Smith so this routine is rarely needed. 17692999313aSBarry Smith 1770f6dfbefdSBarry Smith The `KSP` object that is already in the `SNES` object has its reference count 1771420bcc1bSBarry Smith decreased by one when this is called. 17722999313aSBarry Smith 177342747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `KSP`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()` 17742999313aSBarry Smith @*/ 1775d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetKSP(SNES snes, KSP ksp) 1776d71ae5a4SJacob Faibussowitsch { 17772999313aSBarry Smith PetscFunctionBegin; 17780700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 17790700a824SBarry Smith PetscValidHeaderSpecific(ksp, KSP_CLASSID, 2); 17802999313aSBarry Smith PetscCheckSameComm(snes, 1, ksp, 2); 17819566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)ksp)); 17829566063dSJacob Faibussowitsch if (snes->ksp) PetscCall(PetscObjectDereference((PetscObject)snes->ksp)); 17832999313aSBarry Smith snes->ksp = ksp; 17843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17852999313aSBarry Smith } 17862999313aSBarry Smith 178752baeb72SSatish Balay /*@ 178877e5a1f9SBarry Smith SNESParametersInitialize - Sets all the parameters in `snes` to their default value (when `SNESCreate()` was called) if they 178977e5a1f9SBarry Smith currently contain default values 179077e5a1f9SBarry Smith 179177e5a1f9SBarry Smith Collective 179277e5a1f9SBarry Smith 179377e5a1f9SBarry Smith Input Parameter: 179477e5a1f9SBarry Smith . snes - the `SNES` object 179577e5a1f9SBarry Smith 179677e5a1f9SBarry Smith Level: developer 179777e5a1f9SBarry Smith 179877e5a1f9SBarry Smith Developer Note: 179977e5a1f9SBarry Smith This is called by all the `SNESCreate_XXX()` routines. 180077e5a1f9SBarry Smith 180177e5a1f9SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`, 180277e5a1f9SBarry Smith `PetscObjectParameterSetDefault()` 180377e5a1f9SBarry Smith @*/ 180477e5a1f9SBarry Smith PetscErrorCode SNESParametersInitialize(SNES snes) 180577e5a1f9SBarry Smith { 180677e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, max_its, 50); 180777e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, max_funcs, 10000); 180877e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, rtol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8); 180977e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, abstol, PetscDefined(USE_REAL_SINGLE) ? 1.e-25 : 1.e-50); 181077e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, stol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8); 181177e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, divtol, 1.e4); 181277e5a1f9SBarry Smith return PETSC_SUCCESS; 181377e5a1f9SBarry Smith } 181477e5a1f9SBarry Smith 181577e5a1f9SBarry Smith /*@ 1816dc4c0fb0SBarry Smith SNESCreate - Creates a nonlinear solver context used to manage a set of nonlinear solves 18179b94acceSBarry Smith 1818d083f849SBarry Smith Collective 1819c7afd0dbSLois Curfman McInnes 1820f6dfbefdSBarry Smith Input Parameter: 1821906ed7ccSBarry Smith . comm - MPI communicator 18229b94acceSBarry Smith 18239b94acceSBarry Smith Output Parameter: 182420f4b53cSBarry Smith . outsnes - the new `SNES` context 18259b94acceSBarry Smith 1826c7afd0dbSLois Curfman McInnes Options Database Keys: 18277addb90fSBarry Smith + -snes_mf - Activates default matrix-free Jacobian-vector products, and no matrix to construct a preconditioner 18287addb90fSBarry Smith . -snes_mf_operator - Activates default matrix-free Jacobian-vector products, and a user-provided matrix as set by `SNESSetJacobian()` 1829dc4c0fb0SBarry Smith . -snes_fd_coloring - uses a relative fast computation of the Jacobian using finite differences and a graph coloring 1830c7afd0dbSLois Curfman McInnes - -snes_fd - Uses (slow!) finite differences to compute Jacobian 1831c1f60f51SBarry Smith 183236851e7fSLois Curfman McInnes Level: beginner 183336851e7fSLois Curfman McInnes 183495452b02SPatrick Sanan Developer Notes: 1835f6dfbefdSBarry Smith `SNES` always creates a `KSP` object even though many `SNES` methods do not use it. This is 1836efd4aadfSBarry Smith unfortunate and should be fixed at some point. The flag snes->usesksp indicates if the 1837f6dfbefdSBarry Smith particular method does use `KSP` and regulates if the information about the `KSP` is printed 1838f6dfbefdSBarry Smith in `SNESView()`. 1839efd4aadfSBarry Smith 1840f6dfbefdSBarry Smith `TSSetFromOptions()` does call `SNESSetFromOptions()` which can lead to users being confused 1841f6dfbefdSBarry Smith by help messages about meaningless `SNES` options. 1842f6dfbefdSBarry Smith 18437addb90fSBarry Smith `SNES` always creates the `snes->kspconvctx` even though it is used by only one type. This should be fixed. 1844efd4aadfSBarry Smith 1845e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()` 18469b94acceSBarry Smith @*/ 1847d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESCreate(MPI_Comm comm, SNES *outsnes) 1848d71ae5a4SJacob Faibussowitsch { 18499b94acceSBarry Smith SNES snes; 1850fa9f3622SBarry Smith SNESKSPEW *kctx; 185137fcc0dbSBarry Smith 18523a40ed3dSBarry Smith PetscFunctionBegin; 18534f572ea9SToby Isaac PetscAssertPointer(outsnes, 2); 18549566063dSJacob Faibussowitsch PetscCall(SNESInitializePackage()); 18558ba1e511SMatthew Knepley 18569566063dSJacob Faibussowitsch PetscCall(PetscHeaderCreate(snes, SNES_CLASSID, "SNES", "Nonlinear solver", "SNES", comm, SNESDestroy, SNESView)); 18578d359177SBarry Smith snes->ops->converged = SNESConvergedDefault; 18582c155ee1SBarry Smith snes->usesksp = PETSC_TRUE; 18599b94acceSBarry Smith snes->norm = 0.0; 1860c1e67a49SFande Kong snes->xnorm = 0.0; 1861c1e67a49SFande Kong snes->ynorm = 0.0; 1862365a6726SPeter Brune snes->normschedule = SNES_NORM_ALWAYS; 18636c67d002SPeter Brune snes->functype = SNES_FUNCTION_DEFAULT; 1864b4874afaSBarry Smith snes->ttol = 0.0; 186577e5a1f9SBarry Smith 1866e37c518bSBarry Smith snes->rnorm0 = 0; 18679b94acceSBarry Smith snes->nfuncs = 0; 186850ffb88aSMatthew Knepley snes->numFailures = 0; 186950ffb88aSMatthew Knepley snes->maxFailures = 1; 18707a00f4a9SLois Curfman McInnes snes->linear_its = 0; 1871e35cf81dSBarry Smith snes->lagjacobian = 1; 187237ec4e1aSPeter Brune snes->jac_iter = 0; 187337ec4e1aSPeter Brune snes->lagjac_persist = PETSC_FALSE; 1874a8054027SBarry Smith snes->lagpreconditioner = 1; 187537ec4e1aSPeter Brune snes->pre_iter = 0; 187637ec4e1aSPeter Brune snes->lagpre_persist = PETSC_FALSE; 1877639f9d9dSBarry Smith snes->numbermonitors = 0; 1878c4421ceaSFande Kong snes->numberreasonviews = 0; 18799e5d0892SLisandro Dalcin snes->data = NULL; 18804dc4c822SBarry Smith snes->setupcalled = PETSC_FALSE; 1881186905e3SBarry Smith snes->ksp_ewconv = PETSC_FALSE; 18826f24a144SLois Curfman McInnes snes->nwork = 0; 18839e5d0892SLisandro Dalcin snes->work = NULL; 188458c9b817SLisandro Dalcin snes->nvwork = 0; 18859e5d0892SLisandro Dalcin snes->vwork = NULL; 1886758f92a0SBarry Smith snes->conv_hist_len = 0; 1887758f92a0SBarry Smith snes->conv_hist_max = 0; 18880298fd71SBarry Smith snes->conv_hist = NULL; 18890298fd71SBarry Smith snes->conv_hist_its = NULL; 1890758f92a0SBarry Smith snes->conv_hist_reset = PETSC_TRUE; 1891971e163fSPeter Brune snes->counters_reset = PETSC_TRUE; 1892e4ed7901SPeter Brune snes->vec_func_init_set = PETSC_FALSE; 1893184914b5SBarry Smith snes->reason = SNES_CONVERGED_ITERATING; 1894efd4aadfSBarry Smith snes->npcside = PC_RIGHT; 1895b3cd9a81SMatthew G. Knepley snes->setfromoptionscalled = 0; 1896c40d0f55SPeter Brune 1897d8f46077SPeter Brune snes->mf = PETSC_FALSE; 1898d8f46077SPeter Brune snes->mf_operator = PETSC_FALSE; 1899d8f46077SPeter Brune snes->mf_version = 1; 1900d8f46077SPeter Brune 19013d4c4710SBarry Smith snes->numLinearSolveFailures = 0; 19023d4c4710SBarry Smith snes->maxLinearSolveFailures = 1; 19033d4c4710SBarry Smith 1904349187a7SBarry Smith snes->vizerotolerance = 1.e-8; 190576bd3646SJed Brown snes->checkjacdomainerror = PetscDefined(USE_DEBUG) ? PETSC_TRUE : PETSC_FALSE; 1906349187a7SBarry Smith 19074fc747eaSLawrence Mitchell /* Set this to true if the implementation of SNESSolve_XXX does compute the residual at the final solution. */ 19084fc747eaSLawrence Mitchell snes->alwayscomputesfinalresidual = PETSC_FALSE; 19094fc747eaSLawrence Mitchell 19109b94acceSBarry Smith /* Create context to compute Eisenstat-Walker relative tolerance for KSP */ 19114dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&kctx)); 1912f5af7f23SKarl Rupp 1913835f2295SStefano Zampini snes->kspconvctx = kctx; 19149b94acceSBarry Smith kctx->version = 2; 19150f0abf79SStefano Zampini kctx->rtol_0 = 0.3; /* Eisenstat and Walker suggest rtol_0=.5, but 19169b94acceSBarry Smith this was too large for some test cases */ 191775567043SBarry Smith kctx->rtol_last = 0.0; 19180f0abf79SStefano Zampini kctx->rtol_max = 0.9; 19199b94acceSBarry Smith kctx->gamma = 1.0; 19200f0abf79SStefano Zampini kctx->alpha = 0.5 * (1.0 + PetscSqrtReal(5.0)); 192171f87433Sdalcinl kctx->alpha2 = kctx->alpha; 19220f0abf79SStefano Zampini kctx->threshold = 0.1; 192375567043SBarry Smith kctx->lresid_last = 0.0; 192475567043SBarry Smith kctx->norm_last = 0.0; 19259b94acceSBarry Smith 19260f0abf79SStefano Zampini kctx->rk_last = 0.0; 19270f0abf79SStefano Zampini kctx->rk_last_2 = 0.0; 19280f0abf79SStefano Zampini kctx->rtol_last_2 = 0.0; 19290f0abf79SStefano Zampini kctx->v4_p1 = 0.1; 19300f0abf79SStefano Zampini kctx->v4_p2 = 0.4; 19310f0abf79SStefano Zampini kctx->v4_p3 = 0.7; 19320f0abf79SStefano Zampini kctx->v4_m1 = 0.8; 19330f0abf79SStefano Zampini kctx->v4_m2 = 0.5; 19340f0abf79SStefano Zampini kctx->v4_m3 = 0.1; 19350f0abf79SStefano Zampini kctx->v4_m4 = 0.5; 19360f0abf79SStefano Zampini 1937b50c806fSBarry Smith PetscCall(SNESParametersInitialize(snes)); 19389b94acceSBarry Smith *outsnes = snes; 19393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19409b94acceSBarry Smith } 19419b94acceSBarry Smith 19429b94acceSBarry Smith /*@C 19439b94acceSBarry Smith SNESSetFunction - Sets the function evaluation routine and function 1944f6dfbefdSBarry Smith vector for use by the `SNES` routines in solving systems of nonlinear 19459b94acceSBarry Smith equations. 19469b94acceSBarry Smith 1947c3339decSBarry Smith Logically Collective 1948fee21e36SBarry Smith 1949c7afd0dbSLois Curfman McInnes Input Parameters: 1950f6dfbefdSBarry Smith + snes - the `SNES` context 1951dc4c0fb0SBarry Smith . r - vector to store function values, may be `NULL` 19528434afd1SBarry Smith . f - function evaluation routine; for calling sequence see `SNESFunctionFn` 1953c7afd0dbSLois Curfman McInnes - ctx - [optional] user-defined context for private data for the 1954dc4c0fb0SBarry Smith function evaluation routine (may be `NULL`) 19559b94acceSBarry Smith 195636851e7fSLois Curfman McInnes Level: beginner 195736851e7fSLois Curfman McInnes 19588434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetPicard()`, `SNESFunctionFn` 19599b94acceSBarry Smith @*/ 19608434afd1SBarry Smith PetscErrorCode SNESSetFunction(SNES snes, Vec r, SNESFunctionFn *f, void *ctx) 1961d71ae5a4SJacob Faibussowitsch { 19626cab3a1bSJed Brown DM dm; 19636cab3a1bSJed Brown 19643a40ed3dSBarry Smith PetscFunctionBegin; 19650700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1966d2a683ecSLisandro Dalcin if (r) { 1967d2a683ecSLisandro Dalcin PetscValidHeaderSpecific(r, VEC_CLASSID, 2); 1968d2a683ecSLisandro Dalcin PetscCheckSameComm(snes, 1, r, 2); 19699566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)r)); 19709566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_func)); 197185385478SLisandro Dalcin snes->vec_func = r; 1972d2a683ecSLisandro Dalcin } 19739566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 19749566063dSJacob Faibussowitsch PetscCall(DMSNESSetFunction(dm, f, ctx)); 197548a46eb9SPierre Jolivet if (f == SNESPicardComputeFunction) PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx)); 19763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19779b94acceSBarry Smith } 19789b94acceSBarry Smith 1979e4ed7901SPeter Brune /*@C 19800b4db180SJacob Faibussowitsch SNESSetInitialFunction - Set an already computed function evaluation at the initial guess to be reused by `SNESSolve()`. 1981e4ed7901SPeter Brune 1982c3339decSBarry Smith Logically Collective 1983e4ed7901SPeter Brune 1984e4ed7901SPeter Brune Input Parameters: 1985f6dfbefdSBarry Smith + snes - the `SNES` context 1986e4ed7901SPeter Brune - f - vector to store function value 1987e4ed7901SPeter Brune 1988dc4c0fb0SBarry Smith Level: developer 1989dc4c0fb0SBarry Smith 1990e4ed7901SPeter Brune Notes: 1991e4ed7901SPeter Brune This should not be modified during the solution procedure. 1992e4ed7901SPeter Brune 1993f6dfbefdSBarry Smith This is used extensively in the `SNESFAS` hierarchy and in nonlinear preconditioning. 1994e4ed7901SPeter Brune 19951cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetInitialFunctionNorm()` 1996e4ed7901SPeter Brune @*/ 1997d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetInitialFunction(SNES snes, Vec f) 1998d71ae5a4SJacob Faibussowitsch { 1999e4ed7901SPeter Brune Vec vec_func; 2000e4ed7901SPeter Brune 2001e4ed7901SPeter Brune PetscFunctionBegin; 2002e4ed7901SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2003e4ed7901SPeter Brune PetscValidHeaderSpecific(f, VEC_CLASSID, 2); 2004e4ed7901SPeter Brune PetscCheckSameComm(snes, 1, f, 2); 2005efd4aadfSBarry Smith if (snes->npcside == PC_LEFT && snes->functype == SNES_FUNCTION_PRECONDITIONED) { 2006902f982fSPeter Brune snes->vec_func_init_set = PETSC_FALSE; 20073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2008902f982fSPeter Brune } 20099566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &vec_func, NULL, NULL)); 20109566063dSJacob Faibussowitsch PetscCall(VecCopy(f, vec_func)); 2011f5af7f23SKarl Rupp 2012217b9c2eSPeter Brune snes->vec_func_init_set = PETSC_TRUE; 20133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2014e4ed7901SPeter Brune } 2015e4ed7901SPeter Brune 2016534ebe21SPeter Brune /*@ 2017f6dfbefdSBarry Smith SNESSetNormSchedule - Sets the `SNESNormSchedule` used in convergence and monitoring 2018f6dfbefdSBarry Smith of the `SNES` method, when norms are computed in the solving process 2019534ebe21SPeter Brune 2020c3339decSBarry Smith Logically Collective 2021534ebe21SPeter Brune 2022534ebe21SPeter Brune Input Parameters: 2023f6dfbefdSBarry Smith + snes - the `SNES` context 2024365a6726SPeter Brune - normschedule - the frequency of norm computation 2025534ebe21SPeter Brune 2026517f1916SMatthew G. Knepley Options Database Key: 202767b8a455SSatish Balay . -snes_norm_schedule <none, always, initialonly, finalonly, initialfinalonly> - set the schedule 2028517f1916SMatthew G. Knepley 2029dc4c0fb0SBarry Smith Level: advanced 2030dc4c0fb0SBarry Smith 2031534ebe21SPeter Brune Notes: 2032f6dfbefdSBarry Smith Only certain `SNES` methods support certain `SNESNormSchedules`. Most require evaluation 2033534ebe21SPeter Brune of the nonlinear function and the taking of its norm at every iteration to 2034534ebe21SPeter Brune even ensure convergence at all. However, methods such as custom Gauss-Seidel methods 2035f6dfbefdSBarry Smith `SNESNGS` and the like do not require the norm of the function to be computed, and therefore 2036534ebe21SPeter Brune may either be monitored for convergence or not. As these are often used as nonlinear 2037534ebe21SPeter Brune preconditioners, monitoring the norm of their error is not a useful enterprise within 2038534ebe21SPeter Brune their solution. 2039534ebe21SPeter Brune 2040e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNESNormSchedule`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()` 2041534ebe21SPeter Brune @*/ 2042d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNormSchedule(SNES snes, SNESNormSchedule normschedule) 2043d71ae5a4SJacob Faibussowitsch { 2044534ebe21SPeter Brune PetscFunctionBegin; 2045534ebe21SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2046365a6726SPeter Brune snes->normschedule = normschedule; 20473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2048534ebe21SPeter Brune } 2049534ebe21SPeter Brune 2050534ebe21SPeter Brune /*@ 2051f6dfbefdSBarry Smith SNESGetNormSchedule - Gets the `SNESNormSchedule` used in convergence and monitoring 2052f6dfbefdSBarry Smith of the `SNES` method. 2053534ebe21SPeter Brune 2054c3339decSBarry Smith Logically Collective 2055534ebe21SPeter Brune 2056534ebe21SPeter Brune Input Parameters: 2057f6dfbefdSBarry Smith + snes - the `SNES` context 2058365a6726SPeter Brune - normschedule - the type of the norm used 2059534ebe21SPeter Brune 2060534ebe21SPeter Brune Level: advanced 2061534ebe21SPeter Brune 20621cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 2063534ebe21SPeter Brune @*/ 2064d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNormSchedule(SNES snes, SNESNormSchedule *normschedule) 2065d71ae5a4SJacob Faibussowitsch { 2066534ebe21SPeter Brune PetscFunctionBegin; 2067534ebe21SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2068365a6726SPeter Brune *normschedule = snes->normschedule; 20693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2070534ebe21SPeter Brune } 2071534ebe21SPeter Brune 2072c5ce4427SMatthew G. Knepley /*@ 2073c5ce4427SMatthew G. Knepley SNESSetFunctionNorm - Sets the last computed residual norm. 2074c5ce4427SMatthew G. Knepley 2075c3339decSBarry Smith Logically Collective 2076c5ce4427SMatthew G. Knepley 2077c5ce4427SMatthew G. Knepley Input Parameters: 2078f6dfbefdSBarry Smith + snes - the `SNES` context 2079f6dfbefdSBarry Smith - norm - the value of the norm 2080c5ce4427SMatthew G. Knepley 2081c5ce4427SMatthew G. Knepley Level: developer 2082c5ce4427SMatthew G. Knepley 20831cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 2084c5ce4427SMatthew G. Knepley @*/ 2085d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionNorm(SNES snes, PetscReal norm) 2086d71ae5a4SJacob Faibussowitsch { 2087c5ce4427SMatthew G. Knepley PetscFunctionBegin; 2088c5ce4427SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2089c5ce4427SMatthew G. Knepley snes->norm = norm; 20903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2091c5ce4427SMatthew G. Knepley } 2092c5ce4427SMatthew G. Knepley 2093c5ce4427SMatthew G. Knepley /*@ 2094c5ce4427SMatthew G. Knepley SNESGetFunctionNorm - Gets the last computed norm of the residual 2095c5ce4427SMatthew G. Knepley 2096c5ce4427SMatthew G. Knepley Not Collective 2097c5ce4427SMatthew G. Knepley 2098c5ce4427SMatthew G. Knepley Input Parameter: 2099f6dfbefdSBarry Smith . snes - the `SNES` context 2100c5ce4427SMatthew G. Knepley 2101c5ce4427SMatthew G. Knepley Output Parameter: 2102c5ce4427SMatthew G. Knepley . norm - the last computed residual norm 2103c5ce4427SMatthew G. Knepley 2104c5ce4427SMatthew G. Knepley Level: developer 2105c5ce4427SMatthew G. Knepley 21061cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 2107c5ce4427SMatthew G. Knepley @*/ 2108d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionNorm(SNES snes, PetscReal *norm) 2109d71ae5a4SJacob Faibussowitsch { 2110c5ce4427SMatthew G. Knepley PetscFunctionBegin; 2111c5ce4427SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 21124f572ea9SToby Isaac PetscAssertPointer(norm, 2); 2113c5ce4427SMatthew G. Knepley *norm = snes->norm; 21143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2115c5ce4427SMatthew G. Knepley } 2116c5ce4427SMatthew G. Knepley 2117c1e67a49SFande Kong /*@ 2118f6dfbefdSBarry Smith SNESGetUpdateNorm - Gets the last computed norm of the solution update 2119c1e67a49SFande Kong 2120c1e67a49SFande Kong Not Collective 2121c1e67a49SFande Kong 2122c1e67a49SFande Kong Input Parameter: 2123f6dfbefdSBarry Smith . snes - the `SNES` context 2124c1e67a49SFande Kong 2125c1e67a49SFande Kong Output Parameter: 2126c1e67a49SFande Kong . ynorm - the last computed update norm 2127c1e67a49SFande Kong 2128c1e67a49SFande Kong Level: developer 2129c1e67a49SFande Kong 2130f6dfbefdSBarry Smith Note: 2131f6dfbefdSBarry Smith The new solution is the current solution plus the update, so this norm is an indication of the size of the update 2132f6dfbefdSBarry Smith 21331cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()` 2134c1e67a49SFande Kong @*/ 2135d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUpdateNorm(SNES snes, PetscReal *ynorm) 2136d71ae5a4SJacob Faibussowitsch { 2137c1e67a49SFande Kong PetscFunctionBegin; 2138c1e67a49SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 21394f572ea9SToby Isaac PetscAssertPointer(ynorm, 2); 2140c1e67a49SFande Kong *ynorm = snes->ynorm; 21413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2142c1e67a49SFande Kong } 2143c1e67a49SFande Kong 2144c1e67a49SFande Kong /*@ 21454591eaf2SFande Kong SNESGetSolutionNorm - Gets the last computed norm of the solution 2146c1e67a49SFande Kong 2147c1e67a49SFande Kong Not Collective 2148c1e67a49SFande Kong 2149c1e67a49SFande Kong Input Parameter: 2150f6dfbefdSBarry Smith . snes - the `SNES` context 2151c1e67a49SFande Kong 2152c1e67a49SFande Kong Output Parameter: 2153c1e67a49SFande Kong . xnorm - the last computed solution norm 2154c1e67a49SFande Kong 2155c1e67a49SFande Kong Level: developer 2156c1e67a49SFande Kong 21571cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`, `SNESGetUpdateNorm()` 2158c1e67a49SFande Kong @*/ 2159d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionNorm(SNES snes, PetscReal *xnorm) 2160d71ae5a4SJacob Faibussowitsch { 2161c1e67a49SFande Kong PetscFunctionBegin; 2162c1e67a49SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 21634f572ea9SToby Isaac PetscAssertPointer(xnorm, 2); 2164c1e67a49SFande Kong *xnorm = snes->xnorm; 21653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2166c1e67a49SFande Kong } 2167c1e67a49SFande Kong 2168cc4c1da9SBarry Smith /*@ 2169f6dfbefdSBarry Smith SNESSetFunctionType - Sets the `SNESFunctionType` 2170f6dfbefdSBarry Smith of the `SNES` method. 217147073ea2SPeter Brune 2172c3339decSBarry Smith Logically Collective 217347073ea2SPeter Brune 217447073ea2SPeter Brune Input Parameters: 2175f6dfbefdSBarry Smith + snes - the `SNES` context 2176f6dfbefdSBarry Smith - type - the function type 217747073ea2SPeter Brune 217847073ea2SPeter Brune Level: developer 217947073ea2SPeter Brune 2180420bcc1bSBarry Smith Values of the function type\: 2181f6dfbefdSBarry Smith + `SNES_FUNCTION_DEFAULT` - the default for the given `SNESType` 2182f6dfbefdSBarry Smith . `SNES_FUNCTION_UNPRECONDITIONED` - an unpreconditioned function evaluation (this is the function provided with `SNESSetFunction()` 2183f6dfbefdSBarry Smith - `SNES_FUNCTION_PRECONDITIONED` - a transformation of the function provided with `SNESSetFunction()` 2184f6dfbefdSBarry Smith 2185420bcc1bSBarry Smith Note: 2186f6dfbefdSBarry Smith Different `SNESType`s use this value in different ways 2187f6dfbefdSBarry Smith 21881cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFunctionType`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 218947073ea2SPeter Brune @*/ 2190d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionType(SNES snes, SNESFunctionType type) 2191d71ae5a4SJacob Faibussowitsch { 219247073ea2SPeter Brune PetscFunctionBegin; 219347073ea2SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 219447073ea2SPeter Brune snes->functype = type; 21953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 219647073ea2SPeter Brune } 219747073ea2SPeter Brune 2198cc4c1da9SBarry Smith /*@ 2199f6dfbefdSBarry Smith SNESGetFunctionType - Gets the `SNESFunctionType` used in convergence and monitoring set with `SNESSetFunctionType()` 220047073ea2SPeter Brune of the SNES method. 220147073ea2SPeter Brune 2202c3339decSBarry Smith Logically Collective 220347073ea2SPeter Brune 220447073ea2SPeter Brune Input Parameters: 2205f6dfbefdSBarry Smith + snes - the `SNES` context 2206f6dfbefdSBarry Smith - type - the type of the function evaluation, see `SNESSetFunctionType()` 220747073ea2SPeter Brune 220847073ea2SPeter Brune Level: advanced 220947073ea2SPeter Brune 22101cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetFunctionType()`, `SNESFunctionType`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 221147073ea2SPeter Brune @*/ 2212d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionType(SNES snes, SNESFunctionType *type) 2213d71ae5a4SJacob Faibussowitsch { 221447073ea2SPeter Brune PetscFunctionBegin; 221547073ea2SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 221647073ea2SPeter Brune *type = snes->functype; 22173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2218534ebe21SPeter Brune } 2219534ebe21SPeter Brune 2220c79ef259SPeter Brune /*@C 2221be95d8f1SBarry Smith SNESSetNGS - Sets the user nonlinear Gauss-Seidel routine for 2222c79ef259SPeter Brune use with composed nonlinear solvers. 2223c79ef259SPeter Brune 2224c79ef259SPeter Brune Input Parameters: 22259bcc50f1SBarry Smith + snes - the `SNES` context, usually of the `SNESType` `SNESNGS` 22268434afd1SBarry Smith . f - function evaluation routine to apply Gauss-Seidel, see `SNESNGSFn` for calling sequence 222777e5a1f9SBarry Smith - ctx - [optional] user-defined context for private data for the smoother evaluation routine (may be `NULL`) 2228c79ef259SPeter Brune 2229dc4c0fb0SBarry Smith Level: intermediate 2230dc4c0fb0SBarry Smith 2231f6dfbefdSBarry Smith Note: 2232f6dfbefdSBarry Smith The `SNESNGS` routines are used by the composed nonlinear solver to generate 2233f6dfbefdSBarry Smith a problem appropriate update to the solution, particularly `SNESFAS`. 2234c79ef259SPeter Brune 22358434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGS`, `SNESGetNGS()`, `SNESNCG`, `SNESGetFunction()`, `SNESComputeNGS()`, `SNESNGSFn` 2236c79ef259SPeter Brune @*/ 22378434afd1SBarry Smith PetscErrorCode SNESSetNGS(SNES snes, SNESNGSFn *f, void *ctx) 2238d71ae5a4SJacob Faibussowitsch { 22396cab3a1bSJed Brown DM dm; 22406cab3a1bSJed Brown 2241646217ecSPeter Brune PetscFunctionBegin; 22426cab3a1bSJed Brown PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 22439566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 22449566063dSJacob Faibussowitsch PetscCall(DMSNESSetNGS(dm, f, ctx)); 22453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2246646217ecSPeter Brune } 2247646217ecSPeter Brune 2248bbc1464cSBarry Smith /* 2249bbc1464cSBarry Smith This is used for -snes_mf_operator; it uses a duplicate of snes->jacobian_pre because snes->jacobian_pre cannot be 2250bbc1464cSBarry Smith changed during the KSPSolve() 2251bbc1464cSBarry Smith */ 2252d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeMFFunction(SNES snes, Vec x, Vec f, void *ctx) 2253d71ae5a4SJacob Faibussowitsch { 2254bbc1464cSBarry Smith DM dm; 2255bbc1464cSBarry Smith DMSNES sdm; 2256bbc1464cSBarry Smith 2257bbc1464cSBarry Smith PetscFunctionBegin; 22589566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 22599566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 2260bbc1464cSBarry Smith /* A(x)*x - b(x) */ 2261bbc1464cSBarry Smith if (sdm->ops->computepfunction) { 2262792fecdfSBarry Smith PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx)); 22639566063dSJacob Faibussowitsch PetscCall(VecScale(f, -1.0)); 22640df40c35SBarry Smith /* Cannot share nonzero pattern because of the possible use of SNESComputeJacobianDefault() */ 2265ef1023bdSBarry Smith if (!snes->picard) PetscCall(MatDuplicate(snes->jacobian_pre, MAT_DO_NOT_COPY_VALUES, &snes->picard)); 2266792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx)); 22679566063dSJacob Faibussowitsch PetscCall(MatMultAdd(snes->picard, x, f, f)); 2268bbc1464cSBarry Smith } else { 2269792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx)); 22709566063dSJacob Faibussowitsch PetscCall(MatMult(snes->picard, x, f)); 2271bbc1464cSBarry Smith } 22723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2273bbc1464cSBarry Smith } 2274bbc1464cSBarry Smith 2275d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeFunction(SNES snes, Vec x, Vec f, void *ctx) 2276d71ae5a4SJacob Faibussowitsch { 2277e03ab78fSPeter Brune DM dm; 2278942e3340SBarry Smith DMSNES sdm; 22796cab3a1bSJed Brown 22808b0a5094SBarry Smith PetscFunctionBegin; 22819566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 22829566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 22838b0a5094SBarry Smith /* A(x)*x - b(x) */ 2284bbc1464cSBarry Smith if (sdm->ops->computepfunction) { 2285792fecdfSBarry Smith PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx)); 22869566063dSJacob Faibussowitsch PetscCall(VecScale(f, -1.0)); 2287792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx)); 22889566063dSJacob Faibussowitsch PetscCall(MatMultAdd(snes->jacobian_pre, x, f, f)); 2289bbc1464cSBarry Smith } else { 2290792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx)); 22919566063dSJacob Faibussowitsch PetscCall(MatMult(snes->jacobian_pre, x, f)); 2292bbc1464cSBarry Smith } 22933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22948b0a5094SBarry Smith } 22958b0a5094SBarry Smith 2296d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeJacobian(SNES snes, Vec x1, Mat J, Mat B, void *ctx) 2297d71ae5a4SJacob Faibussowitsch { 22988b0a5094SBarry Smith PetscFunctionBegin; 2299e03ab78fSPeter Brune /* the jacobian matrix should be pre-filled in SNESPicardComputeFunction */ 2300bbc1464cSBarry Smith /* must assembly if matrix-free to get the last SNES solution */ 23019566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 23029566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 23033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23048b0a5094SBarry Smith } 23058b0a5094SBarry Smith 23068b0a5094SBarry Smith /*@C 23071d27aa22SBarry Smith SNESSetPicard - Use `SNES` to solve the system $A(x) x = bp(x) + b $ via a Picard type iteration (Picard linearization) 23088b0a5094SBarry Smith 2309c3339decSBarry Smith Logically Collective 23108b0a5094SBarry Smith 23118b0a5094SBarry Smith Input Parameters: 2312f6dfbefdSBarry Smith + snes - the `SNES` context 2313dc4c0fb0SBarry Smith . r - vector to store function values, may be `NULL` 23148434afd1SBarry Smith . bp - function evaluation routine, may be `NULL`, for the calling sequence see `SNESFunctionFn` 231526a11704SBarry Smith . Amat - matrix with which $A(x) x - bp(x) - b$ is to be computed 2316dc4c0fb0SBarry Smith . Pmat - matrix from which preconditioner is computed (usually the same as `Amat`) 23178434afd1SBarry Smith . J - function to compute matrix values, for the calling sequence see `SNESJacobianFn` 2318dc4c0fb0SBarry Smith - ctx - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`) 2319dc4c0fb0SBarry Smith 2320dc4c0fb0SBarry Smith Level: intermediate 23218b0a5094SBarry Smith 23228b0a5094SBarry Smith Notes: 232326a11704SBarry Smith It is often better to provide the nonlinear function $F()$ and some approximation to its Jacobian directly and use 2324f450aa47SBarry Smith an approximate Newton solver. This interface is provided to allow porting/testing a previous Picard based code in PETSc before converting it to approximate Newton. 2325f450aa47SBarry Smith 2326f6dfbefdSBarry Smith One can call `SNESSetPicard()` or `SNESSetFunction()` (and possibly `SNESSetJacobian()`) but cannot call both 23278b0a5094SBarry Smith 23281d27aa22SBarry Smith Solves the equation $A(x) x = bp(x) - b$ via the defect correction algorithm $A(x^{n}) (x^{n+1} - x^{n}) = bp(x^{n}) + b - A(x^{n})x^{n}$. 23291d27aa22SBarry Smith When an exact solver is used this corresponds to the "classic" Picard $A(x^{n}) x^{n+1} = bp(x^{n}) + b$ iteration. 23308b0a5094SBarry Smith 233126a11704SBarry Smith Run with `-snes_mf_operator` to solve the system with Newton's method using $A(x^{n})$ to construct the preconditioner. 23328b0a5094SBarry Smith 23330d04baf8SBarry Smith We implement the defect correction form of the Picard iteration because it converges much more generally when inexact linear solvers are used then 23341d27aa22SBarry Smith the direct Picard iteration $A(x^n) x^{n+1} = bp(x^n) + b$ 23358b0a5094SBarry Smith 23368b0a5094SBarry Smith There is some controversity over the definition of a Picard iteration for nonlinear systems but almost everyone agrees that it involves a linear solve and some 23371d27aa22SBarry Smith believe it is the iteration $A(x^{n}) x^{n+1} = b(x^{n})$ hence we use the name Picard. If anyone has an authoritative reference that defines the Picard iteration 23381d27aa22SBarry Smith different please contact us at petsc-dev@mcs.anl.gov and we'll have an entirely new argument \:-). 23398b0a5094SBarry Smith 23401d27aa22SBarry Smith When used with `-snes_mf_operator` this will run matrix-free Newton's method where the matrix-vector product is of the true Jacobian of $A(x)x - bp(x) - b$ and 234126a11704SBarry Smith $A(x^{n})$ is used to build the preconditioner 23426b7fb656SBarry Smith 234315229ffcSPierre Jolivet When used with `-snes_fd` this will compute the true Jacobian (very slowly one column at a time) and thus represent Newton's method. 23446b7fb656SBarry Smith 2345dc4c0fb0SBarry Smith When used with `-snes_fd_coloring` this will compute the Jacobian via coloring and thus represent a faster implementation of Newton's method. But the 234626a11704SBarry Smith the nonzero structure of the Jacobian is, in general larger than that of the Picard matrix $A$ so you must provide in $A$ the needed nonzero structure for the correct 234726a11704SBarry Smith coloring. When using `DMDA` this may mean creating the matrix $A$ with `DMCreateMatrix()` using a wider stencil than strictly needed for $A$ or with a `DMDA_STENCIL_BOX`. 2348aaa8cc7dSPierre Jolivet See the comment in src/snes/tutorials/ex15.c. 2349bbc1464cSBarry Smith 23509bcc50f1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESGetPicard()`, `SNESLineSearchPreCheckPicard()`, 23518434afd1SBarry Smith `SNESFunctionFn`, `SNESJacobianFn` 23528b0a5094SBarry Smith @*/ 23538434afd1SBarry Smith PetscErrorCode SNESSetPicard(SNES snes, Vec r, SNESFunctionFn *bp, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx) 2354d71ae5a4SJacob Faibussowitsch { 2355e03ab78fSPeter Brune DM dm; 2356e03ab78fSPeter Brune 23578b0a5094SBarry Smith PetscFunctionBegin; 23588b0a5094SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 23599566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 23609566063dSJacob Faibussowitsch PetscCall(DMSNESSetPicard(dm, bp, J, ctx)); 23619566063dSJacob Faibussowitsch PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx)); 23629566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes, r, SNESPicardComputeFunction, ctx)); 23639566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESPicardComputeJacobian, ctx)); 23643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23658b0a5094SBarry Smith } 23668b0a5094SBarry Smith 23677971a8bfSPeter Brune /*@C 23687971a8bfSPeter Brune SNESGetPicard - Returns the context for the Picard iteration 23697971a8bfSPeter Brune 2370f6dfbefdSBarry Smith Not Collective, but `Vec` is parallel if `SNES` is parallel. Collective if `Vec` is requested, but has not been created yet. 23717971a8bfSPeter Brune 23727971a8bfSPeter Brune Input Parameter: 2373f6dfbefdSBarry Smith . snes - the `SNES` context 23747971a8bfSPeter Brune 2375d8d19677SJose E. Roman Output Parameters: 2376dc4c0fb0SBarry Smith + r - the function (or `NULL`) 23778434afd1SBarry Smith . f - the function (or `NULL`); for calling sequence see `SNESFunctionFn` 2378dc4c0fb0SBarry Smith . Amat - the matrix used to defined the operation A(x) x - b(x) (or `NULL`) 2379dc4c0fb0SBarry Smith . Pmat - the matrix from which the preconditioner will be constructed (or `NULL`) 23808434afd1SBarry Smith . J - the function for matrix evaluation (or `NULL`); for calling sequence see `SNESJacobianFn` 2381dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`) 23827971a8bfSPeter Brune 23837971a8bfSPeter Brune Level: advanced 23847971a8bfSPeter Brune 23858434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetFunction()`, `SNESSetPicard()`, `SNESGetFunction()`, `SNESGetJacobian()`, `SNESGetDM()`, `SNESFunctionFn`, `SNESJacobianFn` 23867971a8bfSPeter Brune @*/ 23878434afd1SBarry Smith PetscErrorCode SNESGetPicard(SNES snes, Vec *r, SNESFunctionFn **f, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx) 2388d71ae5a4SJacob Faibussowitsch { 23897971a8bfSPeter Brune DM dm; 23907971a8bfSPeter Brune 23917971a8bfSPeter Brune PetscFunctionBegin; 23927971a8bfSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 23939566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, r, NULL, NULL)); 23949566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL)); 23959566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 23969566063dSJacob Faibussowitsch PetscCall(DMSNESGetPicard(dm, f, J, ctx)); 23973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23987971a8bfSPeter Brune } 23997971a8bfSPeter Brune 2400d25893d9SBarry Smith /*@C 2401dc4c0fb0SBarry Smith SNESSetComputeInitialGuess - Sets a routine used to compute an initial guess for the nonlinear problem 2402d25893d9SBarry Smith 2403c3339decSBarry Smith Logically Collective 2404d25893d9SBarry Smith 2405d25893d9SBarry Smith Input Parameters: 2406f6dfbefdSBarry Smith + snes - the `SNES` context 24078434afd1SBarry Smith . func - function evaluation routine, see `SNESInitialGuessFn` for the calling sequence 2408d25893d9SBarry Smith - ctx - [optional] user-defined context for private data for the 2409dc4c0fb0SBarry Smith function evaluation routine (may be `NULL`) 2410d25893d9SBarry Smith 2411d25893d9SBarry Smith Level: intermediate 2412d25893d9SBarry Smith 24138434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESInitialGuessFn` 2414d25893d9SBarry Smith @*/ 24158434afd1SBarry Smith PetscErrorCode SNESSetComputeInitialGuess(SNES snes, SNESInitialGuessFn *func, void *ctx) 2416d71ae5a4SJacob Faibussowitsch { 2417d25893d9SBarry Smith PetscFunctionBegin; 2418d25893d9SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2419d25893d9SBarry Smith if (func) snes->ops->computeinitialguess = func; 2420d25893d9SBarry Smith if (ctx) snes->initialguessP = ctx; 24213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2422d25893d9SBarry Smith } 2423d25893d9SBarry Smith 24241096aae1SMatthew Knepley /*@C 2425dc4c0fb0SBarry Smith SNESGetRhs - Gets the vector for solving F(x) = `rhs`. If `rhs` is not set 2426dd8e379bSPierre Jolivet it assumes a zero right-hand side. 24271096aae1SMatthew Knepley 2428c3339decSBarry Smith Logically Collective 24291096aae1SMatthew Knepley 24301096aae1SMatthew Knepley Input Parameter: 2431f6dfbefdSBarry Smith . snes - the `SNES` context 24321096aae1SMatthew Knepley 24331096aae1SMatthew Knepley Output Parameter: 2434dd8e379bSPierre Jolivet . rhs - the right-hand side vector or `NULL` if there is no right-hand side vector 24351096aae1SMatthew Knepley 24361096aae1SMatthew Knepley Level: intermediate 24371096aae1SMatthew Knepley 24381cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetFunction()` 24391096aae1SMatthew Knepley @*/ 2440d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetRhs(SNES snes, Vec *rhs) 2441d71ae5a4SJacob Faibussowitsch { 24421096aae1SMatthew Knepley PetscFunctionBegin; 24430700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 24444f572ea9SToby Isaac PetscAssertPointer(rhs, 2); 244585385478SLisandro Dalcin *rhs = snes->vec_rhs; 24463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24471096aae1SMatthew Knepley } 24481096aae1SMatthew Knepley 24499b94acceSBarry Smith /*@ 2450f6dfbefdSBarry Smith SNESComputeFunction - Calls the function that has been set with `SNESSetFunction()`. 24519b94acceSBarry Smith 2452c3339decSBarry Smith Collective 2453c7afd0dbSLois Curfman McInnes 24549b94acceSBarry Smith Input Parameters: 2455f6dfbefdSBarry Smith + snes - the `SNES` context 2456c7afd0dbSLois Curfman McInnes - x - input vector 24579b94acceSBarry Smith 24589b94acceSBarry Smith Output Parameter: 2459*76c63389SBarry Smith . f - function vector, as set by `SNESSetFunction()` 24609b94acceSBarry Smith 2461dc4c0fb0SBarry Smith Level: developer 2462dc4c0fb0SBarry Smith 246300677de2SStefano Zampini Notes: 2464f6dfbefdSBarry Smith `SNESComputeFunction()` is typically used within nonlinear solvers 2465bbc1464cSBarry Smith implementations, so users would not generally call this routine themselves. 246636851e7fSLois Curfman McInnes 2467*76c63389SBarry Smith When solving for $F(x) = b$, this routine computes $f = F(x) - b$. 246800677de2SStefano Zampini 2469*76c63389SBarry Smith This function usually appears in the pattern. 2470*76c63389SBarry Smith .vb 2471*76c63389SBarry Smith SNESComputeFunction(snes, x, f); 2472*76c63389SBarry Smith VecNorm(f, &fnorm); 2473*76c63389SBarry Smith SNESCheckFunctionDomainError(snes, fnorm); or SNESLineSearchCheckFunctionDomainError(ls, fnorm); 2474*76c63389SBarry Smith .ve 2475*76c63389SBarry Smith to collectively handle the use of `SNESSetFunctionDomainError()` in the provided callback function. 2476*76c63389SBarry Smith 2477*76c63389SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeMFFunction()`, `SNESSetFunctionDomainError()` 24789b94acceSBarry Smith @*/ 2479*76c63389SBarry Smith PetscErrorCode SNESComputeFunction(SNES snes, Vec x, Vec f) 2480d71ae5a4SJacob Faibussowitsch { 24816cab3a1bSJed Brown DM dm; 2482942e3340SBarry Smith DMSNES sdm; 24839b94acceSBarry Smith 24843a40ed3dSBarry Smith PetscFunctionBegin; 24850700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 24860700a824SBarry Smith PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2487*76c63389SBarry Smith PetscValidHeaderSpecific(f, VEC_CLASSID, 3); 2488c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, x, 2); 2489*76c63389SBarry Smith PetscCheckSameComm(snes, 1, f, 3); 2490e0f629ddSJacob Faibussowitsch PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2491184914b5SBarry Smith 24929566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 24939566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 24940fdf79fbSJacob Faibussowitsch PetscCheck(sdm->ops->computefunction || snes->vec_rhs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetFunction() or SNESSetDM() before SNESComputeFunction(), likely called from SNESSolve()."); 249532f3f7c2SPeter Brune if (sdm->ops->computefunction) { 2496*76c63389SBarry Smith if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, f, 0)); 24979566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(x)); 24988ddeebeaSSteve Benbow /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */ 2499*76c63389SBarry Smith snes->functiondomainerror = PETSC_FALSE; 2500800f99ffSJeremy L Thompson { 2501800f99ffSJeremy L Thompson void *ctx; 25028434afd1SBarry Smith SNESFunctionFn *computefunction; 2503800f99ffSJeremy L Thompson PetscCall(DMSNESGetFunction(dm, &computefunction, &ctx)); 2504*76c63389SBarry Smith PetscCallBack("SNES callback function", (*computefunction)(snes, x, f, ctx)); 2505800f99ffSJeremy L Thompson } 25069566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(x)); 2507*76c63389SBarry Smith if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, f, 0)); 25080fdf79fbSJacob Faibussowitsch } else /* if (snes->vec_rhs) */ { 2509*76c63389SBarry Smith PetscCall(MatMult(snes->jacobian, x, f)); 25100fdf79fbSJacob Faibussowitsch } 2511*76c63389SBarry Smith if (snes->vec_rhs) PetscCall(VecAXPY(f, -1.0, snes->vec_rhs)); 2512ae3c334cSLois Curfman McInnes snes->nfuncs++; 2513422a814eSBarry Smith /* 2514*76c63389SBarry Smith domainerror might not be set on all processes; so we tag vector locally with infinity and the next inner product or norm will 2515422a814eSBarry Smith propagate the value to all processes 2516422a814eSBarry Smith */ 2517*76c63389SBarry Smith PetscCall(VecFlag(f, snes->functiondomainerror)); 25183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 25199b94acceSBarry Smith } 25209b94acceSBarry Smith 2521c79ef259SPeter Brune /*@ 25220b4b7b1cSBarry Smith SNESComputeMFFunction - Calls the function that has been set with `DMSNESSetMFFunction()`. 2523bbc1464cSBarry Smith 2524c3339decSBarry Smith Collective 2525bbc1464cSBarry Smith 2526bbc1464cSBarry Smith Input Parameters: 2527f6dfbefdSBarry Smith + snes - the `SNES` context 2528bbc1464cSBarry Smith - x - input vector 2529bbc1464cSBarry Smith 2530bbc1464cSBarry Smith Output Parameter: 25310b4b7b1cSBarry Smith . y - output vector 2532bbc1464cSBarry Smith 2533dc4c0fb0SBarry Smith Level: developer 2534dc4c0fb0SBarry Smith 2535bbc1464cSBarry Smith Notes: 2536420bcc1bSBarry Smith `SNESComputeMFFunction()` is used within the matrix-vector products called by the matrix created with `MatCreateSNESMF()` 2537bbc1464cSBarry Smith so users would not generally call this routine themselves. 2538bbc1464cSBarry Smith 2539dd8e379bSPierre Jolivet Since this function is intended for use with finite differencing it does not subtract the right-hand side vector provided with `SNESSolve()` 2540f6dfbefdSBarry Smith while `SNESComputeFunction()` does. As such, this routine cannot be used with `MatMFFDSetBase()` with a provided F function value even if it applies the 2541dd8e379bSPierre Jolivet same function as `SNESComputeFunction()` if a `SNESSolve()` right-hand side vector is use because the two functions difference would include this right hand side function. 2542bbc1464cSBarry Smith 25430b4b7b1cSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `MatCreateSNESMF()`, `DMSNESSetMFFunction()` 2544bbc1464cSBarry Smith @*/ 2545d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeMFFunction(SNES snes, Vec x, Vec y) 2546d71ae5a4SJacob Faibussowitsch { 2547bbc1464cSBarry Smith DM dm; 2548bbc1464cSBarry Smith DMSNES sdm; 2549bbc1464cSBarry Smith 2550bbc1464cSBarry Smith PetscFunctionBegin; 2551bbc1464cSBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2552bbc1464cSBarry Smith PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2553bbc1464cSBarry Smith PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2554bbc1464cSBarry Smith PetscCheckSameComm(snes, 1, x, 2); 2555bbc1464cSBarry Smith PetscCheckSameComm(snes, 1, y, 3); 2556e0f629ddSJacob Faibussowitsch PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2557bbc1464cSBarry Smith 25589566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 25599566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 25609566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0)); 25619566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(x)); 2562bbc1464cSBarry Smith /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */ 2563*76c63389SBarry Smith snes->functiondomainerror = PETSC_FALSE; 2564792fecdfSBarry Smith PetscCallBack("SNES callback function", (*sdm->ops->computemffunction)(snes, x, y, sdm->mffunctionctx)); 25659566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(x)); 25669566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0)); 2567bbc1464cSBarry Smith snes->nfuncs++; 2568bbc1464cSBarry Smith /* 2569*76c63389SBarry Smith domainerror might not be set on all processes; so we tag vector locally with infinity and the next inner product or norm will 2570bbc1464cSBarry Smith propagate the value to all processes 2571bbc1464cSBarry Smith */ 2572*76c63389SBarry Smith PetscCall(VecFlag(y, snes->functiondomainerror)); 25733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2574bbc1464cSBarry Smith } 2575bbc1464cSBarry Smith 2576bbc1464cSBarry Smith /*@ 2577f6dfbefdSBarry Smith SNESComputeNGS - Calls the Gauss-Seidel function that has been set with `SNESSetNGS()`. 2578c79ef259SPeter Brune 2579c3339decSBarry Smith Collective 2580c79ef259SPeter Brune 2581c79ef259SPeter Brune Input Parameters: 2582f6dfbefdSBarry Smith + snes - the `SNES` context 2583c79ef259SPeter Brune . x - input vector 2584c79ef259SPeter Brune - b - rhs vector 2585c79ef259SPeter Brune 2586c79ef259SPeter Brune Output Parameter: 2587c79ef259SPeter Brune . x - new solution vector 2588c79ef259SPeter Brune 2589dc4c0fb0SBarry Smith Level: developer 2590dc4c0fb0SBarry Smith 2591f6dfbefdSBarry Smith Note: 2592f6dfbefdSBarry Smith `SNESComputeNGS()` is typically used within composed nonlinear solver 2593c79ef259SPeter Brune implementations, so most users would not generally call this routine 2594c79ef259SPeter Brune themselves. 2595c79ef259SPeter Brune 25968434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGSFn`, `SNESSetNGS()`, `SNESComputeFunction()`, `SNESNGS` 2597c79ef259SPeter Brune @*/ 2598d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeNGS(SNES snes, Vec b, Vec x) 2599d71ae5a4SJacob Faibussowitsch { 26006cab3a1bSJed Brown DM dm; 2601942e3340SBarry Smith DMSNES sdm; 2602646217ecSPeter Brune 2603646217ecSPeter Brune PetscFunctionBegin; 2604646217ecSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2605064a246eSJacob Faibussowitsch PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 2606064a246eSJacob Faibussowitsch if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 2607064a246eSJacob Faibussowitsch PetscCheckSameComm(snes, 1, x, 3); 2608064a246eSJacob Faibussowitsch if (b) PetscCheckSameComm(snes, 1, b, 2); 2609e0f629ddSJacob Faibussowitsch if (b) PetscCall(VecValidValues_Internal(b, 2, PETSC_TRUE)); 26109566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_NGSEval, snes, x, b, 0)); 26119566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 26129566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 26130fdf79fbSJacob Faibussowitsch PetscCheck(sdm->ops->computegs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetNGS() before SNESComputeNGS(), likely called from SNESSolve()."); 26149566063dSJacob Faibussowitsch if (b) PetscCall(VecLockReadPush(b)); 2615792fecdfSBarry Smith PetscCallBack("SNES callback NGS", (*sdm->ops->computegs)(snes, x, b, sdm->gsctx)); 26169566063dSJacob Faibussowitsch if (b) PetscCall(VecLockReadPop(b)); 26179566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_NGSEval, snes, x, b, 0)); 26183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2619646217ecSPeter Brune } 2620646217ecSPeter Brune 2621494a190aSStefano Zampini static PetscErrorCode SNESComputeFunction_FD(SNES snes, Vec Xin, Vec G) 2622494a190aSStefano Zampini { 2623494a190aSStefano Zampini Vec X; 2624494a190aSStefano Zampini PetscScalar *g; 2625494a190aSStefano Zampini PetscReal f, f2; 2626494a190aSStefano Zampini PetscInt low, high, N, i; 2627494a190aSStefano Zampini PetscBool flg; 2628494a190aSStefano Zampini PetscReal h = .5 * PETSC_SQRT_MACHINE_EPSILON; 2629494a190aSStefano Zampini 2630494a190aSStefano Zampini PetscFunctionBegin; 2631494a190aSStefano Zampini PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_fd_delta", &h, &flg)); 2632494a190aSStefano Zampini PetscCall(VecDuplicate(Xin, &X)); 2633494a190aSStefano Zampini PetscCall(VecCopy(Xin, X)); 2634494a190aSStefano Zampini PetscCall(VecGetSize(X, &N)); 2635494a190aSStefano Zampini PetscCall(VecGetOwnershipRange(X, &low, &high)); 2636494a190aSStefano Zampini PetscCall(VecSetOption(X, VEC_IGNORE_OFF_PROC_ENTRIES, PETSC_TRUE)); 2637494a190aSStefano Zampini PetscCall(VecGetArray(G, &g)); 2638494a190aSStefano Zampini for (i = 0; i < N; i++) { 2639494a190aSStefano Zampini PetscCall(VecSetValue(X, i, -h, ADD_VALUES)); 2640494a190aSStefano Zampini PetscCall(VecAssemblyBegin(X)); 2641494a190aSStefano Zampini PetscCall(VecAssemblyEnd(X)); 2642494a190aSStefano Zampini PetscCall(SNESComputeObjective(snes, X, &f)); 2643494a190aSStefano Zampini PetscCall(VecSetValue(X, i, 2.0 * h, ADD_VALUES)); 2644494a190aSStefano Zampini PetscCall(VecAssemblyBegin(X)); 2645494a190aSStefano Zampini PetscCall(VecAssemblyEnd(X)); 2646494a190aSStefano Zampini PetscCall(SNESComputeObjective(snes, X, &f2)); 2647494a190aSStefano Zampini PetscCall(VecSetValue(X, i, -h, ADD_VALUES)); 2648494a190aSStefano Zampini PetscCall(VecAssemblyBegin(X)); 2649494a190aSStefano Zampini PetscCall(VecAssemblyEnd(X)); 2650494a190aSStefano Zampini if (i >= low && i < high) g[i - low] = (f2 - f) / (2.0 * h); 2651494a190aSStefano Zampini } 2652494a190aSStefano Zampini PetscCall(VecRestoreArray(G, &g)); 2653494a190aSStefano Zampini PetscCall(VecDestroy(&X)); 2654494a190aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2655494a190aSStefano Zampini } 2656494a190aSStefano Zampini 26571dfd7622SMatthew Knepley /*@ 26581dfd7622SMatthew Knepley SNESTestFunction - Computes the difference between the computed and finite-difference functions 26591dfd7622SMatthew Knepley 26601dfd7622SMatthew Knepley Collective 26611dfd7622SMatthew Knepley 2662d5bfe6baSJose E. Roman Input Parameter: 26631dfd7622SMatthew Knepley . snes - the `SNES` context 26641dfd7622SMatthew Knepley 26651dfd7622SMatthew Knepley Options Database Keys: 26661dfd7622SMatthew Knepley + -snes_test_function - compare the user provided function with one compute via finite differences to check for errors. 26671dfd7622SMatthew Knepley - -snes_test_function_view - display the user provided function, the finite difference function and the difference 26681dfd7622SMatthew Knepley 26691dfd7622SMatthew Knepley Level: developer 26701dfd7622SMatthew Knepley 26711dfd7622SMatthew Knepley .seealso: [](ch_snes), `SNESTestJacobian()`, `SNESSetFunction()`, `SNESComputeFunction()` 26721dfd7622SMatthew Knepley @*/ 2673494a190aSStefano Zampini PetscErrorCode SNESTestFunction(SNES snes) 2674494a190aSStefano Zampini { 2675494a190aSStefano Zampini Vec x, g1, g2, g3; 26761dfd7622SMatthew Knepley PetscBool complete_print = PETSC_FALSE; 2677494a190aSStefano Zampini PetscReal hcnorm, fdnorm, hcmax, fdmax, diffmax, diffnorm; 2678494a190aSStefano Zampini PetscScalar dot; 2679494a190aSStefano Zampini MPI_Comm comm; 2680494a190aSStefano Zampini PetscViewer viewer, mviewer; 2681494a190aSStefano Zampini PetscViewerFormat format; 2682494a190aSStefano Zampini PetscInt tabs; 2683494a190aSStefano Zampini static PetscBool directionsprinted = PETSC_FALSE; 26848434afd1SBarry Smith SNESObjectiveFn *objective; 2685494a190aSStefano Zampini 2686494a190aSStefano Zampini PetscFunctionBegin; 2687494a190aSStefano Zampini PetscCall(SNESGetObjective(snes, &objective, NULL)); 2688494a190aSStefano Zampini if (!objective) PetscFunctionReturn(PETSC_SUCCESS); 2689494a190aSStefano Zampini 2690494a190aSStefano Zampini PetscObjectOptionsBegin((PetscObject)snes); 2691494a190aSStefano Zampini PetscCall(PetscOptionsViewer("-snes_test_function_view", "View difference between hand-coded and finite difference function element entries", "None", &mviewer, &format, &complete_print)); 2692494a190aSStefano Zampini PetscOptionsEnd(); 2693494a190aSStefano Zampini 2694494a190aSStefano Zampini PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 2695494a190aSStefano Zampini PetscCall(PetscViewerASCIIGetStdout(comm, &viewer)); 2696494a190aSStefano Zampini PetscCall(PetscViewerASCIIGetTab(viewer, &tabs)); 2697494a190aSStefano Zampini PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel)); 2698494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Function -------------\n")); 2699494a190aSStefano Zampini if (!complete_print && !directionsprinted) { 2700494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Run with -snes_test_function_view and optionally -snes_test_function <threshold> to show difference\n")); 2701494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " of hand-coded and finite difference function entries greater than <threshold>.\n")); 2702494a190aSStefano Zampini } 2703494a190aSStefano Zampini if (!directionsprinted) { 2704494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Testing hand-coded Function, if (for double precision runs) ||F - Ffd||/||F|| is\n")); 2705494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " O(1.e-8), the hand-coded Function is probably correct.\n")); 2706494a190aSStefano Zampini directionsprinted = PETSC_TRUE; 2707494a190aSStefano Zampini } 2708494a190aSStefano Zampini if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format)); 2709494a190aSStefano Zampini 2710494a190aSStefano Zampini PetscCall(SNESGetSolution(snes, &x)); 2711494a190aSStefano Zampini PetscCall(VecDuplicate(x, &g1)); 2712494a190aSStefano Zampini PetscCall(VecDuplicate(x, &g2)); 2713494a190aSStefano Zampini PetscCall(VecDuplicate(x, &g3)); 2714*76c63389SBarry Smith PetscCall(SNESComputeFunction(snes, x, g1)); /* does not handle use of SNESSetFunctionDomainError() corrrectly */ 2715494a190aSStefano Zampini PetscCall(SNESComputeFunction_FD(snes, x, g2)); 2716494a190aSStefano Zampini 2717494a190aSStefano Zampini PetscCall(VecNorm(g2, NORM_2, &fdnorm)); 2718494a190aSStefano Zampini PetscCall(VecNorm(g1, NORM_2, &hcnorm)); 2719494a190aSStefano Zampini PetscCall(VecNorm(g2, NORM_INFINITY, &fdmax)); 2720494a190aSStefano Zampini PetscCall(VecNorm(g1, NORM_INFINITY, &hcmax)); 2721494a190aSStefano Zampini PetscCall(VecDot(g1, g2, &dot)); 2722494a190aSStefano Zampini PetscCall(VecCopy(g1, g3)); 2723494a190aSStefano Zampini PetscCall(VecAXPY(g3, -1.0, g2)); 2724494a190aSStefano Zampini PetscCall(VecNorm(g3, NORM_2, &diffnorm)); 2725494a190aSStefano Zampini PetscCall(VecNorm(g3, NORM_INFINITY, &diffmax)); 2726494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " ||Ffd|| %g, ||F|| = %g, angle cosine = (Ffd'F)/||Ffd||||F|| = %g\n", (double)fdnorm, (double)hcnorm, (double)(PetscRealPart(dot) / (fdnorm * hcnorm)))); 2727494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " 2-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffnorm / PetscMax(hcnorm, fdnorm)), (double)diffnorm)); 2728494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " max-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffmax / PetscMax(hcmax, fdmax)), (double)diffmax)); 2729494a190aSStefano Zampini 2730494a190aSStefano Zampini if (complete_print) { 2731494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded function ----------\n")); 2732494a190aSStefano Zampini PetscCall(VecView(g1, mviewer)); 2733494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Finite difference function ----------\n")); 2734494a190aSStefano Zampini PetscCall(VecView(g2, mviewer)); 2735494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded minus finite-difference function ----------\n")); 2736494a190aSStefano Zampini PetscCall(VecView(g3, mviewer)); 2737494a190aSStefano Zampini } 2738494a190aSStefano Zampini PetscCall(VecDestroy(&g1)); 2739494a190aSStefano Zampini PetscCall(VecDestroy(&g2)); 2740494a190aSStefano Zampini PetscCall(VecDestroy(&g3)); 2741494a190aSStefano Zampini 2742494a190aSStefano Zampini if (complete_print) { 2743494a190aSStefano Zampini PetscCall(PetscViewerPopFormat(mviewer)); 2744494a190aSStefano Zampini PetscCall(PetscViewerDestroy(&mviewer)); 2745494a190aSStefano Zampini } 2746494a190aSStefano Zampini PetscCall(PetscViewerASCIISetTab(viewer, tabs)); 2747494a190aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2748494a190aSStefano Zampini } 2749494a190aSStefano Zampini 2750cbf8f02cSMatthew G. Knepley /*@ 2751cbf8f02cSMatthew G. Knepley SNESTestJacobian - Computes the difference between the computed and finite-difference Jacobians 2752cbf8f02cSMatthew G. Knepley 2753cbf8f02cSMatthew G. Knepley Collective 2754cbf8f02cSMatthew G. Knepley 2755d5bfe6baSJose E. Roman Input Parameter: 2756cbf8f02cSMatthew G. Knepley . snes - the `SNES` context 2757cbf8f02cSMatthew G. Knepley 2758cbf8f02cSMatthew G. Knepley Output Parameters: 27591dfd7622SMatthew Knepley + Jnorm - the Frobenius norm of the computed Jacobian, or `NULL` 27601dfd7622SMatthew Knepley - diffNorm - the Frobenius norm of the difference of the computed and finite-difference Jacobians, or `NULL` 2761cbf8f02cSMatthew G. Knepley 2762cbf8f02cSMatthew G. Knepley Options Database Keys: 2763cbf8f02cSMatthew G. Knepley + -snes_test_jacobian <optional threshold> - compare the user provided Jacobian with one compute via finite differences to check for errors. If a threshold is given, display only those entries whose difference is greater than the threshold. 2764cbf8f02cSMatthew G. Knepley - -snes_test_jacobian_view - display the user provided Jacobian, the finite difference Jacobian and the difference 2765cbf8f02cSMatthew G. Knepley 2766cbf8f02cSMatthew G. Knepley Level: developer 2767cbf8f02cSMatthew G. Knepley 27681dfd7622SMatthew Knepley Note: 27691dfd7622SMatthew Knepley Directions and norms are printed to stdout if `diffNorm` is `NULL`. 27701dfd7622SMatthew Knepley 27711dfd7622SMatthew Knepley .seealso: [](ch_snes), `SNESTestFunction()`, `SNESSetJacobian()`, `SNESComputeJacobian()` 2772cbf8f02cSMatthew G. Knepley @*/ 2773cbf8f02cSMatthew G. Knepley PetscErrorCode SNESTestJacobian(SNES snes, PetscReal *Jnorm, PetscReal *diffNorm) 2774d71ae5a4SJacob Faibussowitsch { 277512837594SBarry Smith Mat A, B, C, D, jacobian; 27764df93895SStefano Zampini Vec x = snes->vec_sol, f; 2777e885f1abSBarry Smith PetscReal nrm, gnorm; 277881e7118cSBarry Smith PetscReal threshold = 1.e-5; 27790e276705SLisandro Dalcin MatType mattype; 2780e885f1abSBarry Smith PetscInt m, n, M, N; 2781e885f1abSBarry Smith void *functx; 27821dfd7622SMatthew Knepley PetscBool complete_print = PETSC_FALSE, threshold_print = PETSC_FALSE, flg, istranspose; 27831dfd7622SMatthew Knepley PetscBool silent = diffNorm != PETSC_NULLPTR ? PETSC_TRUE : PETSC_FALSE; 27843325ff46SBarry Smith PetscViewer viewer, mviewer; 2785e885f1abSBarry Smith MPI_Comm comm; 2786e885f1abSBarry Smith PetscInt tabs; 278712837594SBarry Smith static PetscBool directionsprinted = PETSC_FALSE; 27883325ff46SBarry Smith PetscViewerFormat format; 2789e885f1abSBarry Smith 2790e885f1abSBarry Smith PetscFunctionBegin; 2791d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)snes); 27929566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-snes_test_jacobian", "Threshold for element difference between hand-coded and finite difference being meaningful", "None", threshold, &threshold, NULL)); 27939566063dSJacob Faibussowitsch PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display", "-snes_test_jacobian_view", "3.13", NULL)); 27944ead3382SBarry Smith PetscCall(PetscOptionsViewer("-snes_test_jacobian_view", "View difference between hand-coded and finite difference Jacobians element entries", "None", &mviewer, &format, &complete_print)); 27959566063dSJacob Faibussowitsch PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display_threshold", "-snes_test_jacobian", "3.13", "-snes_test_jacobian accepts an optional threshold (since v3.10)")); 27969566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-snes_test_jacobian_display_threshold", "Display difference between hand-coded and finite difference Jacobians which exceed input threshold", "None", threshold, &threshold, &threshold_print)); 2797d0609cedSBarry Smith PetscOptionsEnd(); 2798e885f1abSBarry Smith 27999566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 28009566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(comm, &viewer)); 28019566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetTab(viewer, &tabs)); 28029566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel)); 28031dfd7622SMatthew Knepley if (!silent) PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Jacobian -------------\n")); 28041dfd7622SMatthew Knepley if (!complete_print && !silent && !directionsprinted) { 28059566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Run with -snes_test_jacobian_view and optionally -snes_test_jacobian <threshold> to show difference\n")); 28069566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " of hand-coded and finite difference Jacobian entries greater than <threshold>.\n")); 280712837594SBarry Smith } 28081dfd7622SMatthew Knepley if (!directionsprinted && !silent) { 28099566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Testing hand-coded Jacobian, if (for double precision runs) ||J - Jfd||_F/||J||_F is\n")); 28109566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " O(1.e-8), the hand-coded Jacobian is probably correct.\n")); 281112837594SBarry Smith directionsprinted = PETSC_TRUE; 2812e885f1abSBarry Smith } 28131baa6e33SBarry Smith if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format)); 2814e885f1abSBarry Smith 28159566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes->jacobian, MATMFFD, &flg)); 281612837594SBarry Smith if (!flg) jacobian = snes->jacobian; 281712837594SBarry Smith else jacobian = snes->jacobian_pre; 281812837594SBarry Smith 28194df93895SStefano Zampini if (!x) PetscCall(MatCreateVecs(jacobian, &x, NULL)); 28204df93895SStefano Zampini else PetscCall(PetscObjectReference((PetscObject)x)); 28219566063dSJacob Faibussowitsch PetscCall(VecDuplicate(x, &f)); 28224df93895SStefano Zampini 2823a82339d0SMatthew G. Knepley /* evaluate the function at this point because SNESComputeJacobianDefault() assumes that the function has been evaluated and put into snes->vec_func */ 28249566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, x, f)); 28259566063dSJacob Faibussowitsch PetscCall(VecDestroy(&f)); 28269566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESKSPTRANSPOSEONLY, &istranspose)); 282712837594SBarry Smith while (jacobian) { 28282cd624f9SStefano Zampini Mat JT = NULL, Jsave = NULL; 28292cd624f9SStefano Zampini 28302cd624f9SStefano Zampini if (istranspose) { 28319566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(jacobian, &JT)); 28322cd624f9SStefano Zampini Jsave = jacobian; 28332cd624f9SStefano Zampini jacobian = JT; 28342cd624f9SStefano Zampini } 28359566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)jacobian, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, "")); 283612837594SBarry Smith if (flg) { 283712837594SBarry Smith A = jacobian; 28389566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 283912837594SBarry Smith } else { 28409566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(jacobian, MATAIJ, &A)); 284112837594SBarry Smith } 2842e885f1abSBarry Smith 28439566063dSJacob Faibussowitsch PetscCall(MatGetType(A, &mattype)); 28449566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &M, &N)); 28459566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &m, &n)); 28469566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B)); 28479566063dSJacob Faibussowitsch PetscCall(MatSetType(B, mattype)); 28489566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, m, n, M, N)); 28499566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(B, A, A)); 28509566063dSJacob Faibussowitsch PetscCall(MatSetUp(B)); 28519566063dSJacob Faibussowitsch PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 2852e885f1abSBarry Smith 28539566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, NULL, &functx)); 28549566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobianDefault(snes, x, B, B, functx)); 285512837594SBarry Smith 28569566063dSJacob Faibussowitsch PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &D)); 28579566063dSJacob Faibussowitsch PetscCall(MatAYPX(D, -1.0, A, DIFFERENT_NONZERO_PATTERN)); 28589566063dSJacob Faibussowitsch PetscCall(MatNorm(D, NORM_FROBENIUS, &nrm)); 28599566063dSJacob Faibussowitsch PetscCall(MatNorm(A, NORM_FROBENIUS, &gnorm)); 28609566063dSJacob Faibussowitsch PetscCall(MatDestroy(&D)); 286112837594SBarry Smith if (!gnorm) gnorm = 1; /* just in case */ 28621dfd7622SMatthew Knepley if (!silent) PetscCall(PetscViewerASCIIPrintf(viewer, " ||J - Jfd||_F/||J||_F = %g, ||J - Jfd||_F = %g\n", (double)(nrm / gnorm), (double)nrm)); 2863e885f1abSBarry Smith if (complete_print) { 28649566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded Jacobian ----------\n")); 28659566063dSJacob Faibussowitsch PetscCall(MatView(A, mviewer)); 28669566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Finite difference Jacobian ----------\n")); 28679566063dSJacob Faibussowitsch PetscCall(MatView(B, mviewer)); 2868e885f1abSBarry Smith } 2869e885f1abSBarry Smith 2870df10fb39SFande Kong if (threshold_print || complete_print) { 2871e885f1abSBarry Smith PetscInt Istart, Iend, *ccols, bncols, cncols, j, row; 2872e885f1abSBarry Smith PetscScalar *cvals; 2873e885f1abSBarry Smith const PetscInt *bcols; 2874e885f1abSBarry Smith const PetscScalar *bvals; 2875e885f1abSBarry Smith 28769566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C)); 28779566063dSJacob Faibussowitsch PetscCall(MatSetType(C, mattype)); 28789566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, m, n, M, N)); 28799566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(C, A, A)); 28809566063dSJacob Faibussowitsch PetscCall(MatSetUp(C)); 28819566063dSJacob Faibussowitsch PetscCall(MatSetOption(C, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 28820e276705SLisandro Dalcin 28839566063dSJacob Faibussowitsch PetscCall(MatAYPX(B, -1.0, A, DIFFERENT_NONZERO_PATTERN)); 28849566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(B, &Istart, &Iend)); 2885e885f1abSBarry Smith 2886e885f1abSBarry Smith for (row = Istart; row < Iend; row++) { 28879566063dSJacob Faibussowitsch PetscCall(MatGetRow(B, row, &bncols, &bcols, &bvals)); 28889566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(bncols, &ccols, bncols, &cvals)); 2889e885f1abSBarry Smith for (j = 0, cncols = 0; j < bncols; j++) { 289023a52b1dSBarry Smith if (PetscAbsScalar(bvals[j]) > threshold) { 2891e885f1abSBarry Smith ccols[cncols] = bcols[j]; 2892e885f1abSBarry Smith cvals[cncols] = bvals[j]; 2893e885f1abSBarry Smith cncols += 1; 2894e885f1abSBarry Smith } 2895e885f1abSBarry Smith } 289648a46eb9SPierre Jolivet if (cncols) PetscCall(MatSetValues(C, 1, &row, cncols, ccols, cvals, INSERT_VALUES)); 28979566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(B, row, &bncols, &bcols, &bvals)); 28989566063dSJacob Faibussowitsch PetscCall(PetscFree2(ccols, cvals)); 2899e885f1abSBarry Smith } 29009566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 29019566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 29029566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded minus finite-difference Jacobian with tolerance %g ----------\n", (double)threshold)); 29039566063dSJacob Faibussowitsch PetscCall(MatView(C, complete_print ? mviewer : viewer)); 29049566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C)); 2905e885f1abSBarry Smith } 29069566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A)); 29079566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 29089566063dSJacob Faibussowitsch PetscCall(MatDestroy(&JT)); 29092cd624f9SStefano Zampini if (Jsave) jacobian = Jsave; 291012837594SBarry Smith if (jacobian != snes->jacobian_pre) { 291112837594SBarry Smith jacobian = snes->jacobian_pre; 29121dfd7622SMatthew Knepley if (!silent) PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Jacobian for preconditioner -------------\n")); 29139371c9d4SSatish Balay } else jacobian = NULL; 291412837594SBarry Smith } 29159566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); 29161baa6e33SBarry Smith if (complete_print) PetscCall(PetscViewerPopFormat(mviewer)); 2917648c30bcSBarry Smith if (mviewer) PetscCall(PetscViewerDestroy(&mviewer)); 29189566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISetTab(viewer, tabs)); 2919cbf8f02cSMatthew G. Knepley 2920cbf8f02cSMatthew G. Knepley if (Jnorm) *Jnorm = gnorm; 2921cbf8f02cSMatthew G. Knepley if (diffNorm) *diffNorm = nrm; 29223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2923e885f1abSBarry Smith } 2924e885f1abSBarry Smith 292562fef451SLois Curfman McInnes /*@ 2926f6dfbefdSBarry Smith SNESComputeJacobian - Computes the Jacobian matrix that has been set with `SNESSetJacobian()`. 292762fef451SLois Curfman McInnes 2928c3339decSBarry Smith Collective 2929c7afd0dbSLois Curfman McInnes 293062fef451SLois Curfman McInnes Input Parameters: 2931f6dfbefdSBarry Smith + snes - the `SNES` context 2932e4094ef1SJacob Faibussowitsch - X - input vector 293362fef451SLois Curfman McInnes 293462fef451SLois Curfman McInnes Output Parameters: 2935c7afd0dbSLois Curfman McInnes + A - Jacobian matrix 2936420bcc1bSBarry Smith - B - optional matrix for building the preconditioner, usually the same as `A` 2937fee21e36SBarry Smith 2938e35cf81dSBarry Smith Options Database Keys: 293967b8a455SSatish Balay + -snes_lag_preconditioner <lag> - how often to rebuild preconditioner 294067b8a455SSatish Balay . -snes_lag_jacobian <lag> - how often to rebuild Jacobian 2941455a5933SJed Brown . -snes_test_jacobian <optional threshold> - compare the user provided Jacobian with one compute via finite differences to check for errors. If a threshold is given, display only those entries whose difference is greater than the threshold. 2942455a5933SJed Brown . -snes_test_jacobian_view - display the user provided Jacobian, the finite difference Jacobian and the difference between them to help users detect the location of errors in the user provided Jacobian 2943693365a8SJed Brown . -snes_compare_explicit - Compare the computed Jacobian to the finite difference Jacobian and output the differences 2944693365a8SJed Brown . -snes_compare_explicit_draw - Compare the computed Jacobian to the finite difference Jacobian and draw the result 2945693365a8SJed Brown . -snes_compare_explicit_contour - Compare the computed Jacobian to the finite difference Jacobian and draw a contour plot with the result 29467addb90fSBarry Smith . -snes_compare_operator - Make the comparison options above use the operator instead of the matrix used to construct the preconditioner 294794d6a431SBarry Smith . -snes_compare_coloring - Compute the finite difference Jacobian using coloring and display norms of difference 2948a5b23f4aSJose E. Roman . -snes_compare_coloring_display - Compute the finite difference Jacobian using coloring and display verbose differences 2949c01495d3SJed Brown . -snes_compare_coloring_threshold - Display only those matrix entries that differ by more than a given threshold 2950dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_atol - Absolute tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold` 2951dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_rtol - Relative tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold` 2952a5b23f4aSJose E. Roman . -snes_compare_coloring_draw - Compute the finite difference Jacobian using coloring and draw differences 2953a5b23f4aSJose E. Roman - -snes_compare_coloring_draw_contour - Compute the finite difference Jacobian using coloring and show contours of matrices and differences 2954c01495d3SJed Brown 2955dc4c0fb0SBarry Smith Level: developer 2956dc4c0fb0SBarry Smith 2957f6dfbefdSBarry Smith Note: 295862fef451SLois Curfman McInnes Most users should not need to explicitly call this routine, as it 295962fef451SLois Curfman McInnes is used internally within the nonlinear solvers. 296062fef451SLois Curfman McInnes 2961420bcc1bSBarry Smith Developer Note: 2962dc4c0fb0SBarry Smith This has duplicative ways of checking the accuracy of the user provided Jacobian (see the options above). This is for historical reasons, the routine `SNESTestJacobian()` use to used 2963420bcc1bSBarry Smith with the `SNESType` of test that has been removed. 2964e885f1abSBarry Smith 2965*76c63389SBarry Smith .seealso: [](ch_snes), `SNESSetJacobian()`, `KSPSetOperators()`, `MatStructure`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`, 2966*76c63389SBarry Smith `SNESSetJacobianDomainError()`, `SNESCheckJacobianDomainError()`, `SNESSetCheckJacobianDomainError()` 296762fef451SLois Curfman McInnes @*/ 2968d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeJacobian(SNES snes, Vec X, Mat A, Mat B) 2969d71ae5a4SJacob Faibussowitsch { 2970ace3abfcSBarry Smith PetscBool flag; 29716cab3a1bSJed Brown DM dm; 2972942e3340SBarry Smith DMSNES sdm; 2973e0e3a89bSBarry Smith KSP ksp; 29743a40ed3dSBarry Smith 29753a40ed3dSBarry Smith PetscFunctionBegin; 29760700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 29770700a824SBarry Smith PetscValidHeaderSpecific(X, VEC_CLASSID, 2); 2978c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, X, 2); 2979e0f629ddSJacob Faibussowitsch PetscCall(VecValidValues_Internal(X, 2, PETSC_TRUE)); 29809566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 29819566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 29823232da50SPeter Brune 298301c1178eSBarry Smith /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix-free */ 2984fe3ffe1eSBarry Smith if (snes->lagjacobian == -2) { 2985fe3ffe1eSBarry Smith snes->lagjacobian = -1; 2986f5af7f23SKarl Rupp 29879566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n")); 2988fe3ffe1eSBarry Smith } else if (snes->lagjacobian == -1) { 29899566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is -1\n")); 29909566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag)); 2991ebd3b9afSBarry Smith if (flag) { 29929566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 29939566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 2994ebd3b9afSBarry Smith } 29953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 299637ec4e1aSPeter Brune } else if (snes->lagjacobian > 1 && (snes->iter + snes->jac_iter) % snes->lagjacobian) { 299763a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagjacobian, snes->iter)); 29989566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag)); 2999ebd3b9afSBarry Smith if (flag) { 30009566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 30019566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 3002ebd3b9afSBarry Smith } 30033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3004e35cf81dSBarry Smith } 3005efd4aadfSBarry Smith if (snes->npc && snes->npcside == PC_LEFT) { 30069566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 30079566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 30083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3009d728fb7dSPeter Brune } 3010e35cf81dSBarry Smith 30119566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_JacobianEval, snes, X, A, B)); 30129566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(X)); 3013800f99ffSJeremy L Thompson { 3014800f99ffSJeremy L Thompson void *ctx; 30158434afd1SBarry Smith SNESJacobianFn *J; 3016800f99ffSJeremy L Thompson PetscCall(DMSNESGetJacobian(dm, &J, &ctx)); 3017800f99ffSJeremy L Thompson PetscCallBack("SNES callback Jacobian", (*J)(snes, X, A, B, ctx)); 3018800f99ffSJeremy L Thompson } 30199566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(X)); 30209566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_JacobianEval, snes, X, A, B)); 302128d58a37SPierre Jolivet 30227addb90fSBarry Smith /* attach latest linearization point to the matrix used to construct the preconditioner */ 30239566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)B, "__SNES_latest_X", (PetscObject)X)); 3024a8054027SBarry Smith 3025e0e3a89bSBarry Smith /* the next line ensures that snes->ksp exists */ 30269566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 30273b4f5425SBarry Smith if (snes->lagpreconditioner == -2) { 30289566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Rebuilding preconditioner exactly once since lag is -2\n")); 30299566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE)); 30303b4f5425SBarry Smith snes->lagpreconditioner = -1; 30313b4f5425SBarry Smith } else if (snes->lagpreconditioner == -1) { 30329566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is -1\n")); 30339566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE)); 303437ec4e1aSPeter Brune } else if (snes->lagpreconditioner > 1 && (snes->iter + snes->pre_iter) % snes->lagpreconditioner) { 303563a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagpreconditioner, snes->iter)); 30369566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE)); 3037d1e9a80fSBarry Smith } else { 30389566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Rebuilding preconditioner\n")); 30399566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE)); 3040a8054027SBarry Smith } 3041a8054027SBarry Smith 30424df93895SStefano Zampini /* monkey business to allow testing Jacobians in multilevel solvers. 30434df93895SStefano Zampini This is needed because the SNESTestXXX interface does not accept vectors and matrices */ 30444df93895SStefano Zampini { 30454df93895SStefano Zampini Vec xsave = snes->vec_sol; 30464df93895SStefano Zampini Mat jacobiansave = snes->jacobian; 30474df93895SStefano Zampini Mat jacobian_presave = snes->jacobian_pre; 30484df93895SStefano Zampini 30494df93895SStefano Zampini snes->vec_sol = X; 30504df93895SStefano Zampini snes->jacobian = A; 30514df93895SStefano Zampini snes->jacobian_pre = B; 30521dfd7622SMatthew Knepley if (snes->testFunc) PetscCall(SNESTestFunction(snes)); 30531dfd7622SMatthew Knepley if (snes->testJac) PetscCall(SNESTestJacobian(snes, NULL, NULL)); 3054494a190aSStefano Zampini 30554df93895SStefano Zampini snes->vec_sol = xsave; 30564df93895SStefano Zampini snes->jacobian = jacobiansave; 30574df93895SStefano Zampini snes->jacobian_pre = jacobian_presave; 30584df93895SStefano Zampini } 30594df93895SStefano Zampini 3060693365a8SJed Brown { 3061693365a8SJed Brown PetscBool flag = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_operator = PETSC_FALSE; 3062648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit", NULL, NULL, &flag)); 3063648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw", NULL, NULL, &flag_draw)); 3064648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw_contour", NULL, NULL, &flag_contour)); 3065648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_operator", NULL, NULL, &flag_operator)); 3066693365a8SJed Brown if (flag || flag_draw || flag_contour) { 30670298fd71SBarry Smith Mat Bexp_mine = NULL, Bexp, FDexp; 3068693365a8SJed Brown PetscViewer vdraw, vstdout; 30696b3a5b13SJed Brown PetscBool flg; 3070693365a8SJed Brown if (flag_operator) { 30719566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(A, MATAIJ, &Bexp_mine)); 3072693365a8SJed Brown Bexp = Bexp_mine; 3073693365a8SJed Brown } else { 30747addb90fSBarry Smith /* See if the matrix used to construct the preconditioner can be viewed and added directly */ 30752b2f8cc6SPierre Jolivet PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)B, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, "")); 307694ab13aaSBarry Smith if (flg) Bexp = B; 3077693365a8SJed Brown else { 3078693365a8SJed Brown /* If the "preconditioning" matrix is itself MATSHELL or some other type without direct support */ 30799566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(B, MATAIJ, &Bexp_mine)); 3080693365a8SJed Brown Bexp = Bexp_mine; 3081693365a8SJed Brown } 3082693365a8SJed Brown } 30839566063dSJacob Faibussowitsch PetscCall(MatConvert(Bexp, MATSAME, MAT_INITIAL_MATRIX, &FDexp)); 30849566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobianDefault(snes, X, FDexp, FDexp, NULL)); 30859566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout)); 3086693365a8SJed Brown if (flag_draw || flag_contour) { 30879566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Explicit Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw)); 30889566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 30890298fd71SBarry Smith } else vdraw = NULL; 30909566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit %s\n", flag_operator ? "Jacobian" : "preconditioning Jacobian")); 30919566063dSJacob Faibussowitsch if (flag) PetscCall(MatView(Bexp, vstdout)); 30929566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(Bexp, vdraw)); 30939566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Finite difference Jacobian\n")); 30949566063dSJacob Faibussowitsch if (flag) PetscCall(MatView(FDexp, vstdout)); 30959566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(FDexp, vdraw)); 30969566063dSJacob Faibussowitsch PetscCall(MatAYPX(FDexp, -1.0, Bexp, SAME_NONZERO_PATTERN)); 30979566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian\n")); 30989566063dSJacob Faibussowitsch if (flag) PetscCall(MatView(FDexp, vstdout)); 3099693365a8SJed Brown if (vdraw) { /* Always use contour for the difference */ 31009566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 31019566063dSJacob Faibussowitsch PetscCall(MatView(FDexp, vdraw)); 31029566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(vdraw)); 3103693365a8SJed Brown } 31049566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw)); 31059566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&vdraw)); 31069566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bexp_mine)); 31079566063dSJacob Faibussowitsch PetscCall(MatDestroy(&FDexp)); 3108693365a8SJed Brown } 3109693365a8SJed Brown } 31104c30e9fbSJed Brown { 31116719d8e4SJed Brown PetscBool flag = PETSC_FALSE, flag_display = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_threshold = PETSC_FALSE; 31126719d8e4SJed Brown PetscReal threshold_atol = PETSC_SQRT_MACHINE_EPSILON, threshold_rtol = 10 * PETSC_SQRT_MACHINE_EPSILON; 3113648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring", NULL, NULL, &flag)); 3114648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_display", NULL, NULL, &flag_display)); 3115648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw", NULL, NULL, &flag_draw)); 3116648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw_contour", NULL, NULL, &flag_contour)); 3117648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold", NULL, NULL, &flag_threshold)); 311827b0f280SBarry Smith if (flag_threshold) { 31199566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_rtol", &threshold_rtol, NULL)); 31209566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_atol", &threshold_atol, NULL)); 312127b0f280SBarry Smith } 31226719d8e4SJed Brown if (flag || flag_display || flag_draw || flag_contour || flag_threshold) { 31234c30e9fbSJed Brown Mat Bfd; 31244c30e9fbSJed Brown PetscViewer vdraw, vstdout; 3125335efc43SPeter Brune MatColoring coloring; 31264c30e9fbSJed Brown ISColoring iscoloring; 31274c30e9fbSJed Brown MatFDColoring matfdcoloring; 31288434afd1SBarry Smith SNESFunctionFn *func; 31294c30e9fbSJed Brown void *funcctx; 31306719d8e4SJed Brown PetscReal norm1, norm2, normmax; 31314c30e9fbSJed Brown 31329566063dSJacob Faibussowitsch PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &Bfd)); 31339566063dSJacob Faibussowitsch PetscCall(MatColoringCreate(Bfd, &coloring)); 31349566063dSJacob Faibussowitsch PetscCall(MatColoringSetType(coloring, MATCOLORINGSL)); 31359566063dSJacob Faibussowitsch PetscCall(MatColoringSetFromOptions(coloring)); 31369566063dSJacob Faibussowitsch PetscCall(MatColoringApply(coloring, &iscoloring)); 31379566063dSJacob Faibussowitsch PetscCall(MatColoringDestroy(&coloring)); 31389566063dSJacob Faibussowitsch PetscCall(MatFDColoringCreate(Bfd, iscoloring, &matfdcoloring)); 31399566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFromOptions(matfdcoloring)); 31409566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetUp(Bfd, iscoloring, matfdcoloring)); 31419566063dSJacob Faibussowitsch PetscCall(ISColoringDestroy(&iscoloring)); 31424c30e9fbSJed Brown 31434c30e9fbSJed Brown /* This method of getting the function is currently unreliable since it doesn't work for DM local functions. */ 31449566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, &func, &funcctx)); 31452ba42892SBarry Smith PetscCall(MatFDColoringSetFunction(matfdcoloring, (MatFDColoringFn *)func, funcctx)); 31469566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)matfdcoloring, ((PetscObject)snes)->prefix)); 31479566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)matfdcoloring, "coloring_")); 31489566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFromOptions(matfdcoloring)); 31499566063dSJacob Faibussowitsch PetscCall(MatFDColoringApply(Bfd, matfdcoloring, X, snes)); 31509566063dSJacob Faibussowitsch PetscCall(MatFDColoringDestroy(&matfdcoloring)); 31514c30e9fbSJed Brown 31529566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout)); 31534c30e9fbSJed Brown if (flag_draw || flag_contour) { 31549566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Colored Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw)); 31559566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 31560298fd71SBarry Smith } else vdraw = NULL; 31579566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit preconditioning Jacobian\n")); 31589566063dSJacob Faibussowitsch if (flag_display) PetscCall(MatView(B, vstdout)); 31599566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(B, vdraw)); 31609566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Colored Finite difference Jacobian\n")); 31619566063dSJacob Faibussowitsch if (flag_display) PetscCall(MatView(Bfd, vstdout)); 31629566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(Bfd, vdraw)); 31639566063dSJacob Faibussowitsch PetscCall(MatAYPX(Bfd, -1.0, B, SAME_NONZERO_PATTERN)); 31649566063dSJacob Faibussowitsch PetscCall(MatNorm(Bfd, NORM_1, &norm1)); 31659566063dSJacob Faibussowitsch PetscCall(MatNorm(Bfd, NORM_FROBENIUS, &norm2)); 31669566063dSJacob Faibussowitsch PetscCall(MatNorm(Bfd, NORM_MAX, &normmax)); 31679566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian, norm1=%g normFrob=%g normmax=%g\n", (double)norm1, (double)norm2, (double)normmax)); 31689566063dSJacob Faibussowitsch if (flag_display) PetscCall(MatView(Bfd, vstdout)); 31694c30e9fbSJed Brown if (vdraw) { /* Always use contour for the difference */ 31709566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 31719566063dSJacob Faibussowitsch PetscCall(MatView(Bfd, vdraw)); 31729566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(vdraw)); 31734c30e9fbSJed Brown } 31749566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw)); 31756719d8e4SJed Brown 31766719d8e4SJed Brown if (flag_threshold) { 31776719d8e4SJed Brown PetscInt bs, rstart, rend, i; 31789566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(B, &bs)); 31799566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(B, &rstart, &rend)); 31806719d8e4SJed Brown for (i = rstart; i < rend; i++) { 31816719d8e4SJed Brown const PetscScalar *ba, *ca; 31826719d8e4SJed Brown const PetscInt *bj, *cj; 31836719d8e4SJed Brown PetscInt bn, cn, j, maxentrycol = -1, maxdiffcol = -1, maxrdiffcol = -1; 31846719d8e4SJed Brown PetscReal maxentry = 0, maxdiff = 0, maxrdiff = 0; 31859566063dSJacob Faibussowitsch PetscCall(MatGetRow(B, i, &bn, &bj, &ba)); 31869566063dSJacob Faibussowitsch PetscCall(MatGetRow(Bfd, i, &cn, &cj, &ca)); 31875f80ce2aSJacob Faibussowitsch PetscCheck(bn == cn, ((PetscObject)A)->comm, PETSC_ERR_PLIB, "Unexpected different nonzero pattern in -snes_compare_coloring_threshold"); 31886719d8e4SJed Brown for (j = 0; j < bn; j++) { 31896719d8e4SJed Brown PetscReal rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j])); 31906719d8e4SJed Brown if (PetscAbsScalar(ba[j]) > PetscAbs(maxentry)) { 31916719d8e4SJed Brown maxentrycol = bj[j]; 31926719d8e4SJed Brown maxentry = PetscRealPart(ba[j]); 31936719d8e4SJed Brown } 31946719d8e4SJed Brown if (PetscAbsScalar(ca[j]) > PetscAbs(maxdiff)) { 31956719d8e4SJed Brown maxdiffcol = bj[j]; 31966719d8e4SJed Brown maxdiff = PetscRealPart(ca[j]); 31976719d8e4SJed Brown } 31986719d8e4SJed Brown if (rdiff > maxrdiff) { 31996719d8e4SJed Brown maxrdiffcol = bj[j]; 32006719d8e4SJed Brown maxrdiff = rdiff; 32016719d8e4SJed Brown } 32026719d8e4SJed Brown } 32036719d8e4SJed Brown if (maxrdiff > 1) { 320463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "row %" PetscInt_FMT " (maxentry=%g at %" PetscInt_FMT ", maxdiff=%g at %" PetscInt_FMT ", maxrdiff=%g at %" PetscInt_FMT "):", i, (double)maxentry, maxentrycol, (double)maxdiff, maxdiffcol, (double)maxrdiff, maxrdiffcol)); 32056719d8e4SJed Brown for (j = 0; j < bn; j++) { 32066719d8e4SJed Brown PetscReal rdiff; 32076719d8e4SJed Brown rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j])); 320848a46eb9SPierre Jolivet if (rdiff > 1) PetscCall(PetscViewerASCIIPrintf(vstdout, " (%" PetscInt_FMT ",%g:%g)", bj[j], (double)PetscRealPart(ba[j]), (double)PetscRealPart(ca[j]))); 32096719d8e4SJed Brown } 321063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "\n")); 32116719d8e4SJed Brown } 32129566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(B, i, &bn, &bj, &ba)); 32139566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(Bfd, i, &cn, &cj, &ca)); 32146719d8e4SJed Brown } 32156719d8e4SJed Brown } 32169566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&vdraw)); 32179566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bfd)); 32184c30e9fbSJed Brown } 32194c30e9fbSJed Brown } 32203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 32219b94acceSBarry Smith } 32229b94acceSBarry Smith 32239b94acceSBarry Smith /*@C 32249b94acceSBarry Smith SNESSetJacobian - Sets the function to compute Jacobian as well as the 3225044dda88SLois Curfman McInnes location to store the matrix. 32269b94acceSBarry Smith 3227c3339decSBarry Smith Logically Collective 3228c7afd0dbSLois Curfman McInnes 32299b94acceSBarry Smith Input Parameters: 3230f6dfbefdSBarry Smith + snes - the `SNES` context 3231e5d3d808SBarry Smith . Amat - the matrix that defines the (approximate) Jacobian 3232dc4c0fb0SBarry Smith . Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`. 32338434afd1SBarry Smith . J - Jacobian evaluation routine (if `NULL` then `SNES` retains any previously set value), see `SNESJacobianFn` for details 3234c7afd0dbSLois Curfman McInnes - ctx - [optional] user-defined context for private data for the 3235dc4c0fb0SBarry Smith Jacobian evaluation routine (may be `NULL`) (if `NULL` then `SNES` retains any previously set value) 3236dc4c0fb0SBarry Smith 3237dc4c0fb0SBarry Smith Level: beginner 32389b94acceSBarry Smith 32399b94acceSBarry Smith Notes: 3240dc4c0fb0SBarry Smith If the `Amat` matrix and `Pmat` matrix are different you must call `MatAssemblyBegin()`/`MatAssemblyEnd()` on 324116913363SBarry Smith each matrix. 324216913363SBarry Smith 3243dc4c0fb0SBarry Smith If you know the operator `Amat` has a null space you can use `MatSetNullSpace()` and `MatSetTransposeNullSpace()` to supply the null 3244dc4c0fb0SBarry Smith space to `Amat` and the `KSP` solvers will automatically use that null space as needed during the solution process. 3245895c21f2SBarry Smith 3246dc4c0fb0SBarry Smith If using `SNESComputeJacobianDefaultColor()` to assemble a Jacobian, the `ctx` argument 3247f6dfbefdSBarry Smith must be a `MatFDColoring`. 3248a8a26c1eSJed Brown 3249c3cc8fd1SJed Brown Other defect-correction schemes can be used by computing a different matrix in place of the Jacobian. One common 3250f6dfbefdSBarry Smith example is to use the "Picard linearization" which only differentiates through the highest order parts of each term using `SNESSetPicard()` 3251c3cc8fd1SJed Brown 32521cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSPSetOperators()`, `SNESSetFunction()`, `MatMFFDComputeJacobian()`, `SNESComputeJacobianDefaultColor()`, `MatStructure`, 32538434afd1SBarry Smith `SNESSetPicard()`, `SNESJacobianFn`, `SNESFunctionFn` 32549b94acceSBarry Smith @*/ 32558434afd1SBarry Smith PetscErrorCode SNESSetJacobian(SNES snes, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx) 3256d71ae5a4SJacob Faibussowitsch { 32576cab3a1bSJed Brown DM dm; 32583a7fca6bSBarry Smith 32593a40ed3dSBarry Smith PetscFunctionBegin; 32600700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3261e5d3d808SBarry Smith if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2); 3262e5d3d808SBarry Smith if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3); 3263e5d3d808SBarry Smith if (Amat) PetscCheckSameComm(snes, 1, Amat, 2); 3264e5d3d808SBarry Smith if (Pmat) PetscCheckSameComm(snes, 1, Pmat, 3); 32659566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 32669566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, J, ctx)); 3267e5d3d808SBarry Smith if (Amat) { 32689566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)Amat)); 32699566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian)); 3270f5af7f23SKarl Rupp 3271e5d3d808SBarry Smith snes->jacobian = Amat; 32723a7fca6bSBarry Smith } 3273e5d3d808SBarry Smith if (Pmat) { 32749566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)Pmat)); 32759566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian_pre)); 3276f5af7f23SKarl Rupp 3277e5d3d808SBarry Smith snes->jacobian_pre = Pmat; 32783a7fca6bSBarry Smith } 32793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 32809b94acceSBarry Smith } 328162fef451SLois Curfman McInnes 3282c2aafc4cSSatish Balay /*@C 3283b4fd4287SBarry Smith SNESGetJacobian - Returns the Jacobian matrix and optionally the user 3284b4fd4287SBarry Smith provided context for evaluating the Jacobian. 3285b4fd4287SBarry Smith 3286420bcc1bSBarry Smith Not Collective, but `Mat` object will be parallel if `SNES` is 3287c7afd0dbSLois Curfman McInnes 3288b4fd4287SBarry Smith Input Parameter: 3289b4fd4287SBarry Smith . snes - the nonlinear solver context 3290b4fd4287SBarry Smith 3291b4fd4287SBarry Smith Output Parameters: 3292dc4c0fb0SBarry Smith + Amat - location to stash (approximate) Jacobian matrix (or `NULL`) 3293dc4c0fb0SBarry Smith . Pmat - location to stash matrix used to compute the preconditioner (or `NULL`) 32948434afd1SBarry Smith . J - location to put Jacobian function (or `NULL`), for calling sequence see `SNESJacobianFn` 3295dc4c0fb0SBarry Smith - ctx - location to stash Jacobian ctx (or `NULL`) 3296fee21e36SBarry Smith 329736851e7fSLois Curfman McInnes Level: advanced 329836851e7fSLois Curfman McInnes 32998434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `Mat`, `SNESSetJacobian()`, `SNESComputeJacobian()`, `SNESJacobianFn`, `SNESGetFunction()` 3300b4fd4287SBarry Smith @*/ 33018434afd1SBarry Smith PetscErrorCode SNESGetJacobian(SNES snes, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx) 3302d71ae5a4SJacob Faibussowitsch { 33036cab3a1bSJed Brown DM dm; 33046cab3a1bSJed Brown 33053a40ed3dSBarry Smith PetscFunctionBegin; 33060700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3307e5d3d808SBarry Smith if (Amat) *Amat = snes->jacobian; 3308e5d3d808SBarry Smith if (Pmat) *Pmat = snes->jacobian_pre; 33099566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 3310800f99ffSJeremy L Thompson PetscCall(DMSNESGetJacobian(dm, J, ctx)); 33113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3312b4fd4287SBarry Smith } 3313b4fd4287SBarry Smith 3314d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetDefaultComputeJacobian(SNES snes) 3315d71ae5a4SJacob Faibussowitsch { 331658b371f3SBarry Smith DM dm; 331758b371f3SBarry Smith DMSNES sdm; 331858b371f3SBarry Smith 331958b371f3SBarry Smith PetscFunctionBegin; 33209566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 33219566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 332258b371f3SBarry Smith if (!sdm->ops->computejacobian && snes->jacobian_pre) { 332358b371f3SBarry Smith DM dm; 332458b371f3SBarry Smith PetscBool isdense, ismf; 332558b371f3SBarry Smith 33269566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 33279566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &isdense, MATSEQDENSE, MATMPIDENSE, MATDENSE, NULL)); 33289566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &ismf, MATMFFD, MATSHELL, NULL)); 332958b371f3SBarry Smith if (isdense) { 33309566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefault, NULL)); 333158b371f3SBarry Smith } else if (!ismf) { 33329566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefaultColor, NULL)); 333358b371f3SBarry Smith } 333458b371f3SBarry Smith } 33353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 333658b371f3SBarry Smith } 333758b371f3SBarry Smith 33389b94acceSBarry Smith /*@ 33399b94acceSBarry Smith SNESSetUp - Sets up the internal data structures for the later use 33400b4b7b1cSBarry Smith of a nonlinear solver `SNESSolve()`. 33419b94acceSBarry Smith 3342c3339decSBarry Smith Collective 3343fee21e36SBarry Smith 33442fe279fdSBarry Smith Input Parameter: 3345f6dfbefdSBarry Smith . snes - the `SNES` context 3346c7afd0dbSLois Curfman McInnes 3347dc4c0fb0SBarry Smith Level: advanced 3348dc4c0fb0SBarry Smith 3349f6dfbefdSBarry Smith Note: 33500b4b7b1cSBarry Smith For basic use of the `SNES` solvers the user does not need to explicitly call 3351f6dfbefdSBarry Smith `SNESSetUp()`, since these actions will automatically occur during 3352f6dfbefdSBarry Smith the call to `SNESSolve()`. However, if one wishes to control this 3353f6dfbefdSBarry Smith phase separately, `SNESSetUp()` should be called after `SNESCreate()` 3354f6dfbefdSBarry Smith and optional routines of the form SNESSetXXX(), but before `SNESSolve()`. 3355272ac6f2SLois Curfman McInnes 33560b4b7b1cSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`, `SNESDestroy()`, `SNESSetFromOptions()` 33579b94acceSBarry Smith @*/ 3358d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUp(SNES snes) 3359d71ae5a4SJacob Faibussowitsch { 33606cab3a1bSJed Brown DM dm; 3361942e3340SBarry Smith DMSNES sdm; 3362c35f09e5SBarry Smith SNESLineSearch linesearch, pclinesearch; 33636e2a1849SPeter Brune void *lsprectx, *lspostctx; 33649b5c1c08SStefano Zampini PetscBool mf_operator, mf; 33659b5c1c08SStefano Zampini Vec f, fpc; 33669b5c1c08SStefano Zampini void *funcctx; 33679b5c1c08SStefano Zampini void *jacctx, *appctx; 33689b5c1c08SStefano Zampini Mat j, jpre; 33696b2b7091SBarry Smith PetscErrorCode (*precheck)(SNESLineSearch, Vec, Vec, PetscBool *, void *); 33706b2b7091SBarry Smith PetscErrorCode (*postcheck)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *); 33718434afd1SBarry Smith SNESFunctionFn *func; 33728434afd1SBarry Smith SNESJacobianFn *jac; 33733a40ed3dSBarry Smith 33743a40ed3dSBarry Smith PetscFunctionBegin; 33750700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 33763ba16761SJacob Faibussowitsch if (snes->setupcalled) PetscFunctionReturn(PETSC_SUCCESS); 3377fc8bc0e3SRichard Tran Mills PetscCall(PetscLogEventBegin(SNES_SetUp, snes, 0, 0, 0)); 33789b94acceSBarry Smith 337948a46eb9SPierre Jolivet if (!((PetscObject)snes)->type_name) PetscCall(SNESSetType(snes, SNESNEWTONLS)); 338085385478SLisandro Dalcin 33819566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &snes->vec_func, NULL, NULL)); 338258c9b817SLisandro Dalcin 33839566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 33849566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 33859566063dSJacob Faibussowitsch PetscCall(SNESSetDefaultComputeJacobian(snes)); 338658b371f3SBarry Smith 338748a46eb9SPierre Jolivet if (!snes->vec_func) PetscCall(DMCreateGlobalVector(dm, &snes->vec_func)); 3388efd51863SBarry Smith 338948a46eb9SPierre Jolivet if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 3390b710008aSBarry Smith 3391d8d34be6SBarry Smith if (snes->linesearch) { 33929566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 33939566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetFunction(snes->linesearch, SNESComputeFunction)); 3394d8d34be6SBarry Smith } 33959e764e56SPeter Brune 33969b5c1c08SStefano Zampini PetscCall(SNESGetUseMatrixFree(snes, &mf_operator, &mf)); 3397b552625fSStefano Zampini if (snes->npc && snes->npcside == PC_LEFT) { 3398172a4300SPeter Brune snes->mf = PETSC_TRUE; 3399172a4300SPeter Brune snes->mf_operator = PETSC_FALSE; 3400172a4300SPeter Brune } 3401d8f46077SPeter Brune 3402efd4aadfSBarry Smith if (snes->npc) { 34036e2a1849SPeter Brune /* copy the DM over */ 34049566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 34059566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes->npc, dm)); 34066e2a1849SPeter Brune 34079566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &f, &func, &funcctx)); 34089566063dSJacob Faibussowitsch PetscCall(VecDuplicate(f, &fpc)); 34099566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes->npc, fpc, func, funcctx)); 34109566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, &j, &jpre, &jac, &jacctx)); 34119566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes->npc, j, jpre, jac, jacctx)); 34129566063dSJacob Faibussowitsch PetscCall(SNESGetApplicationContext(snes, &appctx)); 34139566063dSJacob Faibussowitsch PetscCall(SNESSetApplicationContext(snes->npc, appctx)); 34149b5c1c08SStefano Zampini PetscCall(SNESSetUseMatrixFree(snes->npc, mf_operator, mf)); 34159566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fpc)); 34166e2a1849SPeter Brune 34176e2a1849SPeter Brune /* copy the function pointers over */ 34189566063dSJacob Faibussowitsch PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)snes->npc)); 34196e2a1849SPeter Brune 34206e2a1849SPeter Brune /* default to 1 iteration */ 34219566063dSJacob Faibussowitsch PetscCall(SNESSetTolerances(snes->npc, 0.0, 0.0, 0.0, 1, snes->npc->max_funcs)); 3422efd4aadfSBarry Smith if (snes->npcside == PC_RIGHT) { 34239566063dSJacob Faibussowitsch PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_FINAL_ONLY)); 3424a9936a0cSPeter Brune } else { 34259566063dSJacob Faibussowitsch PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_NONE)); 3426a9936a0cSPeter Brune } 34279566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes->npc)); 34286e2a1849SPeter Brune 34296e2a1849SPeter Brune /* copy the line search context over */ 3430d8d34be6SBarry Smith if (snes->linesearch && snes->npc->linesearch) { 34319566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &linesearch)); 34329566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes->npc, &pclinesearch)); 34339566063dSJacob Faibussowitsch PetscCall(SNESLineSearchGetPreCheck(linesearch, &precheck, &lsprectx)); 34349566063dSJacob Faibussowitsch PetscCall(SNESLineSearchGetPostCheck(linesearch, &postcheck, &lspostctx)); 34359566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetPreCheck(pclinesearch, precheck, lsprectx)); 34369566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetPostCheck(pclinesearch, postcheck, lspostctx)); 34379566063dSJacob Faibussowitsch PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch)); 34386e2a1849SPeter Brune } 3439d8d34be6SBarry Smith } 34401baa6e33SBarry Smith if (snes->mf) PetscCall(SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version)); 3441835f2295SStefano Zampini if (snes->ops->usercompute && !snes->ctx) PetscCallBack("SNES callback compute application context", (*snes->ops->usercompute)(snes, &snes->ctx)); 34426e2a1849SPeter Brune 344337ec4e1aSPeter Brune snes->jac_iter = 0; 344437ec4e1aSPeter Brune snes->pre_iter = 0; 344537ec4e1aSPeter Brune 3446dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, setup); 344758c9b817SLisandro Dalcin 34489566063dSJacob Faibussowitsch PetscCall(SNESSetDefaultComputeJacobian(snes)); 344958b371f3SBarry Smith 3450b552625fSStefano Zampini if (snes->npc && snes->npcside == PC_LEFT) { 34516c67d002SPeter Brune if (snes->functype == SNES_FUNCTION_PRECONDITIONED) { 3452d8d34be6SBarry Smith if (snes->linesearch) { 34539566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &linesearch)); 34549566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunctionDefaultNPC)); 34556c67d002SPeter Brune } 34566c67d002SPeter Brune } 3457d8d34be6SBarry Smith } 3458fc8bc0e3SRichard Tran Mills PetscCall(PetscLogEventEnd(SNES_SetUp, snes, 0, 0, 0)); 34597aaed0d8SBarry Smith snes->setupcalled = PETSC_TRUE; 34603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 34619b94acceSBarry Smith } 34629b94acceSBarry Smith 346337596af1SLisandro Dalcin /*@ 34640b4b7b1cSBarry Smith SNESReset - Resets a `SNES` context to the state it was in before `SNESSetUp()` was called and removes any allocated `Vec` and `Mat` from its data structures 346537596af1SLisandro Dalcin 3466c3339decSBarry Smith Collective 346737596af1SLisandro Dalcin 346837596af1SLisandro Dalcin Input Parameter: 34690b4b7b1cSBarry Smith . snes - the nonlinear iterative solver context obtained from `SNESCreate()` 347037596af1SLisandro Dalcin 3471d25893d9SBarry Smith Level: intermediate 3472d25893d9SBarry Smith 347395452b02SPatrick Sanan Notes: 34740b4b7b1cSBarry Smith Any options set on the `SNES` object, including those set with `SNESSetFromOptions()` remain. 34750b4b7b1cSBarry Smith 3476f6dfbefdSBarry Smith Call this if you wish to reuse a `SNES` but with different size vectors 347737596af1SLisandro Dalcin 3478f6dfbefdSBarry Smith Also calls the application context destroy routine set with `SNESSetComputeApplicationContext()` 3479f6dfbefdSBarry Smith 34801cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESDestroy()`, `SNESCreate()`, `SNESSetUp()`, `SNESSolve()` 348137596af1SLisandro Dalcin @*/ 3482d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESReset(SNES snes) 3483d71ae5a4SJacob Faibussowitsch { 348437596af1SLisandro Dalcin PetscFunctionBegin; 348537596af1SLisandro Dalcin PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 348649abdd8aSBarry Smith if (snes->ops->ctxdestroy && snes->ctx) { 3487835f2295SStefano Zampini PetscCallBack("SNES callback destroy application context", (*snes->ops->ctxdestroy)(&snes->ctx)); 348849abdd8aSBarry Smith snes->ctx = NULL; 3489d25893d9SBarry Smith } 34901baa6e33SBarry Smith if (snes->npc) PetscCall(SNESReset(snes->npc)); 34918a23116dSBarry Smith 3492dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, reset); 34931baa6e33SBarry Smith if (snes->ksp) PetscCall(KSPReset(snes->ksp)); 34949e764e56SPeter Brune 34951baa6e33SBarry Smith if (snes->linesearch) PetscCall(SNESLineSearchReset(snes->linesearch)); 34969e764e56SPeter Brune 34979566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_rhs)); 34989566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol)); 34999566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol_update)); 35009566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_func)); 35019566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian)); 35029566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian_pre)); 35039566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->picard)); 35049566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(snes->nwork, &snes->work)); 35059566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(snes->nvwork, &snes->vwork)); 3506f5af7f23SKarl Rupp 350740fdac6aSLawrence Mitchell snes->alwayscomputesfinalresidual = PETSC_FALSE; 350840fdac6aSLawrence Mitchell 350937596af1SLisandro Dalcin snes->nwork = snes->nvwork = 0; 351037596af1SLisandro Dalcin snes->setupcalled = PETSC_FALSE; 35113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 351237596af1SLisandro Dalcin } 351337596af1SLisandro Dalcin 351452baeb72SSatish Balay /*@ 351536d43d94SBarry Smith SNESConvergedReasonViewCancel - Clears all the reason view functions for a `SNES` object provided with `SNESConvergedReasonViewSet()` also 351636d43d94SBarry Smith removes the default viewer. 3517c4421ceaSFande Kong 3518c3339decSBarry Smith Collective 3519c4421ceaSFande Kong 3520c4421ceaSFande Kong Input Parameter: 35210b4b7b1cSBarry Smith . snes - the nonlinear iterative solver context obtained from `SNESCreate()` 3522c4421ceaSFande Kong 3523c4421ceaSFande Kong Level: intermediate 3524c4421ceaSFande Kong 3525420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESReset()`, `SNESConvergedReasonViewSet()` 3526c4421ceaSFande Kong @*/ 3527d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewCancel(SNES snes) 3528d71ae5a4SJacob Faibussowitsch { 3529c4421ceaSFande Kong PetscInt i; 3530c4421ceaSFande Kong 3531c4421ceaSFande Kong PetscFunctionBegin; 3532c4421ceaSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3533c4421ceaSFande Kong for (i = 0; i < snes->numberreasonviews; i++) { 353448a46eb9SPierre Jolivet if (snes->reasonviewdestroy[i]) PetscCall((*snes->reasonviewdestroy[i])(&snes->reasonviewcontext[i])); 3535c4421ceaSFande Kong } 3536c4421ceaSFande Kong snes->numberreasonviews = 0; 3537648c30bcSBarry Smith PetscCall(PetscViewerDestroy(&snes->convergedreasonviewer)); 35383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3539c4421ceaSFande Kong } 3540c4421ceaSFande Kong 35410764c050SBarry Smith /*@ 35429b94acceSBarry Smith SNESDestroy - Destroys the nonlinear solver context that was created 3543f6dfbefdSBarry Smith with `SNESCreate()`. 35449b94acceSBarry Smith 3545c3339decSBarry Smith Collective 3546c7afd0dbSLois Curfman McInnes 35479b94acceSBarry Smith Input Parameter: 3548f6dfbefdSBarry Smith . snes - the `SNES` context 35499b94acceSBarry Smith 355036851e7fSLois Curfman McInnes Level: beginner 355136851e7fSLois Curfman McInnes 35521cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()` 35539b94acceSBarry Smith @*/ 3554d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESDestroy(SNES *snes) 3555d71ae5a4SJacob Faibussowitsch { 355692e852f7SPablo Brubeck DM dm; 355792e852f7SPablo Brubeck 35583a40ed3dSBarry Smith PetscFunctionBegin; 35593ba16761SJacob Faibussowitsch if (!*snes) PetscFunctionReturn(PETSC_SUCCESS); 3560f4f49eeaSPierre Jolivet PetscValidHeaderSpecific(*snes, SNES_CLASSID, 1); 3561f4f49eeaSPierre Jolivet if (--((PetscObject)*snes)->refct > 0) { 35629371c9d4SSatish Balay *snes = NULL; 35633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 35649371c9d4SSatish Balay } 3565d4bb536fSBarry Smith 3566f4f49eeaSPierre Jolivet PetscCall(SNESReset(*snes)); 35679566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&(*snes)->npc)); 35686b8b9a38SLisandro Dalcin 3569e04113cfSBarry Smith /* if memory was published with SAWs then destroy it */ 35709566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsViewOff((PetscObject)*snes)); 3571f4f49eeaSPierre Jolivet PetscTryTypeMethod(*snes, destroy); 35726d4c513bSLisandro Dalcin 357392e852f7SPablo Brubeck dm = (*snes)->dm; 357492e852f7SPablo Brubeck while (dm) { 357592e852f7SPablo Brubeck PetscCall(DMCoarsenHookRemove(dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, *snes)); 357692e852f7SPablo Brubeck PetscCall(DMGetCoarseDM(dm, &dm)); 357792e852f7SPablo Brubeck } 357892e852f7SPablo Brubeck 35799566063dSJacob Faibussowitsch PetscCall(DMDestroy(&(*snes)->dm)); 35809566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&(*snes)->ksp)); 35819566063dSJacob Faibussowitsch PetscCall(SNESLineSearchDestroy(&(*snes)->linesearch)); 35826b8b9a38SLisandro Dalcin 35839566063dSJacob Faibussowitsch PetscCall(PetscFree((*snes)->kspconvctx)); 358412651944SBarry Smith if ((*snes)->ops->convergeddestroy) PetscCall((*(*snes)->ops->convergeddestroy)(&(*snes)->cnvP)); 358548a46eb9SPierre Jolivet if ((*snes)->conv_hist_alloc) PetscCall(PetscFree2((*snes)->conv_hist, (*snes)->conv_hist_its)); 3586f4f49eeaSPierre Jolivet PetscCall(SNESMonitorCancel(*snes)); 3587f4f49eeaSPierre Jolivet PetscCall(SNESConvergedReasonViewCancel(*snes)); 35889566063dSJacob Faibussowitsch PetscCall(PetscHeaderDestroy(snes)); 35893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 35909b94acceSBarry Smith } 35919b94acceSBarry Smith 35929b94acceSBarry Smith /* ----------- Routines to set solver parameters ---------- */ 35939b94acceSBarry Smith 3594a8054027SBarry Smith /*@ 35950b4b7b1cSBarry Smith SNESSetLagPreconditioner - Sets when the preconditioner is rebuilt in the nonlinear solve `SNESSolve()`. 3596a8054027SBarry Smith 3597c3339decSBarry Smith Logically Collective 3598a8054027SBarry Smith 3599a8054027SBarry Smith Input Parameters: 3600f6dfbefdSBarry Smith + snes - the `SNES` context 3601d8e291bfSBarry Smith - lag - 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time 36023b4f5425SBarry Smith the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that 3603a8054027SBarry Smith 3604a8054027SBarry Smith Options Database Keys: 3605420bcc1bSBarry Smith + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple `SNESSolve()` 36063d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 3607420bcc1bSBarry Smith . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple `SNESSolve()` 36083d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 3609a8054027SBarry Smith 3610dc4c0fb0SBarry Smith Level: intermediate 3611dc4c0fb0SBarry Smith 3612420bcc1bSBarry Smith Notes: 3613a8054027SBarry Smith The default is 1 3614420bcc1bSBarry Smith 3615f6dfbefdSBarry Smith The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagPreconditionerPersists()` was called 3616d8e291bfSBarry Smith 3617f6dfbefdSBarry Smith `SNESSetLagPreconditionerPersists()` allows using the same uniform lagging (for example every second linear solve) across multiple nonlinear solves. 3618a8054027SBarry Smith 36193201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetLagPreconditionerPersists()`, 3620f6dfbefdSBarry Smith `SNESSetLagJacobianPersists()`, `SNES`, `SNESSolve()` 3621a8054027SBarry Smith @*/ 3622d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditioner(SNES snes, PetscInt lag) 3623d71ae5a4SJacob Faibussowitsch { 3624a8054027SBarry Smith PetscFunctionBegin; 36250700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 36265f80ce2aSJacob Faibussowitsch PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater"); 36275f80ce2aSJacob Faibussowitsch PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0"); 3628c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, lag, 2); 3629a8054027SBarry Smith snes->lagpreconditioner = lag; 36303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3631a8054027SBarry Smith } 3632a8054027SBarry Smith 3633efd51863SBarry Smith /*@ 3634f6dfbefdSBarry Smith SNESSetGridSequence - sets the number of steps of grid sequencing that `SNES` will do 3635efd51863SBarry Smith 3636c3339decSBarry Smith Logically Collective 3637efd51863SBarry Smith 3638efd51863SBarry Smith Input Parameters: 3639f6dfbefdSBarry Smith + snes - the `SNES` context 3640efd51863SBarry Smith - steps - the number of refinements to do, defaults to 0 3641efd51863SBarry Smith 3642f6dfbefdSBarry Smith Options Database Key: 364367b8a455SSatish Balay . -snes_grid_sequence <steps> - Use grid sequencing to generate initial guess 3644efd51863SBarry Smith 3645efd51863SBarry Smith Level: intermediate 3646efd51863SBarry Smith 36470b4b7b1cSBarry Smith Notes: 36480b4b7b1cSBarry Smith Once grid sequencing is turned on `SNESSolve()` will automatically perform the solve on each grid refinement. 36490b4b7b1cSBarry Smith 3650f6dfbefdSBarry Smith Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing. 3651c0df2a02SJed Brown 36523201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetGridSequence()`, 365354c05997SPierre Jolivet `SNESSetDM()`, `SNESSolve()` 3654efd51863SBarry Smith @*/ 3655d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetGridSequence(SNES snes, PetscInt steps) 3656d71ae5a4SJacob Faibussowitsch { 3657efd51863SBarry Smith PetscFunctionBegin; 3658efd51863SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3659efd51863SBarry Smith PetscValidLogicalCollectiveInt(snes, steps, 2); 3660efd51863SBarry Smith snes->gridsequence = steps; 36613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3662efd51863SBarry Smith } 3663efd51863SBarry Smith 3664fa19ca70SBarry Smith /*@ 3665f6dfbefdSBarry Smith SNESGetGridSequence - gets the number of steps of grid sequencing that `SNES` will do 3666fa19ca70SBarry Smith 3667c3339decSBarry Smith Logically Collective 3668fa19ca70SBarry Smith 3669fa19ca70SBarry Smith Input Parameter: 3670f6dfbefdSBarry Smith . snes - the `SNES` context 3671fa19ca70SBarry Smith 3672fa19ca70SBarry Smith Output Parameter: 3673fa19ca70SBarry Smith . steps - the number of refinements to do, defaults to 0 3674fa19ca70SBarry Smith 3675fa19ca70SBarry Smith Level: intermediate 3676fa19ca70SBarry Smith 36773201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetGridSequence()` 3678fa19ca70SBarry Smith @*/ 3679d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetGridSequence(SNES snes, PetscInt *steps) 3680d71ae5a4SJacob Faibussowitsch { 3681fa19ca70SBarry Smith PetscFunctionBegin; 3682fa19ca70SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3683fa19ca70SBarry Smith *steps = snes->gridsequence; 36843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3685fa19ca70SBarry Smith } 3686fa19ca70SBarry Smith 3687a8054027SBarry Smith /*@ 3688f6dfbefdSBarry Smith SNESGetLagPreconditioner - Return how often the preconditioner is rebuilt 3689a8054027SBarry Smith 36903f9fe445SBarry Smith Not Collective 3691a8054027SBarry Smith 3692a8054027SBarry Smith Input Parameter: 3693f6dfbefdSBarry Smith . snes - the `SNES` context 3694a8054027SBarry Smith 3695a8054027SBarry Smith Output Parameter: 3696a8054027SBarry Smith . lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time 36973b4f5425SBarry Smith the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that 3698a8054027SBarry Smith 3699dc4c0fb0SBarry Smith Level: intermediate 3700dc4c0fb0SBarry Smith 3701a8054027SBarry Smith Notes: 3702a8054027SBarry Smith The default is 1 3703f6dfbefdSBarry Smith 3704a8054027SBarry Smith The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 3705a8054027SBarry Smith 37063201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3707a8054027SBarry Smith @*/ 3708d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagPreconditioner(SNES snes, PetscInt *lag) 3709d71ae5a4SJacob Faibussowitsch { 3710a8054027SBarry Smith PetscFunctionBegin; 37110700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3712a8054027SBarry Smith *lag = snes->lagpreconditioner; 37133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3714a8054027SBarry Smith } 3715a8054027SBarry Smith 3716e35cf81dSBarry Smith /*@ 3717f6dfbefdSBarry Smith SNESSetLagJacobian - Set when the Jacobian is rebuilt in the nonlinear solve. See `SNESSetLagPreconditioner()` for determining how 3718e35cf81dSBarry Smith often the preconditioner is rebuilt. 3719e35cf81dSBarry Smith 3720c3339decSBarry Smith Logically Collective 3721e35cf81dSBarry Smith 3722e35cf81dSBarry Smith Input Parameters: 3723f6dfbefdSBarry Smith + snes - the `SNES` context 3724e35cf81dSBarry Smith - lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time 3725fe3ffe1eSBarry Smith the Jacobian is built etc. -2 means rebuild at next chance but then never again 3726e35cf81dSBarry Smith 3727e35cf81dSBarry Smith Options Database Keys: 372879a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 37293d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 373079a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 37313d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag. 3732e35cf81dSBarry Smith 3733dc4c0fb0SBarry Smith Level: intermediate 3734dc4c0fb0SBarry Smith 3735e35cf81dSBarry Smith Notes: 3736e35cf81dSBarry Smith The default is 1 3737f6dfbefdSBarry Smith 3738e35cf81dSBarry Smith The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 3739f6dfbefdSBarry Smith 3740fe3ffe1eSBarry Smith If -1 is used before the very first nonlinear solve the CODE WILL FAIL! because no Jacobian is used, use -2 to indicate you want it recomputed 3741fe3ffe1eSBarry Smith at the next Newton step but never again (unless it is reset to another value) 3742e35cf81dSBarry Smith 37433201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagPreconditioner()`, `SNESGetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3744e35cf81dSBarry Smith @*/ 3745d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobian(SNES snes, PetscInt lag) 3746d71ae5a4SJacob Faibussowitsch { 3747e35cf81dSBarry Smith PetscFunctionBegin; 37480700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 37495f80ce2aSJacob Faibussowitsch PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater"); 37505f80ce2aSJacob Faibussowitsch PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0"); 3751c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, lag, 2); 3752e35cf81dSBarry Smith snes->lagjacobian = lag; 37533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3754e35cf81dSBarry Smith } 3755e35cf81dSBarry Smith 3756e35cf81dSBarry Smith /*@ 3757f6dfbefdSBarry Smith SNESGetLagJacobian - Get how often the Jacobian is rebuilt. See `SNESGetLagPreconditioner()` to determine when the preconditioner is rebuilt 3758e35cf81dSBarry Smith 37593f9fe445SBarry Smith Not Collective 3760e35cf81dSBarry Smith 3761e35cf81dSBarry Smith Input Parameter: 3762f6dfbefdSBarry Smith . snes - the `SNES` context 3763e35cf81dSBarry Smith 3764e35cf81dSBarry Smith Output Parameter: 3765e35cf81dSBarry Smith . lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time 3766e35cf81dSBarry Smith the Jacobian is built etc. 3767e35cf81dSBarry Smith 3768dc4c0fb0SBarry Smith Level: intermediate 3769dc4c0fb0SBarry Smith 3770e35cf81dSBarry Smith Notes: 3771e35cf81dSBarry Smith The default is 1 3772f6dfbefdSBarry Smith 3773f6dfbefdSBarry Smith The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagJacobianPersists()` was called. 3774e35cf81dSBarry Smith 37753201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobian()`, `SNESSetLagPreconditioner()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3776e35cf81dSBarry Smith 3777e35cf81dSBarry Smith @*/ 3778d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagJacobian(SNES snes, PetscInt *lag) 3779d71ae5a4SJacob Faibussowitsch { 3780e35cf81dSBarry Smith PetscFunctionBegin; 37810700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3782e35cf81dSBarry Smith *lag = snes->lagjacobian; 37833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3784e35cf81dSBarry Smith } 3785e35cf81dSBarry Smith 378637ec4e1aSPeter Brune /*@ 3787f6dfbefdSBarry Smith SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple nonlinear solves 378837ec4e1aSPeter Brune 3789c3339decSBarry Smith Logically collective 379037ec4e1aSPeter Brune 3791d8d19677SJose E. Roman Input Parameters: 3792f6dfbefdSBarry Smith + snes - the `SNES` context 37939d7e2deaSPeter Brune - flg - jacobian lagging persists if true 379437ec4e1aSPeter Brune 379537ec4e1aSPeter Brune Options Database Keys: 379679a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 37973d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 379879a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 37993d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 38003d5a8a6aSBarry Smith 3801dc4c0fb0SBarry Smith Level: advanced 3802dc4c0fb0SBarry Smith 380395452b02SPatrick Sanan Notes: 3804420bcc1bSBarry Smith Normally when `SNESSetLagJacobian()` is used, the Jacobian is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior 3805f6dfbefdSBarry Smith 380695452b02SPatrick Sanan This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by 380737ec4e1aSPeter Brune several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several 380837ec4e1aSPeter Brune timesteps may present huge efficiency gains. 380937ec4e1aSPeter Brune 381042747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditionerPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()` 381137ec4e1aSPeter Brune @*/ 3812d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobianPersists(SNES snes, PetscBool flg) 3813d71ae5a4SJacob Faibussowitsch { 381437ec4e1aSPeter Brune PetscFunctionBegin; 381537ec4e1aSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 381637ec4e1aSPeter Brune PetscValidLogicalCollectiveBool(snes, flg, 2); 381737ec4e1aSPeter Brune snes->lagjac_persist = flg; 38183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 381937ec4e1aSPeter Brune } 382037ec4e1aSPeter Brune 382137ec4e1aSPeter Brune /*@ 3822d8e291bfSBarry Smith SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple nonlinear solves 382337ec4e1aSPeter Brune 3824c3339decSBarry Smith Logically Collective 382537ec4e1aSPeter Brune 3826d8d19677SJose E. Roman Input Parameters: 3827f6dfbefdSBarry Smith + snes - the `SNES` context 38289d7e2deaSPeter Brune - flg - preconditioner lagging persists if true 382937ec4e1aSPeter Brune 383037ec4e1aSPeter Brune Options Database Keys: 383179a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 38323d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 383379a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 38343d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 383537ec4e1aSPeter Brune 3836dc4c0fb0SBarry Smith Level: developer 3837dc4c0fb0SBarry Smith 383895452b02SPatrick Sanan Notes: 3839420bcc1bSBarry Smith Normally when `SNESSetLagPreconditioner()` is used, the preconditioner is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior 3840f6dfbefdSBarry Smith 384195452b02SPatrick Sanan This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale 384237ec4e1aSPeter Brune by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over 384337ec4e1aSPeter Brune several timesteps may present huge efficiency gains. 384437ec4e1aSPeter Brune 38451cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobianPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagPreconditioner()` 384637ec4e1aSPeter Brune @*/ 3847d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes, PetscBool flg) 3848d71ae5a4SJacob Faibussowitsch { 384937ec4e1aSPeter Brune PetscFunctionBegin; 385037ec4e1aSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 385137ec4e1aSPeter Brune PetscValidLogicalCollectiveBool(snes, flg, 2); 385237ec4e1aSPeter Brune snes->lagpre_persist = flg; 38533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 385437ec4e1aSPeter Brune } 385537ec4e1aSPeter Brune 38569b94acceSBarry Smith /*@ 3857f6dfbefdSBarry Smith SNESSetForceIteration - force `SNESSolve()` to take at least one iteration regardless of the initial residual norm 3858be5caee7SBarry Smith 3859c3339decSBarry Smith Logically Collective 3860be5caee7SBarry Smith 3861be5caee7SBarry Smith Input Parameters: 3862f6dfbefdSBarry Smith + snes - the `SNES` context 3863f6dfbefdSBarry Smith - force - `PETSC_TRUE` require at least one iteration 3864be5caee7SBarry Smith 3865f6dfbefdSBarry Smith Options Database Key: 3866be5caee7SBarry Smith . -snes_force_iteration <force> - Sets forcing an iteration 3867be5caee7SBarry Smith 3868dc4c0fb0SBarry Smith Level: intermediate 3869dc4c0fb0SBarry Smith 3870f6dfbefdSBarry Smith Note: 3871f6dfbefdSBarry Smith This is used sometimes with `TS` to prevent `TS` from detecting a false steady state solution 3872be5caee7SBarry Smith 38733201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `TS`, `SNESSetDivergenceTolerance()` 3874be5caee7SBarry Smith @*/ 3875d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetForceIteration(SNES snes, PetscBool force) 3876d71ae5a4SJacob Faibussowitsch { 3877be5caee7SBarry Smith PetscFunctionBegin; 3878be5caee7SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3879be5caee7SBarry Smith snes->forceiteration = force; 38803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3881be5caee7SBarry Smith } 3882be5caee7SBarry Smith 388385216dc7SFande Kong /*@ 3884f6dfbefdSBarry Smith SNESGetForceIteration - Check whether or not `SNESSolve()` take at least one iteration regardless of the initial residual norm 388585216dc7SFande Kong 3886c3339decSBarry Smith Logically Collective 388785216dc7SFande Kong 38882fe279fdSBarry Smith Input Parameter: 3889f6dfbefdSBarry Smith . snes - the `SNES` context 389085216dc7SFande Kong 389185216dc7SFande Kong Output Parameter: 3892dc4c0fb0SBarry Smith . force - `PETSC_TRUE` requires at least one iteration. 389385216dc7SFande Kong 389406dd6b0eSSatish Balay Level: intermediate 389506dd6b0eSSatish Balay 38963201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetForceIteration()`, `SNESSetDivergenceTolerance()` 389785216dc7SFande Kong @*/ 3898d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetForceIteration(SNES snes, PetscBool *force) 3899d71ae5a4SJacob Faibussowitsch { 390085216dc7SFande Kong PetscFunctionBegin; 390185216dc7SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 390285216dc7SFande Kong *force = snes->forceiteration; 39033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 390485216dc7SFande Kong } 3905be5caee7SBarry Smith 3906be5caee7SBarry Smith /*@ 39070b4b7b1cSBarry Smith SNESSetTolerances - Sets various parameters used in `SNES` convergence tests. 39089b94acceSBarry Smith 3909c3339decSBarry Smith Logically Collective 3910c7afd0dbSLois Curfman McInnes 39119b94acceSBarry Smith Input Parameters: 3912f6dfbefdSBarry Smith + snes - the `SNES` context 39130b4b7b1cSBarry Smith . abstol - the absolute convergence tolerance, $ F(x^n) \le abstol $ 39140b4b7b1cSBarry Smith . rtol - the relative convergence tolerance, $ F(x^n) \le reltol * F(x^0) $ 39155358d0d4SBarry Smith . stol - convergence tolerance in terms of the norm of the change in the solution between steps, || delta x || < stol*|| x || 39160b4b7b1cSBarry Smith . maxit - the maximum number of iterations allowed in the solver, default 50. 39170b4b7b1cSBarry Smith - maxf - the maximum number of function evaluations allowed in the solver (use `PETSC_UNLIMITED` indicates no limit), default 10,000 3918fee21e36SBarry Smith 391933174efeSLois Curfman McInnes Options Database Keys: 392077e5a1f9SBarry Smith + -snes_atol <abstol> - Sets `abstol` 392177e5a1f9SBarry Smith . -snes_rtol <rtol> - Sets `rtol` 392277e5a1f9SBarry Smith . -snes_stol <stol> - Sets `stol` 392377e5a1f9SBarry Smith . -snes_max_it <maxit> - Sets `maxit` 392477e5a1f9SBarry Smith - -snes_max_funcs <maxf> - Sets `maxf` (use `unlimited` to have no maximum) 39259b94acceSBarry Smith 392636851e7fSLois Curfman McInnes Level: intermediate 392736851e7fSLois Curfman McInnes 392877e5a1f9SBarry Smith Note: 392977e5a1f9SBarry Smith All parameters must be non-negative 393077e5a1f9SBarry Smith 393177e5a1f9SBarry Smith Use `PETSC_CURRENT` to retain the current value of any parameter and `PETSC_DETERMINE` to use the default value for the given `SNES`. 393277e5a1f9SBarry Smith The default value is the value in the object when its type is set. 393377e5a1f9SBarry Smith 393477e5a1f9SBarry Smith Use `PETSC_UNLIMITED` on `maxit` or `maxf` to indicate there is no bound on the number of iterations or number of function evaluations. 393577e5a1f9SBarry Smith 393677e5a1f9SBarry Smith Fortran Note: 393777e5a1f9SBarry Smith Use `PETSC_CURRENT_INTEGER`, `PETSC_CURRENT_REAL`, `PETSC_UNLIMITED_INTEGER`, `PETSC_DETERMINE_INTEGER`, or `PETSC_DETERMINE_REAL` 393877e5a1f9SBarry Smith 39393201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESSolve()`, `SNES`, `SNESSetDivergenceTolerance()`, `SNESSetForceIteration()` 39409b94acceSBarry Smith @*/ 3941d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTolerances(SNES snes, PetscReal abstol, PetscReal rtol, PetscReal stol, PetscInt maxit, PetscInt maxf) 3942d71ae5a4SJacob Faibussowitsch { 39433a40ed3dSBarry Smith PetscFunctionBegin; 39440700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3945c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, abstol, 2); 3946c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, rtol, 3); 3947c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, stol, 4); 3948c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, maxit, 5); 3949c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, maxf, 6); 3950c5eb9154SBarry Smith 395177e5a1f9SBarry Smith if (abstol == (PetscReal)PETSC_DETERMINE) { 395277e5a1f9SBarry Smith snes->abstol = snes->default_abstol; 395377e5a1f9SBarry Smith } else if (abstol != (PetscReal)PETSC_CURRENT) { 39545f80ce2aSJacob Faibussowitsch PetscCheck(abstol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)abstol); 3955ab54825eSJed Brown snes->abstol = abstol; 3956ab54825eSJed Brown } 395777e5a1f9SBarry Smith 395877e5a1f9SBarry Smith if (rtol == (PetscReal)PETSC_DETERMINE) { 395977e5a1f9SBarry Smith snes->rtol = snes->default_rtol; 396077e5a1f9SBarry Smith } else if (rtol != (PetscReal)PETSC_CURRENT) { 39615f80ce2aSJacob Faibussowitsch PetscCheck(rtol >= 0.0 && 1.0 > rtol, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Relative tolerance %g must be non-negative and less than 1.0", (double)rtol); 3962ab54825eSJed Brown snes->rtol = rtol; 3963ab54825eSJed Brown } 396477e5a1f9SBarry Smith 396577e5a1f9SBarry Smith if (stol == (PetscReal)PETSC_DETERMINE) { 396677e5a1f9SBarry Smith snes->stol = snes->default_stol; 396777e5a1f9SBarry Smith } else if (stol != (PetscReal)PETSC_CURRENT) { 39685f80ce2aSJacob Faibussowitsch PetscCheck(stol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Step tolerance %g must be non-negative", (double)stol); 3969c60f73f4SPeter Brune snes->stol = stol; 3970ab54825eSJed Brown } 397177e5a1f9SBarry Smith 3972835f2295SStefano Zampini if (maxit == PETSC_DETERMINE) { 397377e5a1f9SBarry Smith snes->max_its = snes->default_max_its; 3974835f2295SStefano Zampini } else if (maxit == PETSC_UNLIMITED) { 397577e5a1f9SBarry Smith snes->max_its = PETSC_INT_MAX; 397677e5a1f9SBarry Smith } else if (maxit != PETSC_CURRENT) { 397763a3b9bcSJacob Faibussowitsch PetscCheck(maxit >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", maxit); 3978ab54825eSJed Brown snes->max_its = maxit; 3979ab54825eSJed Brown } 398077e5a1f9SBarry Smith 3981835f2295SStefano Zampini if (maxf == PETSC_DETERMINE) { 398277e5a1f9SBarry Smith snes->max_funcs = snes->default_max_funcs; 3983835f2295SStefano Zampini } else if (maxf == PETSC_UNLIMITED || maxf == -1) { 398477e5a1f9SBarry Smith snes->max_funcs = PETSC_UNLIMITED; 398577e5a1f9SBarry Smith } else if (maxf != PETSC_CURRENT) { 398677e5a1f9SBarry Smith PetscCheck(maxf >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations %" PetscInt_FMT " must be nonnegative", maxf); 3987ab54825eSJed Brown snes->max_funcs = maxf; 3988ab54825eSJed Brown } 39893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 39909b94acceSBarry Smith } 39919b94acceSBarry Smith 3992e4d06f11SPatrick Farrell /*@ 3993f6dfbefdSBarry Smith SNESSetDivergenceTolerance - Sets the divergence tolerance used for the `SNES` divergence test. 3994e4d06f11SPatrick Farrell 3995c3339decSBarry Smith Logically Collective 3996e4d06f11SPatrick Farrell 3997e4d06f11SPatrick Farrell Input Parameters: 3998f6dfbefdSBarry Smith + snes - the `SNES` context 39990b4b7b1cSBarry Smith - divtol - the divergence tolerance. Use `PETSC_UNLIMITED` to deactivate the test. If the residual norm $ F(x^n) \ge divtol * F(x^0) $ the solver 40000b4b7b1cSBarry Smith is stopped due to divergence. 4001e4d06f11SPatrick Farrell 4002f6dfbefdSBarry Smith Options Database Key: 4003dc4c0fb0SBarry Smith . -snes_divergence_tolerance <divtol> - Sets `divtol` 4004e4d06f11SPatrick Farrell 4005e4d06f11SPatrick Farrell Level: intermediate 4006e4d06f11SPatrick Farrell 400777e5a1f9SBarry Smith Notes: 400877e5a1f9SBarry Smith Use `PETSC_DETERMINE` to use the default value from when the object's type was set. 4009e5cd489fSStefano Zampini 401077e5a1f9SBarry Smith Fortran Note: 401177e5a1f9SBarry Smith Use ``PETSC_DETERMINE_REAL` or `PETSC_UNLIMITED_REAL` 401277e5a1f9SBarry Smith 401377e5a1f9SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetTolerances()`, `SNESGetDivergenceTolerance()` 4014e4d06f11SPatrick Farrell @*/ 4015d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDivergenceTolerance(SNES snes, PetscReal divtol) 4016d71ae5a4SJacob Faibussowitsch { 4017e4d06f11SPatrick Farrell PetscFunctionBegin; 4018e4d06f11SPatrick Farrell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4019e4d06f11SPatrick Farrell PetscValidLogicalCollectiveReal(snes, divtol, 2); 402077e5a1f9SBarry Smith 402177e5a1f9SBarry Smith if (divtol == (PetscReal)PETSC_DETERMINE) { 402277e5a1f9SBarry Smith snes->divtol = snes->default_divtol; 402377e5a1f9SBarry Smith } else if (divtol == (PetscReal)PETSC_UNLIMITED || divtol == -1) { 402477e5a1f9SBarry Smith snes->divtol = PETSC_UNLIMITED; 402577e5a1f9SBarry Smith } else if (divtol != (PetscReal)PETSC_CURRENT) { 402677e5a1f9SBarry Smith PetscCheck(divtol >= 1.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Divergence tolerance %g must be greater than 1.0", (double)divtol); 402777e5a1f9SBarry Smith snes->divtol = divtol; 402877e5a1f9SBarry Smith } 40293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4030e4d06f11SPatrick Farrell } 4031e4d06f11SPatrick Farrell 40329b94acceSBarry Smith /*@ 40330b4b7b1cSBarry Smith SNESGetTolerances - Gets various parameters used in `SNES` convergence tests. 403433174efeSLois Curfman McInnes 4035c7afd0dbSLois Curfman McInnes Not Collective 4036c7afd0dbSLois Curfman McInnes 403777e5a1f9SBarry Smith Input Parameter: 403877e5a1f9SBarry Smith . snes - the `SNES` context 403977e5a1f9SBarry Smith 404077e5a1f9SBarry Smith Output Parameters: 40410b4b7b1cSBarry Smith + atol - the absolute convergence tolerance 40420b4b7b1cSBarry Smith . rtol - the relative convergence tolerance 404377e5a1f9SBarry Smith . stol - convergence tolerance in terms of the norm of the change in the solution between steps 40440b4b7b1cSBarry Smith . maxit - the maximum number of iterations allowed 40450b4b7b1cSBarry Smith - maxf - the maximum number of function evaluations allowed, `PETSC_UNLIMITED` indicates no bound 4046fee21e36SBarry Smith 404736851e7fSLois Curfman McInnes Level: intermediate 404836851e7fSLois Curfman McInnes 40490b4b7b1cSBarry Smith Notes: 40500b4b7b1cSBarry Smith See `SNESSetTolerances()` for details on the parameters. 40510b4b7b1cSBarry Smith 4052dc4c0fb0SBarry Smith The user can specify `NULL` for any parameter that is not needed. 4053dc4c0fb0SBarry Smith 40541cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTolerances()` 405533174efeSLois Curfman McInnes @*/ 4056d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetTolerances(SNES snes, PetscReal *atol, PetscReal *rtol, PetscReal *stol, PetscInt *maxit, PetscInt *maxf) 4057d71ae5a4SJacob Faibussowitsch { 40583a40ed3dSBarry Smith PetscFunctionBegin; 40590700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 406085385478SLisandro Dalcin if (atol) *atol = snes->abstol; 406133174efeSLois Curfman McInnes if (rtol) *rtol = snes->rtol; 4062c60f73f4SPeter Brune if (stol) *stol = snes->stol; 406333174efeSLois Curfman McInnes if (maxit) *maxit = snes->max_its; 406433174efeSLois Curfman McInnes if (maxf) *maxf = snes->max_funcs; 40653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 406633174efeSLois Curfman McInnes } 406733174efeSLois Curfman McInnes 4068e4d06f11SPatrick Farrell /*@ 4069e4d06f11SPatrick Farrell SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test. 4070e4d06f11SPatrick Farrell 4071e4d06f11SPatrick Farrell Not Collective 4072e4d06f11SPatrick Farrell 4073e4d06f11SPatrick Farrell Input Parameters: 4074f6dfbefdSBarry Smith + snes - the `SNES` context 4075e4d06f11SPatrick Farrell - divtol - divergence tolerance 4076e4d06f11SPatrick Farrell 4077e4d06f11SPatrick Farrell Level: intermediate 4078e4d06f11SPatrick Farrell 40791cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetDivergenceTolerance()` 4080e4d06f11SPatrick Farrell @*/ 4081d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDivergenceTolerance(SNES snes, PetscReal *divtol) 4082d71ae5a4SJacob Faibussowitsch { 4083e4d06f11SPatrick Farrell PetscFunctionBegin; 4084e4d06f11SPatrick Farrell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4085e4d06f11SPatrick Farrell if (divtol) *divtol = snes->divtol; 40863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4087e4d06f11SPatrick Farrell } 4088e4d06f11SPatrick Farrell 40896ba87a44SLisandro Dalcin PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *); 40906ba87a44SLisandro Dalcin 4091d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorLGRange(SNES snes, PetscInt n, PetscReal rnorm, void *monctx) 4092d71ae5a4SJacob Faibussowitsch { 4093b271bb04SBarry Smith PetscDrawLG lg; 4094b271bb04SBarry Smith PetscReal x, y, per; 4095b271bb04SBarry Smith PetscViewer v = (PetscViewer)monctx; 4096b271bb04SBarry Smith static PetscReal prev; /* should be in the context */ 4097b271bb04SBarry Smith PetscDraw draw; 4098b271bb04SBarry Smith 4099459f5d12SBarry Smith PetscFunctionBegin; 41004d4332d5SBarry Smith PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 4); 41019566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 0, &lg)); 41029566063dSJacob Faibussowitsch if (!n) PetscCall(PetscDrawLGReset(lg)); 41039566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 41049566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "Residual norm")); 4105b271bb04SBarry Smith x = (PetscReal)n; 410677b4d14cSPeter Brune if (rnorm > 0.0) y = PetscLog10Real(rnorm); 410794c9c6d3SKarl Rupp else y = -15.0; 41089566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 41096934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 41109566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 41119566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 4112b271bb04SBarry Smith } 4113b271bb04SBarry Smith 41149566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 1, &lg)); 41159566063dSJacob Faibussowitsch if (!n) PetscCall(PetscDrawLGReset(lg)); 41169566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 4117aaa8cc7dSPierre Jolivet PetscCall(PetscDrawSetTitle(draw, "% elements > .2*max element")); 41189566063dSJacob Faibussowitsch PetscCall(SNESMonitorRange_Private(snes, n, &per)); 4119b271bb04SBarry Smith x = (PetscReal)n; 4120b271bb04SBarry Smith y = 100.0 * per; 41219566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 41226934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 41239566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 41249566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 4125b271bb04SBarry Smith } 4126b271bb04SBarry Smith 41279566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 2, &lg)); 41289371c9d4SSatish Balay if (!n) { 41299371c9d4SSatish Balay prev = rnorm; 41309371c9d4SSatish Balay PetscCall(PetscDrawLGReset(lg)); 41319371c9d4SSatish Balay } 41329566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 41339566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm")); 4134b271bb04SBarry Smith x = (PetscReal)n; 4135b271bb04SBarry Smith y = (prev - rnorm) / prev; 41369566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 41376934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 41389566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 41399566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 4140b271bb04SBarry Smith } 4141b271bb04SBarry Smith 41429566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 3, &lg)); 41439566063dSJacob Faibussowitsch if (!n) PetscCall(PetscDrawLGReset(lg)); 41449566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 41459566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm*(% > .2 max)")); 4146b271bb04SBarry Smith x = (PetscReal)n; 4147b271bb04SBarry Smith y = (prev - rnorm) / (prev * per); 4148b271bb04SBarry Smith if (n > 2) { /*skip initial crazy value */ 41499566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 4150b271bb04SBarry Smith } 41516934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 41529566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 41539566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 4154b271bb04SBarry Smith } 4155b271bb04SBarry Smith prev = rnorm; 41563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4157b271bb04SBarry Smith } 4158b271bb04SBarry Smith 4159228d79bcSJed Brown /*@ 41602d157150SStefano Zampini SNESConverged - Run the convergence test and update the `SNESConvergedReason`. 41612d157150SStefano Zampini 41622d157150SStefano Zampini Collective 41632d157150SStefano Zampini 41642d157150SStefano Zampini Input Parameters: 41652d157150SStefano Zampini + snes - the `SNES` context 41662d157150SStefano Zampini . it - current iteration 41672d157150SStefano Zampini . xnorm - 2-norm of current iterate 41682d157150SStefano Zampini . snorm - 2-norm of current step 41692d157150SStefano Zampini - fnorm - 2-norm of function 41702d157150SStefano Zampini 41712d157150SStefano Zampini Level: developer 41722d157150SStefano Zampini 41732d157150SStefano Zampini Note: 4174420bcc1bSBarry Smith This routine is called by the `SNESSolve()` implementations. 41752d157150SStefano Zampini It does not typically need to be called by the user. 41762d157150SStefano Zampini 4177c948abdaSPierre Jolivet .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()` 41782d157150SStefano Zampini @*/ 41792d157150SStefano Zampini PetscErrorCode SNESConverged(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm) 41802d157150SStefano Zampini { 41812d157150SStefano Zampini PetscFunctionBegin; 41822d157150SStefano Zampini if (!snes->reason) { 41832d157150SStefano Zampini if (snes->normschedule == SNES_NORM_ALWAYS) PetscUseTypeMethod(snes, converged, it, xnorm, snorm, fnorm, &snes->reason, snes->cnvP); 41842d157150SStefano Zampini if (it == snes->max_its && !snes->reason) { 41852d157150SStefano Zampini if (snes->normschedule == SNES_NORM_ALWAYS) { 41862d157150SStefano Zampini PetscCall(PetscInfo(snes, "Maximum number of iterations has been reached: %" PetscInt_FMT "\n", snes->max_its)); 41872d157150SStefano Zampini snes->reason = SNES_DIVERGED_MAX_IT; 41882d157150SStefano Zampini } else snes->reason = SNES_CONVERGED_ITS; 41892d157150SStefano Zampini } 41902d157150SStefano Zampini } 41912d157150SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 41922d157150SStefano Zampini } 41932d157150SStefano Zampini 41942d157150SStefano Zampini /*@ 41950b4b7b1cSBarry Smith SNESMonitor - runs any `SNES` monitor routines provided with `SNESMonitor()` or the options database 4196228d79bcSJed Brown 4197c3339decSBarry Smith Collective 4198228d79bcSJed Brown 4199228d79bcSJed Brown Input Parameters: 4200f6dfbefdSBarry Smith + snes - nonlinear solver context obtained from `SNESCreate()` 42010b4b7b1cSBarry Smith . iter - current iteration number 42020b4b7b1cSBarry Smith - rnorm - current relative norm of the residual 4203228d79bcSJed Brown 4204dc4c0fb0SBarry Smith Level: developer 4205dc4c0fb0SBarry Smith 4206f6dfbefdSBarry Smith Note: 4207420bcc1bSBarry Smith This routine is called by the `SNESSolve()` implementations. 4208228d79bcSJed Brown It does not typically need to be called by the user. 4209228d79bcSJed Brown 42101cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorSet()` 4211228d79bcSJed Brown @*/ 4212d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitor(SNES snes, PetscInt iter, PetscReal rnorm) 4213d71ae5a4SJacob Faibussowitsch { 42147a03ce2fSLisandro Dalcin PetscInt i, n = snes->numbermonitors; 42157a03ce2fSLisandro Dalcin 42167a03ce2fSLisandro Dalcin PetscFunctionBegin; 42179566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(snes->vec_sol)); 421848a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall((*snes->monitor[i])(snes, iter, rnorm, snes->monitorcontext[i])); 42199566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(snes->vec_sol)); 42203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 42217a03ce2fSLisandro Dalcin } 42227a03ce2fSLisandro Dalcin 42239b94acceSBarry Smith /* ------------ Routines to set performance monitoring options ----------- */ 42249b94acceSBarry Smith 4225bf388a1fSBarry Smith /*MC 4226f6dfbefdSBarry Smith SNESMonitorFunction - functional form passed to `SNESMonitorSet()` to monitor convergence of nonlinear solver 4227bf388a1fSBarry Smith 4228bf388a1fSBarry Smith Synopsis: 4229aaa7dc30SBarry Smith #include <petscsnes.h> 423037fdd005SBarry Smith PetscErrorCode SNESMonitorFunction(SNES snes, PetscInt its, PetscReal norm, void *mctx) 4231bf388a1fSBarry Smith 4232c3339decSBarry Smith Collective 42331843f636SBarry Smith 42341843f636SBarry Smith Input Parameters: 4235f6dfbefdSBarry Smith + snes - the `SNES` context 4236bf388a1fSBarry Smith . its - iteration number 4237bf388a1fSBarry Smith . norm - 2-norm function value (may be estimated) 4238bf388a1fSBarry Smith - mctx - [optional] monitoring context 4239bf388a1fSBarry Smith 4240878cb397SSatish Balay Level: advanced 4241878cb397SSatish Balay 424256296ac4SStefano Zampini .seealso: [](ch_snes), `SNESMonitorSet()` 4243bf388a1fSBarry Smith M*/ 4244bf388a1fSBarry Smith 42459b94acceSBarry Smith /*@C 4246a6570f20SBarry Smith SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every 42470b4b7b1cSBarry Smith iteration of the `SNES` nonlinear solver to display the iteration's 42489b94acceSBarry Smith progress. 42499b94acceSBarry Smith 4250c3339decSBarry Smith Logically Collective 4251fee21e36SBarry Smith 4252c7afd0dbSLois Curfman McInnes Input Parameters: 4253f6dfbefdSBarry Smith + snes - the `SNES` context 425420f4b53cSBarry Smith . f - the monitor function, for the calling sequence see `SNESMonitorFunction` 4255420bcc1bSBarry Smith . mctx - [optional] user-defined context for private data for the monitor routine (use `NULL` if no context is desired) 425649abdd8aSBarry Smith - monitordestroy - [optional] routine that frees monitor context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence 42579b94acceSBarry Smith 42589665c990SLois Curfman McInnes Options Database Keys: 4259f6dfbefdSBarry Smith + -snes_monitor - sets `SNESMonitorDefault()` 4260798534f6SMatthew G. Knepley . -snes_monitor draw::draw_lg - sets line graph monitor, 4261dc4c0fb0SBarry Smith - -snes_monitor_cancel - cancels all monitors that have been hardwired into a code by calls to `SNESMonitorSet()`, but does not cancel those set via 4262c7afd0dbSLois Curfman McInnes the options database. 42639665c990SLois Curfman McInnes 4264dc4c0fb0SBarry Smith Level: intermediate 4265dc4c0fb0SBarry Smith 4266f6dfbefdSBarry Smith Note: 42676bc08f3fSLois Curfman McInnes Several different monitoring routines may be set by calling 4268f6dfbefdSBarry Smith `SNESMonitorSet()` multiple times; all will be called in the 42696bc08f3fSLois Curfman McInnes order in which they were set. 4270639f9d9dSBarry Smith 4271420bcc1bSBarry Smith Fortran Note: 4272f6dfbefdSBarry Smith Only a single monitor function can be set for each `SNES` object 4273025f1a04SBarry Smith 427449abdd8aSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESMonitorDefault()`, `SNESMonitorCancel()`, `SNESMonitorFunction`, `PetscCtxDestroyFn` 42759b94acceSBarry Smith @*/ 427649abdd8aSBarry Smith PetscErrorCode SNESMonitorSet(SNES snes, PetscErrorCode (*f)(SNES, PetscInt, PetscReal, void *), void *mctx, PetscCtxDestroyFn *monitordestroy) 4277d71ae5a4SJacob Faibussowitsch { 42783a40ed3dSBarry Smith PetscFunctionBegin; 42790700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4280453a69bbSBarry Smith for (PetscInt i = 0; i < snes->numbermonitors; i++) { 4281453a69bbSBarry Smith PetscBool identical; 4282453a69bbSBarry Smith 4283453a69bbSBarry Smith PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))(PetscVoidFn *)f, mctx, monitordestroy, (PetscErrorCode (*)(void))(PetscVoidFn *)snes->monitor[i], snes->monitorcontext[i], snes->monitordestroy[i], &identical)); 42843ba16761SJacob Faibussowitsch if (identical) PetscFunctionReturn(PETSC_SUCCESS); 4285649052a6SBarry Smith } 42865f80ce2aSJacob Faibussowitsch PetscCheck(snes->numbermonitors < MAXSNESMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set"); 42876e4dcb14SBarry Smith snes->monitor[snes->numbermonitors] = f; 4288b8a78c4aSBarry Smith snes->monitordestroy[snes->numbermonitors] = monitordestroy; 4289835f2295SStefano Zampini snes->monitorcontext[snes->numbermonitors++] = mctx; 42903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 42919b94acceSBarry Smith } 42929b94acceSBarry Smith 4293a278d85bSSatish Balay /*@ 4294f6dfbefdSBarry Smith SNESMonitorCancel - Clears all the monitor functions for a `SNES` object. 42955cd90555SBarry Smith 4296c3339decSBarry Smith Logically Collective 4297c7afd0dbSLois Curfman McInnes 42982fe279fdSBarry Smith Input Parameter: 4299f6dfbefdSBarry Smith . snes - the `SNES` context 43005cd90555SBarry Smith 43011a480d89SAdministrator Options Database Key: 4302a6570f20SBarry Smith . -snes_monitor_cancel - cancels all monitors that have been hardwired 4303dc4c0fb0SBarry Smith into a code by calls to `SNESMonitorSet()`, but does not cancel those 4304c7afd0dbSLois Curfman McInnes set via the options database 43055cd90555SBarry Smith 4306dc4c0fb0SBarry Smith Level: intermediate 4307dc4c0fb0SBarry Smith 4308f6dfbefdSBarry Smith Note: 4309f6dfbefdSBarry Smith There is no way to clear one specific monitor from a `SNES` object. 43105cd90555SBarry Smith 431156296ac4SStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESMonitorDefault()`, `SNESMonitorSet()` 43125cd90555SBarry Smith @*/ 4313d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorCancel(SNES snes) 4314d71ae5a4SJacob Faibussowitsch { 4315d952e501SBarry Smith PetscInt i; 4316d952e501SBarry Smith 43175cd90555SBarry Smith PetscFunctionBegin; 43180700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4319d952e501SBarry Smith for (i = 0; i < snes->numbermonitors; i++) { 432048a46eb9SPierre Jolivet if (snes->monitordestroy[i]) PetscCall((*snes->monitordestroy[i])(&snes->monitorcontext[i])); 4321d952e501SBarry Smith } 43225cd90555SBarry Smith snes->numbermonitors = 0; 43233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 43245cd90555SBarry Smith } 43255cd90555SBarry Smith 4326bf388a1fSBarry Smith /*MC 4327bf388a1fSBarry Smith SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver 4328bf388a1fSBarry Smith 4329bf388a1fSBarry Smith Synopsis: 4330aaa7dc30SBarry Smith #include <petscsnes.h> 433137fdd005SBarry Smith PetscErrorCode SNESConvergenceTest(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *cctx) 4332bf388a1fSBarry Smith 4333c3339decSBarry Smith Collective 43341843f636SBarry Smith 43351843f636SBarry Smith Input Parameters: 4336f6dfbefdSBarry Smith + snes - the `SNES` context 4337bf388a1fSBarry Smith . it - current iteration (0 is the first and is before any Newton step) 4338bf388a1fSBarry Smith . xnorm - 2-norm of current iterate 4339bf388a1fSBarry Smith . gnorm - 2-norm of current step 43401843f636SBarry Smith . f - 2-norm of function 43411843f636SBarry Smith - cctx - [optional] convergence context 43421843f636SBarry Smith 43431843f636SBarry Smith Output Parameter: 43441843f636SBarry Smith . reason - reason for convergence/divergence, only needs to be set when convergence or divergence is detected 4345bf388a1fSBarry Smith 4346878cb397SSatish Balay Level: intermediate 4347bf388a1fSBarry Smith 4348c948abdaSPierre Jolivet .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()` 4349bf388a1fSBarry Smith M*/ 4350bf388a1fSBarry Smith 43519b94acceSBarry Smith /*@C 43529b94acceSBarry Smith SNESSetConvergenceTest - Sets the function that is to be used 43539b94acceSBarry Smith to test for convergence of the nonlinear iterative solution. 43549b94acceSBarry Smith 4355c3339decSBarry Smith Logically Collective 4356fee21e36SBarry Smith 4357c7afd0dbSLois Curfman McInnes Input Parameters: 4358f6dfbefdSBarry Smith + snes - the `SNES` context 4359e4094ef1SJacob Faibussowitsch . SNESConvergenceTestFunction - routine to test for convergence 4360dc4c0fb0SBarry Smith . cctx - [optional] context for private data for the convergence routine (may be `NULL`) 4361dc4c0fb0SBarry Smith - destroy - [optional] destructor for the context (may be `NULL`; `PETSC_NULL_FUNCTION` in Fortran) 43629b94acceSBarry Smith 436336851e7fSLois Curfman McInnes Level: advanced 436436851e7fSLois Curfman McInnes 43651cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedDefault()`, `SNESConvergedSkip()`, `SNESConvergenceTestFunction` 43669b94acceSBarry Smith @*/ 436712651944SBarry Smith PetscErrorCode SNESSetConvergenceTest(SNES snes, PetscErrorCode (*SNESConvergenceTestFunction)(SNES, PetscInt, PetscReal, PetscReal, PetscReal, SNESConvergedReason *, void *), void *cctx, PetscCtxDestroyFn *destroy) 4368d71ae5a4SJacob Faibussowitsch { 43693a40ed3dSBarry Smith PetscFunctionBegin; 43700700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4371e2a6519dSDmitry Karpeev if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip; 437212651944SBarry Smith if (snes->ops->convergeddestroy) PetscCall((*snes->ops->convergeddestroy)(&snes->cnvP)); 4373bf388a1fSBarry Smith snes->ops->converged = SNESConvergenceTestFunction; 43747f7931b9SBarry Smith snes->ops->convergeddestroy = destroy; 437585385478SLisandro Dalcin snes->cnvP = cctx; 43763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 43779b94acceSBarry Smith } 43789b94acceSBarry Smith 437952baeb72SSatish Balay /*@ 43800b4b7b1cSBarry Smith SNESGetConvergedReason - Gets the reason the `SNES` iteration was stopped, which may be due to convergence, divergence, or stagnation 4381184914b5SBarry Smith 4382184914b5SBarry Smith Not Collective 4383184914b5SBarry Smith 4384184914b5SBarry Smith Input Parameter: 4385f6dfbefdSBarry Smith . snes - the `SNES` context 4386184914b5SBarry Smith 4387184914b5SBarry Smith Output Parameter: 4388f6dfbefdSBarry Smith . reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` for the individual convergence tests for complete lists 4389184914b5SBarry Smith 4390f6dfbefdSBarry Smith Options Database Key: 43916a4d7782SBarry Smith . -snes_converged_reason - prints the reason to standard out 43926a4d7782SBarry Smith 4393184914b5SBarry Smith Level: intermediate 4394184914b5SBarry Smith 4395f6dfbefdSBarry Smith Note: 4396f6dfbefdSBarry Smith Should only be called after the call the `SNESSolve()` is complete, if it is called earlier it returns the value `SNES__CONVERGED_ITERATING`. 4397184914b5SBarry Smith 43981cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESSetConvergedReason()`, `SNESConvergedReason`, `SNESGetConvergedReasonString()` 4399184914b5SBarry Smith @*/ 4400d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReason(SNES snes, SNESConvergedReason *reason) 4401d71ae5a4SJacob Faibussowitsch { 4402184914b5SBarry Smith PetscFunctionBegin; 44030700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 44044f572ea9SToby Isaac PetscAssertPointer(reason, 2); 4405184914b5SBarry Smith *reason = snes->reason; 44063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4407184914b5SBarry Smith } 4408184914b5SBarry Smith 4409c4421ceaSFande Kong /*@C 4410f6dfbefdSBarry Smith SNESGetConvergedReasonString - Return a human readable string for `SNESConvergedReason` 4411c4421ceaSFande Kong 4412c4421ceaSFande Kong Not Collective 4413c4421ceaSFande Kong 4414c4421ceaSFande Kong Input Parameter: 4415f6dfbefdSBarry Smith . snes - the `SNES` context 4416c4421ceaSFande Kong 4417c4421ceaSFande Kong Output Parameter: 4418dc4c0fb0SBarry Smith . strreason - a human readable string that describes `SNES` converged reason 4419c4421ceaSFande Kong 442099c90e12SSatish Balay Level: beginner 4421c4421ceaSFande Kong 44221cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetConvergedReason()` 4423c4421ceaSFande Kong @*/ 4424d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReasonString(SNES snes, const char **strreason) 4425d71ae5a4SJacob Faibussowitsch { 4426c4421ceaSFande Kong PetscFunctionBegin; 4427c4421ceaSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 44284f572ea9SToby Isaac PetscAssertPointer(strreason, 2); 4429c4421ceaSFande Kong *strreason = SNESConvergedReasons[snes->reason]; 44303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4431c4421ceaSFande Kong } 4432c4421ceaSFande Kong 443333866048SMatthew G. Knepley /*@ 4434f6dfbefdSBarry Smith SNESSetConvergedReason - Sets the reason the `SNES` iteration was stopped. 443533866048SMatthew G. Knepley 443633866048SMatthew G. Knepley Not Collective 443733866048SMatthew G. Knepley 443833866048SMatthew G. Knepley Input Parameters: 4439f6dfbefdSBarry Smith + snes - the `SNES` context 4440f6dfbefdSBarry Smith - reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` or the 444133866048SMatthew G. Knepley manual pages for the individual convergence tests for complete lists 444233866048SMatthew G. Knepley 4443f6dfbefdSBarry Smith Level: developer 4444f6dfbefdSBarry Smith 4445420bcc1bSBarry Smith Developer Note: 4446f6dfbefdSBarry Smith Called inside the various `SNESSolve()` implementations 444733866048SMatthew G. Knepley 44481cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetConvergedReason()`, `SNESSetConvergenceTest()`, `SNESConvergedReason` 444933866048SMatthew G. Knepley @*/ 4450d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergedReason(SNES snes, SNESConvergedReason reason) 4451d71ae5a4SJacob Faibussowitsch { 445233866048SMatthew G. Knepley PetscFunctionBegin; 445333866048SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 44545f3c5e7aSBarry Smith PetscCheck(!snes->errorifnotconverged || reason > 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "SNES code should have previously errored due to negative reason"); 445533866048SMatthew G. Knepley snes->reason = reason; 44563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 445733866048SMatthew G. Knepley } 445833866048SMatthew G. Knepley 4459c9005455SLois Curfman McInnes /*@ 4460420bcc1bSBarry Smith SNESSetConvergenceHistory - Sets the arrays used to hold the convergence history. 4461c9005455SLois Curfman McInnes 4462c3339decSBarry Smith Logically Collective 4463fee21e36SBarry Smith 4464c7afd0dbSLois Curfman McInnes Input Parameters: 4465f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 44668c7482ecSBarry Smith . a - array to hold history, this array will contain the function norms computed at each step 4467cd5578b5SBarry Smith . its - integer array holds the number of linear iterations for each solve. 4468420bcc1bSBarry Smith . na - size of `a` and `its` 4469f6dfbefdSBarry Smith - reset - `PETSC_TRUE` indicates each new nonlinear solve resets the history counter to zero, 4470758f92a0SBarry Smith else it continues storing new values for new nonlinear solves after the old ones 4471c7afd0dbSLois Curfman McInnes 4472dc4c0fb0SBarry Smith Level: intermediate 4473dc4c0fb0SBarry Smith 4474308dcc3eSBarry Smith Notes: 4475ce78bad3SBarry Smith If 'a' and 'its' are `NULL` then space is allocated for the history. If 'na' is `PETSC_DECIDE` (or, deprecated, `PETSC_DEFAULT`) then a 447677e5a1f9SBarry Smith default array of length 1,000 is allocated. 4477308dcc3eSBarry Smith 4478c9005455SLois Curfman McInnes This routine is useful, e.g., when running a code for purposes 4479c9005455SLois Curfman McInnes of accurate performance monitoring, when no I/O should be done 4480c9005455SLois Curfman McInnes during the section of code that is being timed. 4481c9005455SLois Curfman McInnes 4482420bcc1bSBarry Smith If the arrays run out of space after a number of iterations then the later values are not saved in the history 4483420bcc1bSBarry Smith 44841cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetConvergenceHistory()` 4485c9005455SLois Curfman McInnes @*/ 4486d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceHistory(SNES snes, PetscReal a[], PetscInt its[], PetscInt na, PetscBool reset) 4487d71ae5a4SJacob Faibussowitsch { 44883a40ed3dSBarry Smith PetscFunctionBegin; 44890700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 44904f572ea9SToby Isaac if (a) PetscAssertPointer(a, 2); 44914f572ea9SToby Isaac if (its) PetscAssertPointer(its, 3); 44927a1ec6d4SBarry Smith if (!a) { 449377e5a1f9SBarry Smith if (na == PETSC_DECIDE) na = 1000; 44949566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(na, &a, na, &its)); 4495071fcb05SBarry Smith snes->conv_hist_alloc = PETSC_TRUE; 4496308dcc3eSBarry Smith } 4497c9005455SLois Curfman McInnes snes->conv_hist = a; 4498758f92a0SBarry Smith snes->conv_hist_its = its; 4499115dd874SBarry Smith snes->conv_hist_max = (size_t)na; 4500a12bc48fSLisandro Dalcin snes->conv_hist_len = 0; 4501758f92a0SBarry Smith snes->conv_hist_reset = reset; 45023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4503758f92a0SBarry Smith } 4504758f92a0SBarry Smith 4505d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB) 4506c6db04a5SJed Brown #include <engine.h> /* MATLAB include file */ 4507c6db04a5SJed Brown #include <mex.h> /* MATLAB include file */ 450899e0435eSBarry Smith 4509d71ae5a4SJacob Faibussowitsch PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes) 4510d71ae5a4SJacob Faibussowitsch { 4511308dcc3eSBarry Smith mxArray *mat; 4512308dcc3eSBarry Smith PetscInt i; 4513308dcc3eSBarry Smith PetscReal *ar; 4514308dcc3eSBarry Smith 4515308dcc3eSBarry Smith mat = mxCreateDoubleMatrix(snes->conv_hist_len, 1, mxREAL); 4516308dcc3eSBarry Smith ar = (PetscReal *)mxGetData(mat); 4517f5af7f23SKarl Rupp for (i = 0; i < snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i]; 451811cc89d2SBarry Smith return mat; 4519308dcc3eSBarry Smith } 4520308dcc3eSBarry Smith #endif 4521308dcc3eSBarry Smith 45220c4c9dddSBarry Smith /*@C 4523420bcc1bSBarry Smith SNESGetConvergenceHistory - Gets the arrays used to hold the convergence history. 4524758f92a0SBarry Smith 45253f9fe445SBarry Smith Not Collective 4526758f92a0SBarry Smith 4527758f92a0SBarry Smith Input Parameter: 4528f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 4529758f92a0SBarry Smith 4530758f92a0SBarry Smith Output Parameters: 4531f6dfbefdSBarry Smith + a - array to hold history, usually was set with `SNESSetConvergenceHistory()` 4532758f92a0SBarry Smith . its - integer array holds the number of linear iterations (or 4533758f92a0SBarry Smith negative if not converged) for each solve. 453420f4b53cSBarry Smith - na - size of `a` and `its` 4535758f92a0SBarry Smith 4536dc4c0fb0SBarry Smith Level: intermediate 4537dc4c0fb0SBarry Smith 453820f4b53cSBarry Smith Note: 453920f4b53cSBarry Smith This routine is useful, e.g., when running a code for purposes 454020f4b53cSBarry Smith of accurate performance monitoring, when no I/O should be done 454120f4b53cSBarry Smith during the section of code that is being timed. 454220f4b53cSBarry Smith 4543ce78bad3SBarry Smith Fortran Notes: 4544ce78bad3SBarry Smith Return the arrays with ``SNESRestoreConvergenceHistory()` 4545ce78bad3SBarry Smith 4546ce78bad3SBarry Smith Use the arguments 4547dc4c0fb0SBarry Smith .vb 4548ce78bad3SBarry Smith PetscReal, pointer :: a(:) 4549ce78bad3SBarry Smith PetscInt, pointer :: its(:) 4550dc4c0fb0SBarry Smith .ve 4551758f92a0SBarry Smith 45521cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceHistory()` 4553758f92a0SBarry Smith @*/ 4554d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergenceHistory(SNES snes, PetscReal *a[], PetscInt *its[], PetscInt *na) 4555d71ae5a4SJacob Faibussowitsch { 4556758f92a0SBarry Smith PetscFunctionBegin; 45570700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4558758f92a0SBarry Smith if (a) *a = snes->conv_hist; 4559758f92a0SBarry Smith if (its) *its = snes->conv_hist_its; 4560115dd874SBarry Smith if (na) *na = (PetscInt)snes->conv_hist_len; 45613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4562c9005455SLois Curfman McInnes } 4563c9005455SLois Curfman McInnes 4564ac226902SBarry Smith /*@C 456576b2cf59SMatthew Knepley SNESSetUpdate - Sets the general-purpose update function called 4566eec8f646SJed Brown at the beginning of every iteration of the nonlinear solve. Specifically 456753e5d35bSStefano Zampini it is called just before the Jacobian is "evaluated" and after the function 456853e5d35bSStefano Zampini evaluation. 456976b2cf59SMatthew Knepley 4570c3339decSBarry Smith Logically Collective 457176b2cf59SMatthew Knepley 457276b2cf59SMatthew Knepley Input Parameters: 4573a2b725a8SWilliam Gropp + snes - The nonlinear solver context 457453e5d35bSStefano Zampini - func - The update function; for calling sequence see `SNESUpdateFn` 457576b2cf59SMatthew Knepley 4576fe97e370SBarry Smith Level: advanced 4577fe97e370SBarry Smith 4578420bcc1bSBarry Smith Notes: 4579f6dfbefdSBarry Smith This is NOT what one uses to update the ghost points before a function evaluation, that should be done at the beginning of your function provided 4580f6dfbefdSBarry Smith to `SNESSetFunction()`, or `SNESSetPicard()` 458153e5d35bSStefano Zampini This is not used by most users, and it is intended to provide a general hook that is run 458253e5d35bSStefano Zampini right before the direction step is computed. 4583ce78bad3SBarry Smith 458453e5d35bSStefano Zampini Users are free to modify the current residual vector, 458553e5d35bSStefano Zampini the current linearization point, or any other vector associated to the specific solver used. 458653e5d35bSStefano Zampini If such modifications take place, it is the user responsibility to update all the relevant 4587ce78bad3SBarry Smith vectors. For example, if one is adjusting the model parameters at each Newton step their code may look like 4588ce78bad3SBarry Smith .vb 4589ce78bad3SBarry Smith PetscErrorCode update(SNES snes, PetscInt iteration) 4590ce78bad3SBarry Smith { 4591ce78bad3SBarry Smith PetscFunctionBeginUser; 4592ce78bad3SBarry Smith if (iteration > 0) { 4593ce78bad3SBarry Smith // update the model parameters here 4594ce78bad3SBarry Smith Vec x,f; 4595ce78bad3SBarry Smith PetscCall(SNESGetSolution(snes,&x)); 4596ce78bad3SBarry Smith PetcCall(SNESGetFunction(snes,&f,NULL,NULL)); 4597ce78bad3SBarry Smith PetscCall(SNESComputeFunction(snes,x,f)); 4598ce78bad3SBarry Smith } 4599ce78bad3SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 4600ce78bad3SBarry Smith } 4601ce78bad3SBarry Smith .ve 460276b2cf59SMatthew Knepley 4603aaa8cc7dSPierre Jolivet There are a variety of function hooks one many set that are called at different stages of the nonlinear solution process, see the functions listed below. 46046b7fb656SBarry Smith 4605e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetJacobian()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRSetPostCheck()`, 460653e5d35bSStefano Zampini `SNESMonitorSet()` 460776b2cf59SMatthew Knepley @*/ 460853e5d35bSStefano Zampini PetscErrorCode SNESSetUpdate(SNES snes, SNESUpdateFn *func) 4609d71ae5a4SJacob Faibussowitsch { 461076b2cf59SMatthew Knepley PetscFunctionBegin; 46110700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4612e7788613SBarry Smith snes->ops->update = func; 46133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 461476b2cf59SMatthew Knepley } 461576b2cf59SMatthew Knepley 4616ffeef943SBarry Smith /*@ 4617f6dfbefdSBarry Smith SNESConvergedReasonView - Displays the reason a `SNES` solve converged or diverged to a viewer 46182a359c20SBarry Smith 4619c3339decSBarry Smith Collective 46202a359c20SBarry Smith 4621e4094ef1SJacob Faibussowitsch Input Parameters: 4622f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 46232a359c20SBarry Smith - viewer - the viewer to display the reason 46242a359c20SBarry Smith 46252a359c20SBarry Smith Options Database Keys: 4626ee300463SSatish Balay + -snes_converged_reason - print reason for converged or diverged, also prints number of iterations 4627ee300463SSatish Balay - -snes_converged_reason ::failed - only print reason and number of iterations when diverged 4628eafd5ff0SAlex Lindsay 4629420bcc1bSBarry Smith Level: beginner 4630420bcc1bSBarry Smith 4631f6dfbefdSBarry Smith Note: 4632f6dfbefdSBarry Smith To change the format of the output call `PetscViewerPushFormat`(viewer,format) before this call. Use `PETSC_VIEWER_DEFAULT` for the default, 4633f6dfbefdSBarry Smith use `PETSC_VIEWER_FAILED` to only display a reason if it fails. 46342a359c20SBarry Smith 46351cc06b55SBarry Smith .seealso: [](ch_snes), `SNESConvergedReason`, `PetscViewer`, `SNES`, 4636f6dfbefdSBarry Smith `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, 4637f6dfbefdSBarry Smith `SNESConvergedReasonViewFromOptions()`, 4638db781477SPatrick Sanan `PetscViewerPushFormat()`, `PetscViewerPopFormat()` 46392a359c20SBarry Smith @*/ 4640d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonView(SNES snes, PetscViewer viewer) 4641d71ae5a4SJacob Faibussowitsch { 464275cca76cSMatthew G. Knepley PetscViewerFormat format; 46432a359c20SBarry Smith PetscBool isAscii; 46442a359c20SBarry Smith 46452a359c20SBarry Smith PetscFunctionBegin; 464619a666eeSBarry Smith if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)); 46479566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii)); 46482a359c20SBarry Smith if (isAscii) { 46499566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 465065bf60d2SBarry Smith PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel + 1)); 465175cca76cSMatthew G. Knepley if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 465275cca76cSMatthew G. Knepley DM dm; 465375cca76cSMatthew G. Knepley Vec u; 465475cca76cSMatthew G. Knepley PetscDS prob; 465575cca76cSMatthew G. Knepley PetscInt Nf, f; 465695cbbfd3SMatthew G. Knepley PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *); 465795cbbfd3SMatthew G. Knepley void **exactCtx; 465875cca76cSMatthew G. Knepley PetscReal error; 465975cca76cSMatthew G. Knepley 46609566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 46619566063dSJacob Faibussowitsch PetscCall(SNESGetSolution(snes, &u)); 46629566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob)); 46639566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(prob, &Nf)); 46649566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(Nf, &exactSol, Nf, &exactCtx)); 46659566063dSJacob Faibussowitsch for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f])); 46669566063dSJacob Faibussowitsch PetscCall(DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error)); 46679566063dSJacob Faibussowitsch PetscCall(PetscFree2(exactSol, exactCtx)); 46689566063dSJacob Faibussowitsch if (error < 1.0e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n")); 466963a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", (double)error)); 467075cca76cSMatthew G. Knepley } 4671eafd5ff0SAlex Lindsay if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) { 46722a359c20SBarry Smith if (((PetscObject)snes)->prefix) { 467363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter)); 46742a359c20SBarry Smith } else { 467563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve converged due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter)); 46762a359c20SBarry Smith } 4677eafd5ff0SAlex Lindsay } else if (snes->reason <= 0) { 46782a359c20SBarry Smith if (((PetscObject)snes)->prefix) { 467963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve did not converge due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter)); 46802a359c20SBarry Smith } else { 468163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve did not converge due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter)); 46822a359c20SBarry Smith } 46832a359c20SBarry Smith } 468465bf60d2SBarry Smith PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel + 1)); 46852a359c20SBarry Smith } 46863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 46872a359c20SBarry Smith } 46882a359c20SBarry Smith 4689c4421ceaSFande Kong /*@C 4690c4421ceaSFande Kong SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the 4691aaa8cc7dSPierre Jolivet end of the nonlinear solver to display the convergence reason of the nonlinear solver. 4692c4421ceaSFande Kong 4693c3339decSBarry Smith Logically Collective 4694c4421ceaSFande Kong 4695c4421ceaSFande Kong Input Parameters: 4696f6dfbefdSBarry Smith + snes - the `SNES` context 4697420bcc1bSBarry Smith . f - the `SNESConvergedReason` view function 4698420bcc1bSBarry Smith . vctx - [optional] user-defined context for private data for the `SNESConvergedReason` view function (use `NULL` if no context is desired) 469949abdd8aSBarry Smith - reasonviewdestroy - [optional] routine that frees the context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence 4700420bcc1bSBarry Smith 4701420bcc1bSBarry Smith Calling sequence of `f`: 4702420bcc1bSBarry Smith + snes - the `SNES` context 470349abdd8aSBarry Smith - vctx - [optional] context for private data for the function 4704c4421ceaSFande Kong 4705c4421ceaSFande Kong Options Database Keys: 4706f6dfbefdSBarry Smith + -snes_converged_reason - sets a default `SNESConvergedReasonView()` 4707420bcc1bSBarry Smith - -snes_converged_reason_view_cancel - cancels all converged reason viewers that have been hardwired into a code by 4708420bcc1bSBarry Smith calls to `SNESConvergedReasonViewSet()`, but does not cancel those set via the options database. 4709c4421ceaSFande Kong 4710dc4c0fb0SBarry Smith Level: intermediate 4711dc4c0fb0SBarry Smith 4712f6dfbefdSBarry Smith Note: 4713c4421ceaSFande Kong Several different converged reason view routines may be set by calling 4714f6dfbefdSBarry Smith `SNESConvergedReasonViewSet()` multiple times; all will be called in the 4715c4421ceaSFande Kong order in which they were set. 4716c4421ceaSFande Kong 471749abdd8aSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`, `SNESConvergedReasonViewCancel()`, 471849abdd8aSBarry Smith `PetscCtxDestroyFn` 4719c4421ceaSFande Kong @*/ 472049abdd8aSBarry Smith PetscErrorCode SNESConvergedReasonViewSet(SNES snes, PetscErrorCode (*f)(SNES snes, void *vctx), void *vctx, PetscCtxDestroyFn *reasonviewdestroy) 4721d71ae5a4SJacob Faibussowitsch { 4722c4421ceaSFande Kong PetscFunctionBegin; 4723c4421ceaSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4724453a69bbSBarry Smith for (PetscInt i = 0; i < snes->numberreasonviews; i++) { 4725453a69bbSBarry Smith PetscBool identical; 4726453a69bbSBarry Smith 4727453a69bbSBarry Smith PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))(PetscVoidFn *)f, vctx, reasonviewdestroy, (PetscErrorCode (*)(void))(PetscVoidFn *)snes->reasonview[i], snes->reasonviewcontext[i], snes->reasonviewdestroy[i], &identical)); 47283ba16761SJacob Faibussowitsch if (identical) PetscFunctionReturn(PETSC_SUCCESS); 4729c4421ceaSFande Kong } 47305f80ce2aSJacob Faibussowitsch PetscCheck(snes->numberreasonviews < MAXSNESREASONVIEWS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many SNES reasonview set"); 4731c4421ceaSFande Kong snes->reasonview[snes->numberreasonviews] = f; 4732c4421ceaSFande Kong snes->reasonviewdestroy[snes->numberreasonviews] = reasonviewdestroy; 4733835f2295SStefano Zampini snes->reasonviewcontext[snes->numberreasonviews++] = vctx; 47343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4735c4421ceaSFande Kong } 4736c4421ceaSFande Kong 473791f3e32bSBarry Smith /*@ 4738420bcc1bSBarry Smith SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a `SNESConvergedReason` is to be viewed at the end of `SNESSolve()` 47390b4b7b1cSBarry Smith All the user-provided viewer routines set with `SNESConvergedReasonViewSet()` will be called, if they exist. 47402a359c20SBarry Smith 4741c3339decSBarry Smith Collective 47422a359c20SBarry Smith 47432fe279fdSBarry Smith Input Parameter: 4744f6dfbefdSBarry Smith . snes - the `SNES` object 47452a359c20SBarry Smith 4746f6dfbefdSBarry Smith Level: advanced 47472a359c20SBarry Smith 47481cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESConvergedReasonViewSet()`, `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, 4749f6dfbefdSBarry Smith `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()` 47502a359c20SBarry Smith @*/ 4751d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes) 4752d71ae5a4SJacob Faibussowitsch { 47532a359c20SBarry Smith static PetscBool incall = PETSC_FALSE; 47542a359c20SBarry Smith 47552a359c20SBarry Smith PetscFunctionBegin; 47563ba16761SJacob Faibussowitsch if (incall) PetscFunctionReturn(PETSC_SUCCESS); 47572a359c20SBarry Smith incall = PETSC_TRUE; 4758c4421ceaSFande Kong 4759c4421ceaSFande Kong /* All user-provided viewers are called first, if they exist. */ 476036d43d94SBarry Smith for (PetscInt i = 0; i < snes->numberreasonviews; i++) PetscCall((*snes->reasonview[i])(snes, snes->reasonviewcontext[i])); 4761c4421ceaSFande Kong 4762c4421ceaSFande Kong /* Call PETSc default routine if users ask for it */ 476336d43d94SBarry Smith if (snes->convergedreasonviewer) { 476436d43d94SBarry Smith PetscCall(PetscViewerPushFormat(snes->convergedreasonviewer, snes->convergedreasonformat)); 476536d43d94SBarry Smith PetscCall(SNESConvergedReasonView(snes, snes->convergedreasonviewer)); 476636d43d94SBarry Smith PetscCall(PetscViewerPopFormat(snes->convergedreasonviewer)); 47672a359c20SBarry Smith } 47682a359c20SBarry Smith incall = PETSC_FALSE; 47693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 47702a359c20SBarry Smith } 47712a359c20SBarry Smith 4772487a658cSBarry Smith /*@ 47730b4b7b1cSBarry Smith SNESSolve - Solves a nonlinear system $F(x) = b $ associated with a `SNES` object 47749b94acceSBarry Smith 4775c3339decSBarry Smith Collective 4776c7afd0dbSLois Curfman McInnes 4777b2002411SLois Curfman McInnes Input Parameters: 4778f6dfbefdSBarry Smith + snes - the `SNES` context 47790b4b7b1cSBarry Smith . b - the constant part of the equation $F(x) = b$, or `NULL` to use zero. 478085385478SLisandro Dalcin - x - the solution vector. 47819b94acceSBarry Smith 4782dc4c0fb0SBarry Smith Level: beginner 4783dc4c0fb0SBarry Smith 4784f6dfbefdSBarry Smith Note: 4785420bcc1bSBarry Smith The user should initialize the vector, `x`, with the initial guess 4786a9b45538SStefano Zampini for the nonlinear solve prior to calling `SNESSolve()` . 47878ddd3da0SLois Curfman McInnes 47881cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESSetFunction()`, `SNESSetJacobian()`, `SNESSetGridSequence()`, `SNESGetSolution()`, 4789db781477SPatrick Sanan `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRGetPreCheck()`, `SNESNewtonTRSetPostCheck()`, `SNESNewtonTRGetPostCheck()`, 4790a9b45538SStefano Zampini `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()` 47919b94acceSBarry Smith @*/ 4792d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSolve(SNES snes, Vec b, Vec x) 4793d71ae5a4SJacob Faibussowitsch { 4794ace3abfcSBarry Smith PetscBool flg; 4795efd51863SBarry Smith PetscInt grid; 47960298fd71SBarry Smith Vec xcreated = NULL; 4797caa4e7f2SJed Brown DM dm; 4798052efed2SBarry Smith 47993a40ed3dSBarry Smith PetscFunctionBegin; 48000700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4801a69afd8bSBarry Smith if (x) PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4802a69afd8bSBarry Smith if (x) PetscCheckSameComm(snes, 1, x, 3); 48030700a824SBarry Smith if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 480485385478SLisandro Dalcin if (b) PetscCheckSameComm(snes, 1, b, 2); 480585385478SLisandro Dalcin 480634b4d3a8SMatthew G. Knepley /* High level operations using the nonlinear solver */ 480706fc46c8SMatthew G. Knepley { 480806fc46c8SMatthew G. Knepley PetscViewer viewer; 480906fc46c8SMatthew G. Knepley PetscViewerFormat format; 48107c88af5aSMatthew G. Knepley PetscInt num; 481106fc46c8SMatthew G. Knepley PetscBool flg; 481206fc46c8SMatthew G. Knepley static PetscBool incall = PETSC_FALSE; 481306fc46c8SMatthew G. Knepley 481406fc46c8SMatthew G. Knepley if (!incall) { 481534b4d3a8SMatthew G. Knepley /* Estimate the convergence rate of the discretization */ 4816648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg)); 481706fc46c8SMatthew G. Knepley if (flg) { 481806fc46c8SMatthew G. Knepley PetscConvEst conv; 481946079b62SMatthew G. Knepley DM dm; 482046079b62SMatthew G. Knepley PetscReal *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */ 482146079b62SMatthew G. Knepley PetscInt Nf; 482206fc46c8SMatthew G. Knepley 482306fc46c8SMatthew G. Knepley incall = PETSC_TRUE; 48249566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 48259566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 48269566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(Nf, &alpha)); 48279566063dSJacob Faibussowitsch PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)snes), &conv)); 48289566063dSJacob Faibussowitsch PetscCall(PetscConvEstSetSolver(conv, (PetscObject)snes)); 48299566063dSJacob Faibussowitsch PetscCall(PetscConvEstSetFromOptions(conv)); 48309566063dSJacob Faibussowitsch PetscCall(PetscConvEstSetUp(conv)); 48319566063dSJacob Faibussowitsch PetscCall(PetscConvEstGetConvRate(conv, alpha)); 48329566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(viewer, format)); 48339566063dSJacob Faibussowitsch PetscCall(PetscConvEstRateView(conv, alpha, viewer)); 48349566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer)); 4835648c30bcSBarry Smith PetscCall(PetscViewerDestroy(&viewer)); 48369566063dSJacob Faibussowitsch PetscCall(PetscConvEstDestroy(&conv)); 48379566063dSJacob Faibussowitsch PetscCall(PetscFree(alpha)); 483806fc46c8SMatthew G. Knepley incall = PETSC_FALSE; 483906fc46c8SMatthew G. Knepley } 484034b4d3a8SMatthew G. Knepley /* Adaptively refine the initial grid */ 4841b2588ea6SMatthew G. Knepley num = 1; 48429566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_initial", &num, &flg)); 484334b4d3a8SMatthew G. Knepley if (flg) { 484434b4d3a8SMatthew G. Knepley DMAdaptor adaptor; 484534b4d3a8SMatthew G. Knepley 484634b4d3a8SMatthew G. Knepley incall = PETSC_TRUE; 48479566063dSJacob Faibussowitsch PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor)); 48489566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSolver(adaptor, snes)); 48499566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSequenceLength(adaptor, num)); 48509566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetFromOptions(adaptor)); 48519566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetUp(adaptor)); 48529566063dSJacob Faibussowitsch PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x)); 48539566063dSJacob Faibussowitsch PetscCall(DMAdaptorDestroy(&adaptor)); 485434b4d3a8SMatthew G. Knepley incall = PETSC_FALSE; 485534b4d3a8SMatthew G. Knepley } 48567c88af5aSMatthew G. Knepley /* Use grid sequencing to adapt */ 48577c88af5aSMatthew G. Knepley num = 0; 48589566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_sequence", &num, NULL)); 48597c88af5aSMatthew G. Knepley if (num) { 48607c88af5aSMatthew G. Knepley DMAdaptor adaptor; 4861e03fd340SMatthew G. Knepley const char *prefix; 48627c88af5aSMatthew G. Knepley 48637c88af5aSMatthew G. Knepley incall = PETSC_TRUE; 48649566063dSJacob Faibussowitsch PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor)); 4865e03fd340SMatthew G. Knepley PetscCall(SNESGetOptionsPrefix(snes, &prefix)); 4866e03fd340SMatthew G. Knepley PetscCall(DMAdaptorSetOptionsPrefix(adaptor, prefix)); 48679566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSolver(adaptor, snes)); 48689566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSequenceLength(adaptor, num)); 48699566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetFromOptions(adaptor)); 48709566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetUp(adaptor)); 4871e5148a0bSMatthew G. Knepley PetscCall(PetscObjectViewFromOptions((PetscObject)adaptor, NULL, "-snes_adapt_view")); 48729566063dSJacob Faibussowitsch PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x)); 48739566063dSJacob Faibussowitsch PetscCall(DMAdaptorDestroy(&adaptor)); 48747c88af5aSMatthew G. Knepley incall = PETSC_FALSE; 48757c88af5aSMatthew G. Knepley } 487606fc46c8SMatthew G. Knepley } 487706fc46c8SMatthew G. Knepley } 4878ad540459SPierre Jolivet if (!x) x = snes->vec_sol; 4879caa4e7f2SJed Brown if (!x) { 48809566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 48819566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dm, &xcreated)); 4882a69afd8bSBarry Smith x = xcreated; 4883a69afd8bSBarry Smith } 48849566063dSJacob Faibussowitsch PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view_pre")); 4885f05ece33SBarry Smith 48869566063dSJacob Faibussowitsch for (grid = 0; grid < snes->gridsequence; grid++) PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)))); 4887efd51863SBarry Smith for (grid = 0; grid < snes->gridsequence + 1; grid++) { 488885385478SLisandro Dalcin /* set solution vector */ 48899566063dSJacob Faibussowitsch if (!grid) PetscCall(PetscObjectReference((PetscObject)x)); 48909566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol)); 489185385478SLisandro Dalcin snes->vec_sol = x; 48929566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 4893caa4e7f2SJed Brown 4894caa4e7f2SJed Brown /* set affine vector if provided */ 48959566063dSJacob Faibussowitsch if (b) PetscCall(PetscObjectReference((PetscObject)b)); 48969566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_rhs)); 489785385478SLisandro Dalcin snes->vec_rhs = b; 489885385478SLisandro Dalcin 48995f80ce2aSJacob Faibussowitsch if (snes->vec_rhs) PetscCheck(snes->vec_func != snes->vec_rhs, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Right hand side vector cannot be function vector"); 49005f80ce2aSJacob Faibussowitsch PetscCheck(snes->vec_func != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be function vector"); 4901dd8e379bSPierre Jolivet PetscCheck(snes->vec_rhs != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be right-hand side vector"); 4902aa624791SPierre Jolivet if (!snes->vec_sol_update /* && snes->vec_sol */) PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_sol_update)); 49039566063dSJacob Faibussowitsch PetscCall(DMShellSetGlobalVector(dm, snes->vec_sol)); 49049566063dSJacob Faibussowitsch PetscCall(SNESSetUp(snes)); 49053f149594SLisandro Dalcin 49067eee914bSBarry Smith if (!grid) { 49079927e4dfSBarry Smith if (snes->ops->computeinitialguess) PetscCallBack("SNES callback compute initial guess", (*snes->ops->computeinitialguess)(snes, snes->vec_sol, snes->initialguessP)); 4908dd568438SSatish Balay } 4909d25893d9SBarry Smith 4910abc0a331SBarry Smith if (snes->conv_hist_reset) snes->conv_hist_len = 0; 491112b1dd1aSStefano Zampini PetscCall(SNESResetCounters(snes)); 49122d157150SStefano Zampini snes->reason = SNES_CONVERGED_ITERATING; 49139566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_Solve, snes, 0, 0, 0)); 4914dbbe0bcdSBarry Smith PetscUseTypeMethod(snes, solve); 49159566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_Solve, snes, 0, 0, 0)); 49162d157150SStefano Zampini PetscCheck(snes->reason, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error, solver %s returned without setting converged reason", ((PetscObject)snes)->type_name); 4917*76c63389SBarry Smith snes->functiondomainerror = PETSC_FALSE; /* clear the flag if it has been set */ 4918*76c63389SBarry Smith snes->objectivedomainerror = PETSC_FALSE; /* clear the flag if it has been set */ 4919*76c63389SBarry Smith snes->jacobiandomainerror = PETSC_FALSE; /* clear the flag if it has been set */ 49203f149594SLisandro Dalcin 492137ec4e1aSPeter Brune if (snes->lagjac_persist) snes->jac_iter += snes->iter; 492237ec4e1aSPeter Brune if (snes->lagpre_persist) snes->pre_iter += snes->iter; 492337ec4e1aSPeter Brune 4924648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_test_local_min", NULL, NULL, &flg)); 49259566063dSJacob Faibussowitsch if (flg && !PetscPreLoadingOn) PetscCall(SNESTestLocalMin(snes)); 4926c4421ceaSFande Kong /* Call converged reason views. This may involve user-provided viewers as well */ 49279566063dSJacob Faibussowitsch PetscCall(SNESConvergedReasonViewFromOptions(snes)); 49285968eb51SBarry Smith 49291b3000acSStefano Zampini if (snes->errorifnotconverged) { 49301b3000acSStefano Zampini if (snes->reason < 0) PetscCall(SNESMonitorCancel(snes)); 49311b3000acSStefano Zampini PetscCheck(snes->reason >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_NOT_CONVERGED, "SNESSolve has not converged"); 49321b3000acSStefano Zampini } 49339c8e83a9SBarry Smith if (snes->reason < 0) break; 4934efd51863SBarry Smith if (grid < snes->gridsequence) { 4935efd51863SBarry Smith DM fine; 4936efd51863SBarry Smith Vec xnew; 4937efd51863SBarry Smith Mat interp; 4938efd51863SBarry Smith 49399566063dSJacob Faibussowitsch PetscCall(DMRefine(snes->dm, PetscObjectComm((PetscObject)snes), &fine)); 49405f80ce2aSJacob Faibussowitsch PetscCheck(fine, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_INCOMP, "DMRefine() did not perform any refinement, cannot continue grid sequencing"); 49412eace19aSMatthew G. Knepley PetscCall(DMGetCoordinatesLocalSetUp(fine)); 49429566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(snes->dm, fine, &interp, NULL)); 49439566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(fine, &xnew)); 49449566063dSJacob Faibussowitsch PetscCall(MatInterpolate(interp, x, xnew)); 49459566063dSJacob Faibussowitsch PetscCall(DMInterpolate(snes->dm, interp, fine)); 49469566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interp)); 4947efd51863SBarry Smith x = xnew; 4948efd51863SBarry Smith 49499566063dSJacob Faibussowitsch PetscCall(SNESReset(snes)); 49509566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes, fine)); 49519566063dSJacob Faibussowitsch PetscCall(SNESResetFromOptions(snes)); 49529566063dSJacob Faibussowitsch PetscCall(DMDestroy(&fine)); 49539566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)))); 4954efd51863SBarry Smith } 4955efd51863SBarry Smith } 49569566063dSJacob Faibussowitsch PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view")); 49579566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(snes->vec_sol, (PetscObject)snes, "-snes_view_solution")); 49589566063dSJacob Faibussowitsch PetscCall(DMMonitor(snes->dm)); 49599566063dSJacob Faibussowitsch PetscCall(SNESMonitorPauseFinal_Internal(snes)); 49603f7e2da0SPeter Brune 49619566063dSJacob Faibussowitsch PetscCall(VecDestroy(&xcreated)); 49629566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsBlock((PetscObject)snes)); 49633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49649b94acceSBarry Smith } 49659b94acceSBarry Smith 49669b94acceSBarry Smith /* --------- Internal routines for SNES Package --------- */ 49679b94acceSBarry Smith 4968cc4c1da9SBarry Smith /*@ 49690b4b7b1cSBarry Smith SNESSetType - Sets the algorithm/method to be used to solve the nonlinear system with the given `SNES` 49709b94acceSBarry Smith 4971c3339decSBarry Smith Collective 4972fee21e36SBarry Smith 4973c7afd0dbSLois Curfman McInnes Input Parameters: 4974f6dfbefdSBarry Smith + snes - the `SNES` context 4975454a90a3SBarry Smith - type - a known method 4976c7afd0dbSLois Curfman McInnes 4977c7afd0dbSLois Curfman McInnes Options Database Key: 4978454a90a3SBarry Smith . -snes_type <type> - Sets the method; use -help for a list 497904d7464bSBarry Smith of available methods (for instance, newtonls or newtontr) 4980ae12b187SLois Curfman McInnes 4981dc4c0fb0SBarry Smith Level: intermediate 4982dc4c0fb0SBarry Smith 49839b94acceSBarry Smith Notes: 49840b4b7b1cSBarry Smith See `SNESType` for available methods (for instance) 4985f6dfbefdSBarry Smith + `SNESNEWTONLS` - Newton's method with line search 4986c7afd0dbSLois Curfman McInnes (systems of nonlinear equations) 49874a221d59SStefano Zampini - `SNESNEWTONTR` - Newton's method with trust region 4988c7afd0dbSLois Curfman McInnes (systems of nonlinear equations) 49899b94acceSBarry Smith 4990f6dfbefdSBarry Smith Normally, it is best to use the `SNESSetFromOptions()` command and then 4991f6dfbefdSBarry Smith set the `SNES` solver type from the options database rather than by using 4992ae12b187SLois Curfman McInnes this routine. Using the options database provides the user with 4993ae12b187SLois Curfman McInnes maximum flexibility in evaluating the many nonlinear solvers. 4994f6dfbefdSBarry Smith The `SNESSetType()` routine is provided for those situations where it 4995ae12b187SLois Curfman McInnes is necessary to set the nonlinear solver independently of the command 4996ae12b187SLois Curfman McInnes line or options database. This might be the case, for example, when 4997ae12b187SLois Curfman McInnes the choice of solver changes during the execution of the program, 4998ae12b187SLois Curfman McInnes and the user's application is taking responsibility for choosing the 4999b0a32e0cSBarry Smith appropriate method. 500036851e7fSLois Curfman McInnes 5001420bcc1bSBarry Smith Developer Note: 5002f6dfbefdSBarry Smith `SNESRegister()` adds a constructor for a new `SNESType` to `SNESList`, `SNESSetType()` locates 5003f6dfbefdSBarry Smith the constructor in that list and calls it to create the specific object. 50048f6c3df8SBarry Smith 50051cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESType`, `SNESCreate()`, `SNESDestroy()`, `SNESGetType()`, `SNESSetFromOptions()` 50069b94acceSBarry Smith @*/ 5007d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetType(SNES snes, SNESType type) 5008d71ae5a4SJacob Faibussowitsch { 5009ace3abfcSBarry Smith PetscBool match; 50105f80ce2aSJacob Faibussowitsch PetscErrorCode (*r)(SNES); 50113a40ed3dSBarry Smith 50123a40ed3dSBarry Smith PetscFunctionBegin; 50130700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 50144f572ea9SToby Isaac PetscAssertPointer(type, 2); 501582bf6240SBarry Smith 50169566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes, type, &match)); 50173ba16761SJacob Faibussowitsch if (match) PetscFunctionReturn(PETSC_SUCCESS); 501892ff6ae8SBarry Smith 50199566063dSJacob Faibussowitsch PetscCall(PetscFunctionListFind(SNESList, type, &r)); 50206adde796SStefano Zampini PetscCheck(r, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested SNES type %s", type); 502175396ef9SLisandro Dalcin /* Destroy the previous private SNES context */ 5022dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, destroy); 502343547594SStefano Zampini /* Reinitialize type-specific function pointers in SNESOps structure */ 502443547594SStefano Zampini snes->ops->reset = NULL; 50259e5d0892SLisandro Dalcin snes->ops->setup = NULL; 50269e5d0892SLisandro Dalcin snes->ops->solve = NULL; 50279e5d0892SLisandro Dalcin snes->ops->view = NULL; 50289e5d0892SLisandro Dalcin snes->ops->setfromoptions = NULL; 50299e5d0892SLisandro Dalcin snes->ops->destroy = NULL; 50307fe760d5SStefano Zampini 50317fe760d5SStefano Zampini /* It may happen the user has customized the line search before calling SNESSetType */ 50329566063dSJacob Faibussowitsch if (((PetscObject)snes)->type_name) PetscCall(SNESLineSearchDestroy(&snes->linesearch)); 50337fe760d5SStefano Zampini 503475396ef9SLisandro Dalcin /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */ 503575396ef9SLisandro Dalcin snes->setupcalled = PETSC_FALSE; 5036f5af7f23SKarl Rupp 50379566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)snes, type)); 50389566063dSJacob Faibussowitsch PetscCall((*r)(snes)); 50393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50409b94acceSBarry Smith } 50419b94acceSBarry Smith 5042cc4c1da9SBarry Smith /*@ 5043f6dfbefdSBarry Smith SNESGetType - Gets the `SNES` method type and name (as a string). 50449b94acceSBarry Smith 5045c7afd0dbSLois Curfman McInnes Not Collective 5046c7afd0dbSLois Curfman McInnes 50479b94acceSBarry Smith Input Parameter: 50484b0e389bSBarry Smith . snes - nonlinear solver context 50499b94acceSBarry Smith 50509b94acceSBarry Smith Output Parameter: 5051f6dfbefdSBarry Smith . type - `SNES` method (a character string) 50529b94acceSBarry Smith 505336851e7fSLois Curfman McInnes Level: intermediate 505436851e7fSLois Curfman McInnes 50551cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetType()`, `SNESType`, `SNESSetFromOptions()`, `SNES` 50569b94acceSBarry Smith @*/ 5057d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetType(SNES snes, SNESType *type) 5058d71ae5a4SJacob Faibussowitsch { 50593a40ed3dSBarry Smith PetscFunctionBegin; 50600700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 50614f572ea9SToby Isaac PetscAssertPointer(type, 2); 50627adad957SLisandro Dalcin *type = ((PetscObject)snes)->type_name; 50633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50649b94acceSBarry Smith } 50659b94acceSBarry Smith 50663cd8a7caSMatthew G. Knepley /*@ 5067f6dfbefdSBarry Smith SNESSetSolution - Sets the solution vector for use by the `SNES` routines. 50683cd8a7caSMatthew G. Knepley 5069c3339decSBarry Smith Logically Collective 50703cd8a7caSMatthew G. Knepley 50713cd8a7caSMatthew G. Knepley Input Parameters: 5072f6dfbefdSBarry Smith + snes - the `SNES` context obtained from `SNESCreate()` 50733cd8a7caSMatthew G. Knepley - u - the solution vector 50743cd8a7caSMatthew G. Knepley 50753cd8a7caSMatthew G. Knepley Level: beginner 50763cd8a7caSMatthew G. Knepley 50771cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetSolution()`, `Vec` 50783cd8a7caSMatthew G. Knepley @*/ 5079d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetSolution(SNES snes, Vec u) 5080d71ae5a4SJacob Faibussowitsch { 50813cd8a7caSMatthew G. Knepley DM dm; 50823cd8a7caSMatthew G. Knepley 50833cd8a7caSMatthew G. Knepley PetscFunctionBegin; 50843cd8a7caSMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 50853cd8a7caSMatthew G. Knepley PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 50869566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)u)); 50879566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol)); 50883cd8a7caSMatthew G. Knepley 50893cd8a7caSMatthew G. Knepley snes->vec_sol = u; 50903cd8a7caSMatthew G. Knepley 50919566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 50929566063dSJacob Faibussowitsch PetscCall(DMShellSetGlobalVector(dm, u)); 50933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50943cd8a7caSMatthew G. Knepley } 50953cd8a7caSMatthew G. Knepley 509652baeb72SSatish Balay /*@ 50979b94acceSBarry Smith SNESGetSolution - Returns the vector where the approximate solution is 5098f6dfbefdSBarry Smith stored. This is the fine grid solution when using `SNESSetGridSequence()`. 50999b94acceSBarry Smith 5100420bcc1bSBarry Smith Not Collective, but `x` is parallel if `snes` is parallel 5101c7afd0dbSLois Curfman McInnes 51029b94acceSBarry Smith Input Parameter: 5103f6dfbefdSBarry Smith . snes - the `SNES` context 51049b94acceSBarry Smith 51059b94acceSBarry Smith Output Parameter: 51069b94acceSBarry Smith . x - the solution 51079b94acceSBarry Smith 510870e92668SMatthew Knepley Level: intermediate 510936851e7fSLois Curfman McInnes 51101cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetSolution()`, `SNESSolve()`, `SNES`, `SNESGetSolutionUpdate()`, `SNESGetFunction()` 51119b94acceSBarry Smith @*/ 5112d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolution(SNES snes, Vec *x) 5113d71ae5a4SJacob Faibussowitsch { 51143a40ed3dSBarry Smith PetscFunctionBegin; 51150700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 51164f572ea9SToby Isaac PetscAssertPointer(x, 2); 511785385478SLisandro Dalcin *x = snes->vec_sol; 51183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 511970e92668SMatthew Knepley } 512070e92668SMatthew Knepley 512152baeb72SSatish Balay /*@ 51229b94acceSBarry Smith SNESGetSolutionUpdate - Returns the vector where the solution update is 51239b94acceSBarry Smith stored. 51249b94acceSBarry Smith 5125420bcc1bSBarry Smith Not Collective, but `x` is parallel if `snes` is parallel 5126c7afd0dbSLois Curfman McInnes 51279b94acceSBarry Smith Input Parameter: 5128f6dfbefdSBarry Smith . snes - the `SNES` context 51299b94acceSBarry Smith 51309b94acceSBarry Smith Output Parameter: 51319b94acceSBarry Smith . x - the solution update 51329b94acceSBarry Smith 513336851e7fSLois Curfman McInnes Level: advanced 513436851e7fSLois Curfman McInnes 51351cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()` 51369b94acceSBarry Smith @*/ 5137d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionUpdate(SNES snes, Vec *x) 5138d71ae5a4SJacob Faibussowitsch { 51393a40ed3dSBarry Smith PetscFunctionBegin; 51400700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 51414f572ea9SToby Isaac PetscAssertPointer(x, 2); 514285385478SLisandro Dalcin *x = snes->vec_sol_update; 51433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 51449b94acceSBarry Smith } 51459b94acceSBarry Smith 51469b94acceSBarry Smith /*@C 5147f6dfbefdSBarry Smith SNESGetFunction - Returns the function that defines the nonlinear system set with `SNESSetFunction()` 51489b94acceSBarry Smith 5149420bcc1bSBarry Smith Not Collective, but `r` is parallel if `snes` is parallel. Collective if `r` is requested, but has not been created yet. 5150c7afd0dbSLois Curfman McInnes 51519b94acceSBarry Smith Input Parameter: 5152f6dfbefdSBarry Smith . snes - the `SNES` context 51539b94acceSBarry Smith 5154d8d19677SJose E. Roman Output Parameters: 5155dc4c0fb0SBarry Smith + r - the vector that is used to store residuals (or `NULL` if you don't want it) 51568434afd1SBarry Smith . f - the function (or `NULL` if you don't want it); for calling sequence see `SNESFunctionFn` 5157dc4c0fb0SBarry Smith - ctx - the function context (or `NULL` if you don't want it) 51589b94acceSBarry Smith 515936851e7fSLois Curfman McInnes Level: advanced 516036851e7fSLois Curfman McInnes 5161f6dfbefdSBarry Smith Note: 5162dc4c0fb0SBarry Smith The vector `r` DOES NOT, in general, contain the current value of the `SNES` nonlinear function 516304edfde5SBarry Smith 51648434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetSolution()`, `SNESFunctionFn` 51659b94acceSBarry Smith @*/ 51668434afd1SBarry Smith PetscErrorCode SNESGetFunction(SNES snes, Vec *r, SNESFunctionFn **f, void **ctx) 5167d71ae5a4SJacob Faibussowitsch { 51686cab3a1bSJed Brown DM dm; 5169a63bb30eSJed Brown 51703a40ed3dSBarry Smith PetscFunctionBegin; 51710700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5172a63bb30eSJed Brown if (r) { 5173a63bb30eSJed Brown if (!snes->vec_func) { 5174a63bb30eSJed Brown if (snes->vec_rhs) { 51759566063dSJacob Faibussowitsch PetscCall(VecDuplicate(snes->vec_rhs, &snes->vec_func)); 5176a63bb30eSJed Brown } else if (snes->vec_sol) { 51779566063dSJacob Faibussowitsch PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_func)); 5178a63bb30eSJed Brown } else if (snes->dm) { 51799566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(snes->dm, &snes->vec_func)); 5180a63bb30eSJed Brown } 5181a63bb30eSJed Brown } 5182a63bb30eSJed Brown *r = snes->vec_func; 5183a63bb30eSJed Brown } 51849566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 51859566063dSJacob Faibussowitsch PetscCall(DMSNESGetFunction(dm, f, ctx)); 51863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 51879b94acceSBarry Smith } 51889b94acceSBarry Smith 5189c79ef259SPeter Brune /*@C 519037fdd005SBarry Smith SNESGetNGS - Returns the function and context set with `SNESSetNGS()` 5191c79ef259SPeter Brune 5192c79ef259SPeter Brune Input Parameter: 5193f6dfbefdSBarry Smith . snes - the `SNES` context 5194c79ef259SPeter Brune 5195d8d19677SJose E. Roman Output Parameters: 51968434afd1SBarry Smith + f - the function (or `NULL`) see `SNESNGSFn` for calling sequence 5197dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`) 5198c79ef259SPeter Brune 5199c79ef259SPeter Brune Level: advanced 5200c79ef259SPeter Brune 52018434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetNGS()`, `SNESGetFunction()`, `SNESNGSFn` 5202c79ef259SPeter Brune @*/ 52038434afd1SBarry Smith PetscErrorCode SNESGetNGS(SNES snes, SNESNGSFn **f, void **ctx) 5204d71ae5a4SJacob Faibussowitsch { 52056cab3a1bSJed Brown DM dm; 52066cab3a1bSJed Brown 5207646217ecSPeter Brune PetscFunctionBegin; 5208646217ecSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 52099566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 52109566063dSJacob Faibussowitsch PetscCall(DMSNESGetNGS(dm, f, ctx)); 52113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5212646217ecSPeter Brune } 5213646217ecSPeter Brune 5214cc4c1da9SBarry Smith /*@ 52153c7409f5SSatish Balay SNESSetOptionsPrefix - Sets the prefix used for searching for all 5216f6dfbefdSBarry Smith `SNES` options in the database. 52173c7409f5SSatish Balay 5218c3339decSBarry Smith Logically Collective 5219fee21e36SBarry Smith 5220d8d19677SJose E. Roman Input Parameters: 5221f6dfbefdSBarry Smith + snes - the `SNES` context 5222c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names 5223c7afd0dbSLois Curfman McInnes 5224dc4c0fb0SBarry Smith Level: advanced 5225dc4c0fb0SBarry Smith 5226f6dfbefdSBarry Smith Note: 5227a83b1b31SSatish Balay A hyphen (-) must NOT be given at the beginning of the prefix name. 5228c7afd0dbSLois Curfman McInnes The first character of all runtime options is AUTOMATICALLY the hyphen. 5229d850072dSLois Curfman McInnes 52301cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESAppendOptionsPrefix()` 52313c7409f5SSatish Balay @*/ 5232d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetOptionsPrefix(SNES snes, const char prefix[]) 5233d71ae5a4SJacob Faibussowitsch { 52343a40ed3dSBarry Smith PetscFunctionBegin; 52350700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 52369566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes, prefix)); 52379566063dSJacob Faibussowitsch if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 523835f5d045SPeter Brune if (snes->linesearch) { 52399566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 52409566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch, prefix)); 524135f5d045SPeter Brune } 52429566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(snes->ksp, prefix)); 52433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 52443c7409f5SSatish Balay } 52453c7409f5SSatish Balay 5246cc4c1da9SBarry Smith /*@ 5247f525115eSLois Curfman McInnes SNESAppendOptionsPrefix - Appends to the prefix used for searching for all 5248f6dfbefdSBarry Smith `SNES` options in the database. 52493c7409f5SSatish Balay 5250c3339decSBarry Smith Logically Collective 5251fee21e36SBarry Smith 5252c7afd0dbSLois Curfman McInnes Input Parameters: 5253f6dfbefdSBarry Smith + snes - the `SNES` context 5254c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names 5255c7afd0dbSLois Curfman McInnes 5256dc4c0fb0SBarry Smith Level: advanced 5257dc4c0fb0SBarry Smith 5258f6dfbefdSBarry Smith Note: 5259a83b1b31SSatish Balay A hyphen (-) must NOT be given at the beginning of the prefix name. 5260c7afd0dbSLois Curfman McInnes The first character of all runtime options is AUTOMATICALLY the hyphen. 5261d850072dSLois Curfman McInnes 52621cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetOptionsPrefix()`, `SNESSetOptionsPrefix()` 52633c7409f5SSatish Balay @*/ 5264d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESAppendOptionsPrefix(SNES snes, const char prefix[]) 5265d71ae5a4SJacob Faibussowitsch { 52663a40ed3dSBarry Smith PetscFunctionBegin; 52670700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 52689566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes, prefix)); 52699566063dSJacob Faibussowitsch if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 527035f5d045SPeter Brune if (snes->linesearch) { 52719566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 52729566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch, prefix)); 527335f5d045SPeter Brune } 52749566063dSJacob Faibussowitsch PetscCall(KSPAppendOptionsPrefix(snes->ksp, prefix)); 52753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 52763c7409f5SSatish Balay } 52773c7409f5SSatish Balay 5278cc4c1da9SBarry Smith /*@ 5279f6dfbefdSBarry Smith SNESGetOptionsPrefix - Gets the prefix used for searching for all 5280f6dfbefdSBarry Smith `SNES` options in the database. 52813c7409f5SSatish Balay 5282c7afd0dbSLois Curfman McInnes Not Collective 5283c7afd0dbSLois Curfman McInnes 52843c7409f5SSatish Balay Input Parameter: 5285f6dfbefdSBarry Smith . snes - the `SNES` context 52863c7409f5SSatish Balay 52873c7409f5SSatish Balay Output Parameter: 52883c7409f5SSatish Balay . prefix - pointer to the prefix string used 52893c7409f5SSatish Balay 529036851e7fSLois Curfman McInnes Level: advanced 529136851e7fSLois Curfman McInnes 52921cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetOptionsPrefix()`, `SNESAppendOptionsPrefix()` 52933c7409f5SSatish Balay @*/ 5294d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetOptionsPrefix(SNES snes, const char *prefix[]) 5295d71ae5a4SJacob Faibussowitsch { 52963a40ed3dSBarry Smith PetscFunctionBegin; 52970700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 52989566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)snes, prefix)); 52993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 53003c7409f5SSatish Balay } 53013c7409f5SSatish Balay 53023cea93caSBarry Smith /*@C 53031c84c290SBarry Smith SNESRegister - Adds a method to the nonlinear solver package. 53041c84c290SBarry Smith 530520f4b53cSBarry Smith Not Collective 53061c84c290SBarry Smith 53071c84c290SBarry Smith Input Parameters: 530820f4b53cSBarry Smith + sname - name of a new user-defined solver 530920f4b53cSBarry Smith - function - routine to create method context 53101c84c290SBarry Smith 5311dc4c0fb0SBarry Smith Level: advanced 5312dc4c0fb0SBarry Smith 5313f6dfbefdSBarry Smith Note: 5314f6dfbefdSBarry Smith `SNESRegister()` may be called multiple times to add several user-defined solvers. 53151c84c290SBarry Smith 5316e4094ef1SJacob Faibussowitsch Example Usage: 53171c84c290SBarry Smith .vb 5318bdf89e91SBarry Smith SNESRegister("my_solver", MySolverCreate); 53191c84c290SBarry Smith .ve 53201c84c290SBarry Smith 53211c84c290SBarry Smith Then, your solver can be chosen with the procedural interface via 5322b44f4de4SBarry Smith .vb 5323b44f4de4SBarry Smith SNESSetType(snes, "my_solver") 5324b44f4de4SBarry Smith .ve 53251c84c290SBarry Smith or at runtime via the option 5326b44f4de4SBarry Smith .vb 5327b44f4de4SBarry Smith -snes_type my_solver 5328b44f4de4SBarry Smith .ve 53291c84c290SBarry Smith 53301cc06b55SBarry Smith .seealso: [](ch_snes), `SNESRegisterAll()`, `SNESRegisterDestroy()` 53313cea93caSBarry Smith @*/ 5332d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESRegister(const char sname[], PetscErrorCode (*function)(SNES)) 5333d71ae5a4SJacob Faibussowitsch { 5334b2002411SLois Curfman McInnes PetscFunctionBegin; 53359566063dSJacob Faibussowitsch PetscCall(SNESInitializePackage()); 53369566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&SNESList, sname, function)); 53373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5338b2002411SLois Curfman McInnes } 5339da9b6338SBarry Smith 5340d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestLocalMin(SNES snes) 5341d71ae5a4SJacob Faibussowitsch { 534277431f27SBarry Smith PetscInt N, i, j; 5343da9b6338SBarry Smith Vec u, uh, fh; 5344da9b6338SBarry Smith PetscScalar value; 5345da9b6338SBarry Smith PetscReal norm; 5346da9b6338SBarry Smith 5347da9b6338SBarry Smith PetscFunctionBegin; 53489566063dSJacob Faibussowitsch PetscCall(SNESGetSolution(snes, &u)); 53499566063dSJacob Faibussowitsch PetscCall(VecDuplicate(u, &uh)); 53509566063dSJacob Faibussowitsch PetscCall(VecDuplicate(u, &fh)); 5351da9b6338SBarry Smith 5352da9b6338SBarry Smith /* currently only works for sequential */ 53539566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Testing FormFunction() for local min\n")); 53549566063dSJacob Faibussowitsch PetscCall(VecGetSize(u, &N)); 5355da9b6338SBarry Smith for (i = 0; i < N; i++) { 53569566063dSJacob Faibussowitsch PetscCall(VecCopy(u, uh)); 535763a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "i = %" PetscInt_FMT "\n", i)); 5358da9b6338SBarry Smith for (j = -10; j < 11; j++) { 53598b49ba18SBarry Smith value = PetscSign(j) * PetscExpReal(PetscAbs(j) - 10.0); 53609566063dSJacob Faibussowitsch PetscCall(VecSetValue(uh, i, value, ADD_VALUES)); 53619566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, uh, fh)); 5362*76c63389SBarry Smith PetscCall(VecNorm(fh, NORM_2, &norm)); /* does not handle use of SNESSetFunctionDomainError() correctly */ 536363a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), " j norm %" PetscInt_FMT " %18.16e\n", j, (double)norm)); 5364da9b6338SBarry Smith value = -value; 53659566063dSJacob Faibussowitsch PetscCall(VecSetValue(uh, i, value, ADD_VALUES)); 5366da9b6338SBarry Smith } 5367da9b6338SBarry Smith } 53689566063dSJacob Faibussowitsch PetscCall(VecDestroy(&uh)); 53699566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fh)); 53703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5371da9b6338SBarry Smith } 537271f87433Sdalcinl 537371f87433Sdalcinl /*@ 5374*76c63389SBarry Smith SNESGetLineSearch - Returns the line search associated with the `SNES`. 5375*76c63389SBarry Smith 5376*76c63389SBarry Smith Not Collective 5377*76c63389SBarry Smith 5378*76c63389SBarry Smith Input Parameter: 5379*76c63389SBarry Smith . snes - iterative context obtained from `SNESCreate()` 5380*76c63389SBarry Smith 5381*76c63389SBarry Smith Output Parameter: 5382*76c63389SBarry Smith . linesearch - linesearch context 5383*76c63389SBarry Smith 5384*76c63389SBarry Smith Level: beginner 5385*76c63389SBarry Smith 5386*76c63389SBarry Smith Notes: 5387*76c63389SBarry Smith It creates a default line search instance which can be configured as needed in case it has not been already set with `SNESSetLineSearch()`. 5388*76c63389SBarry Smith 5389*76c63389SBarry Smith You can also use the options database keys `-snes_linesearch_*` to configure the line search. See `SNESLineSearchSetFromOptions()` for the possible options. 5390*76c63389SBarry Smith 5391*76c63389SBarry Smith .seealso: [](ch_snes), `SNESLineSearch`, `SNESSetLineSearch()`, `SNESLineSearchCreate()`, `SNESLineSearchSetFromOptions()` 5392*76c63389SBarry Smith @*/ 5393*76c63389SBarry Smith PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch) 5394*76c63389SBarry Smith { 5395*76c63389SBarry Smith const char *optionsprefix; 5396*76c63389SBarry Smith 5397*76c63389SBarry Smith PetscFunctionBegin; 5398*76c63389SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5399*76c63389SBarry Smith PetscAssertPointer(linesearch, 2); 5400*76c63389SBarry Smith if (!snes->linesearch) { 5401*76c63389SBarry Smith PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 5402*76c63389SBarry Smith PetscCall(SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch)); 5403*76c63389SBarry Smith PetscCall(SNESLineSearchSetSNES(snes->linesearch, snes)); 5404*76c63389SBarry Smith PetscCall(SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix)); 5405*76c63389SBarry Smith PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->linesearch, (PetscObject)snes, 1)); 5406*76c63389SBarry Smith } 5407*76c63389SBarry Smith *linesearch = snes->linesearch; 5408*76c63389SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 5409*76c63389SBarry Smith } 5410*76c63389SBarry Smith 5411*76c63389SBarry Smith /*@ 5412f6dfbefdSBarry Smith SNESKSPSetUseEW - Sets `SNES` to the use Eisenstat-Walker method for 541371f87433Sdalcinl computing relative tolerance for linear solvers within an inexact 541471f87433Sdalcinl Newton method. 541571f87433Sdalcinl 5416c3339decSBarry Smith Logically Collective 541771f87433Sdalcinl 541871f87433Sdalcinl Input Parameters: 5419f6dfbefdSBarry Smith + snes - `SNES` context 5420f6dfbefdSBarry Smith - flag - `PETSC_TRUE` or `PETSC_FALSE` 542171f87433Sdalcinl 5422f6dfbefdSBarry Smith Options Database Keys: 542364ba62caSBarry Smith + -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence 542464ba62caSBarry Smith . -snes_ksp_ew_version ver - version of Eisenstat-Walker method 542564ba62caSBarry Smith . -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0 542664ba62caSBarry Smith . -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax 542764ba62caSBarry Smith . -snes_ksp_ew_gamma <gamma> - Sets gamma 542864ba62caSBarry Smith . -snes_ksp_ew_alpha <alpha> - Sets alpha 542964ba62caSBarry Smith . -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2 543064ba62caSBarry Smith - -snes_ksp_ew_threshold <threshold> - Sets threshold 543164ba62caSBarry Smith 5432dc4c0fb0SBarry Smith Level: advanced 5433dc4c0fb0SBarry Smith 5434f6dfbefdSBarry Smith Note: 5435f6dfbefdSBarry Smith The default is to use a constant relative tolerance for 543671f87433Sdalcinl the inner linear solvers. Alternatively, one can use the 54371d27aa22SBarry Smith Eisenstat-Walker method {cite}`ew96`, where the relative convergence tolerance 543871f87433Sdalcinl is reset at each Newton iteration according progress of the nonlinear 543971f87433Sdalcinl solver. 544071f87433Sdalcinl 54411cc06b55SBarry Smith .seealso: [](ch_snes), `KSP`, `SNES`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()` 544271f87433Sdalcinl @*/ 5443d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetUseEW(SNES snes, PetscBool flag) 5444d71ae5a4SJacob Faibussowitsch { 544571f87433Sdalcinl PetscFunctionBegin; 54460700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5447acfcf0e5SJed Brown PetscValidLogicalCollectiveBool(snes, flag, 2); 544871f87433Sdalcinl snes->ksp_ewconv = flag; 54493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 545071f87433Sdalcinl } 545171f87433Sdalcinl 545271f87433Sdalcinl /*@ 5453f6dfbefdSBarry Smith SNESKSPGetUseEW - Gets if `SNES` is using Eisenstat-Walker method 545471f87433Sdalcinl for computing relative tolerance for linear solvers within an 545571f87433Sdalcinl inexact Newton method. 545671f87433Sdalcinl 545771f87433Sdalcinl Not Collective 545871f87433Sdalcinl 545971f87433Sdalcinl Input Parameter: 5460f6dfbefdSBarry Smith . snes - `SNES` context 546171f87433Sdalcinl 546271f87433Sdalcinl Output Parameter: 5463f6dfbefdSBarry Smith . flag - `PETSC_TRUE` or `PETSC_FALSE` 546471f87433Sdalcinl 546571f87433Sdalcinl Level: advanced 546671f87433Sdalcinl 54671cc06b55SBarry Smith .seealso: [](ch_snes), `SNESKSPSetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()` 546871f87433Sdalcinl @*/ 5469d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag) 5470d71ae5a4SJacob Faibussowitsch { 547171f87433Sdalcinl PetscFunctionBegin; 54720700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 54734f572ea9SToby Isaac PetscAssertPointer(flag, 2); 547471f87433Sdalcinl *flag = snes->ksp_ewconv; 54753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 547671f87433Sdalcinl } 547771f87433Sdalcinl 547871f87433Sdalcinl /*@ 5479fa9f3622SBarry Smith SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker 548071f87433Sdalcinl convergence criteria for the linear solvers within an inexact 548171f87433Sdalcinl Newton method. 548271f87433Sdalcinl 5483c3339decSBarry Smith Logically Collective 548471f87433Sdalcinl 548571f87433Sdalcinl Input Parameters: 5486f6dfbefdSBarry Smith + snes - `SNES` context 54870f0abf79SStefano Zampini . version - version 1, 2 (default is 2), 3 or 4 548871f87433Sdalcinl . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 548971f87433Sdalcinl . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 549071f87433Sdalcinl . gamma - multiplicative factor for version 2 rtol computation 549171f87433Sdalcinl (0 <= gamma2 <= 1) 549271f87433Sdalcinl . alpha - power for version 2 rtol computation (1 < alpha <= 2) 549371f87433Sdalcinl . alpha2 - power for safeguard 549471f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1) 549571f87433Sdalcinl 5496dc4c0fb0SBarry Smith Level: advanced 5497dc4c0fb0SBarry Smith 5498f6dfbefdSBarry Smith Notes: 549971f87433Sdalcinl Version 3 was contributed by Luis Chacon, June 2006. 550071f87433Sdalcinl 550177e5a1f9SBarry Smith Use `PETSC_CURRENT` to retain the default for any of the parameters. 550271f87433Sdalcinl 55031cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()` 550471f87433Sdalcinl @*/ 5505d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetParametersEW(SNES snes, PetscInt version, PetscReal rtol_0, PetscReal rtol_max, PetscReal gamma, PetscReal alpha, PetscReal alpha2, PetscReal threshold) 5506d71ae5a4SJacob Faibussowitsch { 5507fa9f3622SBarry Smith SNESKSPEW *kctx; 55085fd66863SKarl Rupp 550971f87433Sdalcinl PetscFunctionBegin; 55100700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5511fa9f3622SBarry Smith kctx = (SNESKSPEW *)snes->kspconvctx; 55125f80ce2aSJacob Faibussowitsch PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing"); 5513c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, version, 2); 5514c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, rtol_0, 3); 5515c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, rtol_max, 4); 5516c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, gamma, 5); 5517c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, alpha, 6); 5518c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, alpha2, 7); 5519c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, threshold, 8); 552071f87433Sdalcinl 552177e5a1f9SBarry Smith if (version != PETSC_CURRENT) kctx->version = version; 552277e5a1f9SBarry Smith if (rtol_0 != (PetscReal)PETSC_CURRENT) kctx->rtol_0 = rtol_0; 552377e5a1f9SBarry Smith if (rtol_max != (PetscReal)PETSC_CURRENT) kctx->rtol_max = rtol_max; 552477e5a1f9SBarry Smith if (gamma != (PetscReal)PETSC_CURRENT) kctx->gamma = gamma; 552577e5a1f9SBarry Smith if (alpha != (PetscReal)PETSC_CURRENT) kctx->alpha = alpha; 552677e5a1f9SBarry Smith if (alpha2 != (PetscReal)PETSC_CURRENT) kctx->alpha2 = alpha2; 552777e5a1f9SBarry Smith if (threshold != (PetscReal)PETSC_CURRENT) kctx->threshold = threshold; 552871f87433Sdalcinl 55290f0abf79SStefano Zampini PetscCheck(kctx->version >= 1 && kctx->version <= 4, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Only versions 1 to 4 are supported: %" PetscInt_FMT, kctx->version); 55300b121fc5SBarry Smith PetscCheck(kctx->rtol_0 >= 0.0 && kctx->rtol_0 < 1.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "0.0 <= rtol_0 < 1.0: %g", (double)kctx->rtol_0); 55310b121fc5SBarry Smith PetscCheck(kctx->rtol_max >= 0.0 && kctx->rtol_max < 1.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "0.0 <= rtol_max (%g) < 1.0", (double)kctx->rtol_max); 55320b121fc5SBarry Smith PetscCheck(kctx->gamma >= 0.0 && kctx->gamma <= 1.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "0.0 <= gamma (%g) <= 1.0", (double)kctx->gamma); 55330b121fc5SBarry Smith PetscCheck(kctx->alpha > 1.0 && kctx->alpha <= 2.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "1.0 < alpha (%g) <= 2.0", (double)kctx->alpha); 55340b121fc5SBarry Smith PetscCheck(kctx->threshold > 0.0 && kctx->threshold < 1.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "0.0 < threshold (%g) < 1.0", (double)kctx->threshold); 55353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 553671f87433Sdalcinl } 553771f87433Sdalcinl 553871f87433Sdalcinl /*@ 5539fa9f3622SBarry Smith SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker 554071f87433Sdalcinl convergence criteria for the linear solvers within an inexact 554171f87433Sdalcinl Newton method. 554271f87433Sdalcinl 554371f87433Sdalcinl Not Collective 554471f87433Sdalcinl 554597bb3fdcSJose E. Roman Input Parameter: 5546f6dfbefdSBarry Smith . snes - `SNES` context 554771f87433Sdalcinl 554871f87433Sdalcinl Output Parameters: 55490f0abf79SStefano Zampini + version - version 1, 2 (default is 2), 3 or 4 555071f87433Sdalcinl . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 555171f87433Sdalcinl . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 5552bf388a1fSBarry Smith . gamma - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1) 555371f87433Sdalcinl . alpha - power for version 2 rtol computation (1 < alpha <= 2) 555471f87433Sdalcinl . alpha2 - power for safeguard 555571f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1) 555671f87433Sdalcinl 555771f87433Sdalcinl Level: advanced 555871f87433Sdalcinl 55591cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPSetParametersEW()` 556071f87433Sdalcinl @*/ 5561d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetParametersEW(SNES snes, PetscInt *version, PetscReal *rtol_0, PetscReal *rtol_max, PetscReal *gamma, PetscReal *alpha, PetscReal *alpha2, PetscReal *threshold) 5562d71ae5a4SJacob Faibussowitsch { 5563fa9f3622SBarry Smith SNESKSPEW *kctx; 55645fd66863SKarl Rupp 556571f87433Sdalcinl PetscFunctionBegin; 55660700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5567fa9f3622SBarry Smith kctx = (SNESKSPEW *)snes->kspconvctx; 55685f80ce2aSJacob Faibussowitsch PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing"); 556971f87433Sdalcinl if (version) *version = kctx->version; 557071f87433Sdalcinl if (rtol_0) *rtol_0 = kctx->rtol_0; 557171f87433Sdalcinl if (rtol_max) *rtol_max = kctx->rtol_max; 557271f87433Sdalcinl if (gamma) *gamma = kctx->gamma; 557371f87433Sdalcinl if (alpha) *alpha = kctx->alpha; 557471f87433Sdalcinl if (alpha2) *alpha2 = kctx->alpha2; 557571f87433Sdalcinl if (threshold) *threshold = kctx->threshold; 55763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 557771f87433Sdalcinl } 557871f87433Sdalcinl 55795c0db29aSPierre Jolivet PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx) 5580d71ae5a4SJacob Faibussowitsch { 55815c0db29aSPierre Jolivet SNES snes = (SNES)ctx; 5582fa9f3622SBarry Smith SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx; 558377e5a1f9SBarry Smith PetscReal rtol = PETSC_CURRENT, stol; 558471f87433Sdalcinl 558571f87433Sdalcinl PetscFunctionBegin; 55863ba16761SJacob Faibussowitsch if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS); 558730058271SDmitry Karpeev if (!snes->iter) { 558830058271SDmitry Karpeev rtol = kctx->rtol_0; /* first time in, so use the original user rtol */ 55899566063dSJacob Faibussowitsch PetscCall(VecNorm(snes->vec_func, NORM_2, &kctx->norm_first)); 55900f0abf79SStefano Zampini } else { 55910fdf79fbSJacob Faibussowitsch PetscCheck(kctx->version >= 1 && kctx->version <= 4, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Only versions 1-4 are supported: %" PetscInt_FMT, kctx->version); 559271f87433Sdalcinl if (kctx->version == 1) { 55930f0abf79SStefano Zampini rtol = PetscAbsReal(snes->norm - kctx->lresid_last) / kctx->norm_last; 559485ec1a3cSBarry Smith stol = PetscPowReal(kctx->rtol_last, kctx->alpha2); 559571f87433Sdalcinl if (stol > kctx->threshold) rtol = PetscMax(rtol, stol); 559671f87433Sdalcinl } else if (kctx->version == 2) { 559785ec1a3cSBarry Smith rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha); 559885ec1a3cSBarry Smith stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha); 559971f87433Sdalcinl if (stol > kctx->threshold) rtol = PetscMax(rtol, stol); 560071f87433Sdalcinl } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */ 560185ec1a3cSBarry Smith rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha); 560271f87433Sdalcinl /* safeguard: avoid sharp decrease of rtol */ 560385ec1a3cSBarry Smith stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha); 560471f87433Sdalcinl stol = PetscMax(rtol, stol); 560571f87433Sdalcinl rtol = PetscMin(kctx->rtol_0, stol); 560671f87433Sdalcinl /* safeguard: avoid oversolving */ 560730058271SDmitry Karpeev stol = kctx->gamma * (kctx->norm_first * snes->rtol) / snes->norm; 560871f87433Sdalcinl stol = PetscMax(rtol, stol); 560971f87433Sdalcinl rtol = PetscMin(kctx->rtol_0, stol); 56100fdf79fbSJacob Faibussowitsch } else /* if (kctx->version == 4) */ { 56110fdf79fbSJacob Faibussowitsch /* H.-B. An et al. Journal of Computational and Applied Mathematics 200 (2007) 47-60 */ 56120f0abf79SStefano Zampini PetscReal ared = PetscAbsReal(kctx->norm_last - snes->norm); 56130f0abf79SStefano Zampini PetscReal pred = PetscAbsReal(kctx->norm_last - kctx->lresid_last); 56140f0abf79SStefano Zampini PetscReal rk = ared / pred; 56150f0abf79SStefano Zampini if (rk < kctx->v4_p1) rtol = 1. - 2. * kctx->v4_p1; 56160f0abf79SStefano Zampini else if (rk < kctx->v4_p2) rtol = kctx->rtol_last; 56170f0abf79SStefano Zampini else if (rk < kctx->v4_p3) rtol = kctx->v4_m1 * kctx->rtol_last; 56180f0abf79SStefano Zampini else rtol = kctx->v4_m2 * kctx->rtol_last; 56190f0abf79SStefano Zampini 5620a4598233SStefano Zampini if (kctx->rtol_last_2 > kctx->v4_m3 && kctx->rtol_last > kctx->v4_m3 && kctx->rk_last_2 < kctx->v4_p1 && kctx->rk_last < kctx->v4_p1) rtol = kctx->v4_m4 * kctx->rtol_last; 56210f0abf79SStefano Zampini kctx->rtol_last_2 = kctx->rtol_last; 56220f0abf79SStefano Zampini kctx->rk_last_2 = kctx->rk_last; 56230f0abf79SStefano Zampini kctx->rk_last = rk; 56240fdf79fbSJacob Faibussowitsch } 56250f0abf79SStefano Zampini } 56260f0abf79SStefano Zampini /* safeguard: avoid rtol greater than rtol_max */ 562771f87433Sdalcinl rtol = PetscMin(rtol, kctx->rtol_max); 562877e5a1f9SBarry Smith PetscCall(KSPSetTolerances(ksp, rtol, PETSC_CURRENT, PETSC_CURRENT, PETSC_CURRENT)); 562963a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "iter %" PetscInt_FMT ", Eisenstat-Walker (version %" PetscInt_FMT ") KSP rtol=%g\n", snes->iter, kctx->version, (double)rtol)); 56303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 563171f87433Sdalcinl } 563271f87433Sdalcinl 56335c0db29aSPierre Jolivet PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx) 5634d71ae5a4SJacob Faibussowitsch { 56355c0db29aSPierre Jolivet SNES snes = (SNES)ctx; 5636fa9f3622SBarry Smith SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx; 563771f87433Sdalcinl PCSide pcside; 563871f87433Sdalcinl Vec lres; 563971f87433Sdalcinl 564071f87433Sdalcinl PetscFunctionBegin; 56413ba16761SJacob Faibussowitsch if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS); 56429566063dSJacob Faibussowitsch PetscCall(KSPGetTolerances(ksp, &kctx->rtol_last, NULL, NULL, NULL)); 564371dbe336SPeter Brune kctx->norm_last = snes->norm; 56440f0abf79SStefano Zampini if (kctx->version == 1 || kctx->version == 4) { 56454f00ce20SMatthew G. Knepley PC pc; 56460f0abf79SStefano Zampini PetscBool getRes; 56474f00ce20SMatthew G. Knepley 56489566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksp, &pc)); 56490f0abf79SStefano Zampini PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &getRes)); 56500f0abf79SStefano Zampini if (!getRes) { 56510f0abf79SStefano Zampini KSPNormType normtype; 56520f0abf79SStefano Zampini 56530f0abf79SStefano Zampini PetscCall(KSPGetNormType(ksp, &normtype)); 56540f0abf79SStefano Zampini getRes = (PetscBool)(normtype == KSP_NORM_UNPRECONDITIONED); 56550f0abf79SStefano Zampini } 56569566063dSJacob Faibussowitsch PetscCall(KSPGetPCSide(ksp, &pcside)); 56570f0abf79SStefano Zampini if (pcside == PC_RIGHT || getRes) { /* KSP residual is true linear residual */ 56589566063dSJacob Faibussowitsch PetscCall(KSPGetResidualNorm(ksp, &kctx->lresid_last)); 565971f87433Sdalcinl } else { 566071f87433Sdalcinl /* KSP residual is preconditioned residual */ 566171f87433Sdalcinl /* compute true linear residual norm */ 56620f0abf79SStefano Zampini Mat J; 56630f0abf79SStefano Zampini PetscCall(KSPGetOperators(ksp, &J, NULL)); 56649566063dSJacob Faibussowitsch PetscCall(VecDuplicate(b, &lres)); 56650f0abf79SStefano Zampini PetscCall(MatMult(J, x, lres)); 56669566063dSJacob Faibussowitsch PetscCall(VecAYPX(lres, -1.0, b)); 56679566063dSJacob Faibussowitsch PetscCall(VecNorm(lres, NORM_2, &kctx->lresid_last)); 56689566063dSJacob Faibussowitsch PetscCall(VecDestroy(&lres)); 566971f87433Sdalcinl } 567071f87433Sdalcinl } 56713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 567271f87433Sdalcinl } 567371f87433Sdalcinl 5674d4211eb9SBarry Smith /*@ 5675f6dfbefdSBarry Smith SNESGetKSP - Returns the `KSP` context for a `SNES` solver. 5676d4211eb9SBarry Smith 5677420bcc1bSBarry Smith Not Collective, but if `snes` is parallel, then `ksp` is parallel 5678d4211eb9SBarry Smith 5679d4211eb9SBarry Smith Input Parameter: 5680f6dfbefdSBarry Smith . snes - the `SNES` context 5681d4211eb9SBarry Smith 5682d4211eb9SBarry Smith Output Parameter: 5683f6dfbefdSBarry Smith . ksp - the `KSP` context 5684d4211eb9SBarry Smith 5685dc4c0fb0SBarry Smith Level: beginner 5686dc4c0fb0SBarry Smith 5687d4211eb9SBarry Smith Notes: 5688f6dfbefdSBarry Smith The user can then directly manipulate the `KSP` context to set various 5689d4211eb9SBarry Smith options, etc. Likewise, the user can then extract and manipulate the 5690f6dfbefdSBarry Smith `PC` contexts as well. 5691f6dfbefdSBarry Smith 56920b4b7b1cSBarry Smith Some `SNESType`s do not use a `KSP` but a `KSP` is still returned by this function, changes to that `KSP` will have no effect. 5693d4211eb9SBarry Smith 56941cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSP`, `PC`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()` 5695d4211eb9SBarry Smith @*/ 5696d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetKSP(SNES snes, KSP *ksp) 5697d71ae5a4SJacob Faibussowitsch { 569871f87433Sdalcinl PetscFunctionBegin; 5699d4211eb9SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 57004f572ea9SToby Isaac PetscAssertPointer(ksp, 2); 5701d4211eb9SBarry Smith 5702d4211eb9SBarry Smith if (!snes->ksp) { 57039566063dSJacob Faibussowitsch PetscCall(KSPCreate(PetscObjectComm((PetscObject)snes), &snes->ksp)); 57049566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->ksp, (PetscObject)snes, 1)); 5705d4211eb9SBarry Smith 57065c0db29aSPierre Jolivet PetscCall(KSPSetPreSolve(snes->ksp, KSPPreSolve_SNESEW, snes)); 57075c0db29aSPierre Jolivet PetscCall(KSPSetPostSolve(snes->ksp, KSPPostSolve_SNESEW, snes)); 5708a5c2985bSBarry Smith 57099566063dSJacob Faibussowitsch PetscCall(KSPMonitorSetFromOptions(snes->ksp, "-snes_monitor_ksp", "snes_preconditioned_residual", snes)); 57109566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptions((PetscObject)snes->ksp, ((PetscObject)snes)->options)); 5711d4211eb9SBarry Smith } 5712d4211eb9SBarry Smith *ksp = snes->ksp; 57133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 571471f87433Sdalcinl } 57156c699258SBarry Smith 5716af0996ceSBarry Smith #include <petsc/private/dmimpl.h> 57176c699258SBarry Smith /*@ 57180b4b7b1cSBarry Smith SNESSetDM - Sets the `DM` that may be used by some `SNES` nonlinear solvers or their underlying preconditioners 57196c699258SBarry Smith 5720c3339decSBarry Smith Logically Collective 57216c699258SBarry Smith 57226c699258SBarry Smith Input Parameters: 57232a808120SBarry Smith + snes - the nonlinear solver context 5724420bcc1bSBarry Smith - dm - the `DM`, cannot be `NULL` 5725dc4c0fb0SBarry Smith 5726dc4c0fb0SBarry Smith Level: intermediate 57276c699258SBarry Smith 5728f6dfbefdSBarry Smith Note: 5729f6dfbefdSBarry Smith A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`, 5730f6dfbefdSBarry Smith even when not using interfaces like `DMSNESSetFunction()`. Use `DMClone()` to get a distinct `DM` when solving different 5731e03a659cSJed Brown problems using the same function space. 5732e03a659cSJed Brown 5733420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()` 57346c699258SBarry Smith @*/ 5735d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDM(SNES snes, DM dm) 5736d71ae5a4SJacob Faibussowitsch { 5737345fed2cSBarry Smith KSP ksp; 5738942e3340SBarry Smith DMSNES sdm; 57396c699258SBarry Smith 57406c699258SBarry Smith PetscFunctionBegin; 57410700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 57422a808120SBarry Smith PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 57439566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 5744942e3340SBarry Smith if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */ 574551f4b3c7SToby Isaac if (snes->dm->dmsnes && !dm->dmsnes) { 57469566063dSJacob Faibussowitsch PetscCall(DMCopyDMSNES(snes->dm, dm)); 57479566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(snes->dm, &sdm)); 5748f5af7f23SKarl Rupp if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */ 57496cab3a1bSJed Brown } 57509566063dSJacob Faibussowitsch PetscCall(DMCoarsenHookRemove(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes)); 57519566063dSJacob Faibussowitsch PetscCall(DMDestroy(&snes->dm)); 57526cab3a1bSJed Brown } 57536c699258SBarry Smith snes->dm = dm; 5754116d1032SJed Brown snes->dmAuto = PETSC_FALSE; 5755f5af7f23SKarl Rupp 57569566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 57579566063dSJacob Faibussowitsch PetscCall(KSPSetDM(ksp, dm)); 57589566063dSJacob Faibussowitsch PetscCall(KSPSetDMActive(ksp, PETSC_FALSE)); 5759efd4aadfSBarry Smith if (snes->npc) { 57609566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes->npc, snes->dm)); 57619566063dSJacob Faibussowitsch PetscCall(SNESSetNPCSide(snes, snes->npcside)); 57622c155ee1SBarry Smith } 57633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 57646c699258SBarry Smith } 57656c699258SBarry Smith 57666c699258SBarry Smith /*@ 57670b4b7b1cSBarry Smith SNESGetDM - Gets the `DM` that may be used by some `SNES` nonlinear solvers/preconditioners 57686c699258SBarry Smith 57690b4b7b1cSBarry Smith Not Collective but `dm` obtained is parallel on `snes` 57706c699258SBarry Smith 57716c699258SBarry Smith Input Parameter: 5772420bcc1bSBarry Smith . snes - the `SNES` context 57736c699258SBarry Smith 57746c699258SBarry Smith Output Parameter: 5775420bcc1bSBarry Smith . dm - the `DM` 57766c699258SBarry Smith 57776c699258SBarry Smith Level: intermediate 57786c699258SBarry Smith 5779420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESSetDM()`, `KSPSetDM()`, `KSPGetDM()` 57806c699258SBarry Smith @*/ 5781d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDM(SNES snes, DM *dm) 5782d71ae5a4SJacob Faibussowitsch { 57836c699258SBarry Smith PetscFunctionBegin; 57840700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 57856cab3a1bSJed Brown if (!snes->dm) { 57869566063dSJacob Faibussowitsch PetscCall(DMShellCreate(PetscObjectComm((PetscObject)snes), &snes->dm)); 5787116d1032SJed Brown snes->dmAuto = PETSC_TRUE; 57886cab3a1bSJed Brown } 57896c699258SBarry Smith *dm = snes->dm; 57903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 57916c699258SBarry Smith } 57920807856dSBarry Smith 579331823bd8SMatthew G Knepley /*@ 5794be95d8f1SBarry Smith SNESSetNPC - Sets the nonlinear preconditioner to be used. 579531823bd8SMatthew G Knepley 5796c3339decSBarry Smith Collective 579731823bd8SMatthew G Knepley 579831823bd8SMatthew G Knepley Input Parameters: 5799f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 580062842358SBarry Smith - npc - the `SNES` nonlinear preconditioner object 580162842358SBarry Smith 580262842358SBarry Smith Options Database Key: 580362842358SBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner 580431823bd8SMatthew G Knepley 5805dc4c0fb0SBarry Smith Level: developer 5806dc4c0fb0SBarry Smith 580731823bd8SMatthew G Knepley Notes: 580862842358SBarry Smith This is rarely used, rather use `SNESGetNPC()` to retrieve the preconditioner and configure it using the API. 580931823bd8SMatthew G Knepley 5810f6dfbefdSBarry Smith Only some `SNESType` can use a nonlinear preconditioner 5811f6dfbefdSBarry Smith 5812420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNGS`, `SNESFAS`, `SNESGetNPC()`, `SNESHasNPC()` 581331823bd8SMatthew G Knepley @*/ 5814d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPC(SNES snes, SNES npc) 5815d71ae5a4SJacob Faibussowitsch { 581631823bd8SMatthew G Knepley PetscFunctionBegin; 581731823bd8SMatthew G Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5818f6dfbefdSBarry Smith PetscValidHeaderSpecific(npc, SNES_CLASSID, 2); 5819f6dfbefdSBarry Smith PetscCheckSameComm(snes, 1, npc, 2); 5820f6dfbefdSBarry Smith PetscCall(PetscObjectReference((PetscObject)npc)); 58219566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&snes->npc)); 5822f6dfbefdSBarry Smith snes->npc = npc; 58233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 582431823bd8SMatthew G Knepley } 582531823bd8SMatthew G Knepley 582631823bd8SMatthew G Knepley /*@ 5827f6dfbefdSBarry Smith SNESGetNPC - Gets a nonlinear preconditioning solver SNES` to be used to precondition the original nonlinear solver. 582831823bd8SMatthew G Knepley 58290b4b7b1cSBarry Smith Not Collective; but any changes to the obtained the `pc` object must be applied collectively 583031823bd8SMatthew G Knepley 583131823bd8SMatthew G Knepley Input Parameter: 5832f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 583331823bd8SMatthew G Knepley 583431823bd8SMatthew G Knepley Output Parameter: 583562842358SBarry Smith . pc - the `SNES` preconditioner context 583631823bd8SMatthew G Knepley 5837f6dfbefdSBarry Smith Options Database Key: 5838f6dfbefdSBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner 5839b5badacbSBarry Smith 58400b4b7b1cSBarry Smith Level: advanced 5841dc4c0fb0SBarry Smith 584295452b02SPatrick Sanan Notes: 58430b4b7b1cSBarry Smith If a `SNES` was previously set with `SNESSetNPC()` then that value is returned, otherwise a new `SNES` object is created that will 58440b4b7b1cSBarry Smith be used as the nonlinear preconditioner for the current `SNES`. 5845be95d8f1SBarry Smith 5846f6dfbefdSBarry Smith The (preconditioner) `SNES` returned automatically inherits the same nonlinear function and Jacobian supplied to the original 584762842358SBarry Smith `SNES`. These may be overwritten if needed. 584862842358SBarry Smith 584962842358SBarry Smith Use the options database prefixes `-npc_snes`, `-npc_ksp`, etc., to control the configuration of the nonlinear preconditioner 5850951fe5abSBarry Smith 58511cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESHasNPC()`, `SNES`, `SNESCreate()` 585231823bd8SMatthew G Knepley @*/ 5853d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPC(SNES snes, SNES *pc) 5854d71ae5a4SJacob Faibussowitsch { 5855a64e098fSPeter Brune const char *optionsprefix; 585631823bd8SMatthew G Knepley 585731823bd8SMatthew G Knepley PetscFunctionBegin; 585831823bd8SMatthew G Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 58594f572ea9SToby Isaac PetscAssertPointer(pc, 2); 5860efd4aadfSBarry Smith if (!snes->npc) { 5861ec785e5bSStefano Zampini void *ctx; 5862ec785e5bSStefano Zampini 58639566063dSJacob Faibussowitsch PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &snes->npc)); 58649566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->npc, (PetscObject)snes, 1)); 58659566063dSJacob Faibussowitsch PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 58669566063dSJacob Faibussowitsch PetscCall(SNESSetOptionsPrefix(snes->npc, optionsprefix)); 58679566063dSJacob Faibussowitsch PetscCall(SNESAppendOptionsPrefix(snes->npc, "npc_")); 5868fb87a551SStefano Zampini if (snes->ops->usercompute) { 586949abdd8aSBarry Smith PetscCall(SNESSetComputeApplicationContext(snes, snes->ops->usercompute, snes->ops->ctxdestroy)); 5870fb87a551SStefano Zampini } else { 5871ec785e5bSStefano Zampini PetscCall(SNESGetApplicationContext(snes, &ctx)); 5872ec785e5bSStefano Zampini PetscCall(SNESSetApplicationContext(snes->npc, ctx)); 5873fb87a551SStefano Zampini } 58749566063dSJacob Faibussowitsch PetscCall(SNESSetCountersReset(snes->npc, PETSC_FALSE)); 587531823bd8SMatthew G Knepley } 5876efd4aadfSBarry Smith *pc = snes->npc; 58773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 587831823bd8SMatthew G Knepley } 587931823bd8SMatthew G Knepley 58803ad1a0b9SPatrick Farrell /*@ 58810b4b7b1cSBarry Smith SNESHasNPC - Returns whether a nonlinear preconditioner is associated with the given `SNES` 58823ad1a0b9SPatrick Farrell 58833ad1a0b9SPatrick Farrell Not Collective 58843ad1a0b9SPatrick Farrell 58853ad1a0b9SPatrick Farrell Input Parameter: 5886f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 58873ad1a0b9SPatrick Farrell 58883ad1a0b9SPatrick Farrell Output Parameter: 5889420bcc1bSBarry Smith . has_npc - whether the `SNES` has a nonlinear preconditioner or not 58903ad1a0b9SPatrick Farrell 58913ad1a0b9SPatrick Farrell Level: developer 58923ad1a0b9SPatrick Farrell 58931cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESGetNPC()` 58943ad1a0b9SPatrick Farrell @*/ 5895d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc) 5896d71ae5a4SJacob Faibussowitsch { 58973ad1a0b9SPatrick Farrell PetscFunctionBegin; 58983ad1a0b9SPatrick Farrell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5899835f2295SStefano Zampini PetscAssertPointer(has_npc, 2); 5900835f2295SStefano Zampini *has_npc = snes->npc ? PETSC_TRUE : PETSC_FALSE; 59013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 59023ad1a0b9SPatrick Farrell } 59033ad1a0b9SPatrick Farrell 5904c40d0f55SPeter Brune /*@ 590562842358SBarry Smith SNESSetNPCSide - Sets the nonlinear preconditioning side used by the nonlinear preconditioner inside `SNES`. 5906c40d0f55SPeter Brune 5907c3339decSBarry Smith Logically Collective 5908c40d0f55SPeter Brune 5909c40d0f55SPeter Brune Input Parameter: 5910f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 5911c40d0f55SPeter Brune 5912c40d0f55SPeter Brune Output Parameter: 5913c40d0f55SPeter Brune . side - the preconditioning side, where side is one of 5914c40d0f55SPeter Brune .vb 59152d547940SBarry Smith PC_LEFT - left preconditioning 59162d547940SBarry Smith PC_RIGHT - right preconditioning (default for most nonlinear solvers) 5917c40d0f55SPeter Brune .ve 5918c40d0f55SPeter Brune 5919f6dfbefdSBarry Smith Options Database Key: 592067b8a455SSatish Balay . -snes_npc_side <right,left> - nonlinear preconditioner side 5921c40d0f55SPeter Brune 5922dc4c0fb0SBarry Smith Level: intermediate 5923dc4c0fb0SBarry Smith 5924f6dfbefdSBarry Smith Note: 5925f6dfbefdSBarry Smith `SNESNRICHARDSON` and `SNESNCG` only support left preconditioning. 59262d547940SBarry Smith 592762842358SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNPC()`, `SNESNRICHARDSON`, `SNESNCG`, `SNESType`, `SNESGetNPCSide()`, `KSPSetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide` 5928c40d0f55SPeter Brune @*/ 5929d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPCSide(SNES snes, PCSide side) 5930d71ae5a4SJacob Faibussowitsch { 5931c40d0f55SPeter Brune PetscFunctionBegin; 5932c40d0f55SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5933c40d0f55SPeter Brune PetscValidLogicalCollectiveEnum(snes, side, 2); 5934b552625fSStefano Zampini if (side == PC_SIDE_DEFAULT) side = PC_RIGHT; 593554c59aa7SJacob Faibussowitsch PetscCheck((side == PC_LEFT) || (side == PC_RIGHT), PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Only PC_LEFT and PC_RIGHT are supported"); 5936efd4aadfSBarry Smith snes->npcside = side; 59373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5938c40d0f55SPeter Brune } 5939c40d0f55SPeter Brune 5940c40d0f55SPeter Brune /*@ 594162842358SBarry Smith SNESGetNPCSide - Gets the preconditioning side used by the nonlinear preconditioner inside `SNES`. 5942c40d0f55SPeter Brune 5943c40d0f55SPeter Brune Not Collective 5944c40d0f55SPeter Brune 5945c40d0f55SPeter Brune Input Parameter: 5946f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 5947c40d0f55SPeter Brune 5948c40d0f55SPeter Brune Output Parameter: 5949c40d0f55SPeter Brune . side - the preconditioning side, where side is one of 5950c40d0f55SPeter Brune .vb 5951f6dfbefdSBarry Smith `PC_LEFT` - left preconditioning 5952f6dfbefdSBarry Smith `PC_RIGHT` - right preconditioning (default for most nonlinear solvers) 5953c40d0f55SPeter Brune .ve 5954c40d0f55SPeter Brune 5955c40d0f55SPeter Brune Level: intermediate 5956c40d0f55SPeter Brune 595762842358SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNPC()`, `SNESSetNPCSide()`, `KSPGetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide` 5958c40d0f55SPeter Brune @*/ 5959d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPCSide(SNES snes, PCSide *side) 5960d71ae5a4SJacob Faibussowitsch { 5961c40d0f55SPeter Brune PetscFunctionBegin; 5962c40d0f55SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 59634f572ea9SToby Isaac PetscAssertPointer(side, 2); 5964efd4aadfSBarry Smith *side = snes->npcside; 59653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5966c40d0f55SPeter Brune } 5967c40d0f55SPeter Brune 59689e764e56SPeter Brune /*@ 59690b4b7b1cSBarry Smith SNESSetLineSearch - Sets the `SNESLineSearch` to be used for a given `SNES` 59709e764e56SPeter Brune 5971c3339decSBarry Smith Collective 59729e764e56SPeter Brune 59739e764e56SPeter Brune Input Parameters: 5974f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 59759e764e56SPeter Brune - linesearch - the linesearch object 59769e764e56SPeter Brune 5977dc4c0fb0SBarry Smith Level: developer 5978dc4c0fb0SBarry Smith 5979f6dfbefdSBarry Smith Note: 5980420bcc1bSBarry Smith This is almost never used, rather one uses `SNESGetLineSearch()` to retrieve the line search and set options on it 59819e764e56SPeter Brune to configure it using the API). 59829e764e56SPeter Brune 5983420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()` 59849e764e56SPeter Brune @*/ 5985d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch) 5986d71ae5a4SJacob Faibussowitsch { 59879e764e56SPeter Brune PetscFunctionBegin; 59889e764e56SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5989f1c6b773SPeter Brune PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 2); 59909e764e56SPeter Brune PetscCheckSameComm(snes, 1, linesearch, 2); 59919566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)linesearch)); 59929566063dSJacob Faibussowitsch PetscCall(SNESLineSearchDestroy(&snes->linesearch)); 5993f5af7f23SKarl Rupp 59949e764e56SPeter Brune snes->linesearch = linesearch; 59953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 59969e764e56SPeter Brune } 5997