1af0996ceSBarry Smith #include <petsc/private/snesimpl.h> /*I "petscsnes.h" I*/ 276c63389SBarry 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 11976c63389SBarry 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 13176c63389SBarry 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 13276c63389SBarry 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 13776c63389SBarry Smith You should always call `SNESGetConvergedReason()` after each `SNESSolve()` and verify if the iteration converged (positive result) or diverged (negative result). 13876c63389SBarry 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: 14276c63389SBarry 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()`, 14676c63389SBarry 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); 15276c63389SBarry Smith snes->functiondomainerror = PETSC_TRUE; 15376c63389SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 15476c63389SBarry Smith } 15576c63389SBarry Smith 15676c63389SBarry Smith /*@ 15776c63389SBarry Smith SNESSetObjectiveDomainError - tells `SNES` that the input vector, a proposed new solution, to your function you provided to `SNESSetObjective()` is not 15876c63389SBarry Smith in the function's domain. For example, a step with negative pressure. 15976c63389SBarry Smith 16076c63389SBarry Smith Not Collective 16176c63389SBarry Smith 16276c63389SBarry Smith Input Parameter: 16376c63389SBarry Smith . snes - the `SNES` context 16476c63389SBarry Smith 16576c63389SBarry Smith Level: advanced 16676c63389SBarry Smith 16776c63389SBarry Smith Notes: 16876c63389SBarry Smith This does not need to be called by all processes in the `SNES` MPI communicator. 16976c63389SBarry Smith 17076c63389SBarry 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 17176c63389SBarry Smith returns with a `SNESConvergedReason` of `SNES_DIVERGED_FUNCTION_DOMAIN` 17276c63389SBarry Smith 17376c63389SBarry Smith You can direct `SNES` to avoid certain steps by using `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()` or 17476c63389SBarry Smith `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()` 17576c63389SBarry Smith 17676c63389SBarry Smith You should always call `SNESGetConvergedReason()` after each `SNESSolve()` and verify if the iteration converged (positive result) or diverged (negative result). 17776c63389SBarry Smith 17876c63389SBarry Smith You can call `SNESSetJacobianDomainError()` during a Jacobian computation to indicate the proposed solution is not in the domain. 17976c63389SBarry Smith 18076c63389SBarry Smith Developer Note: 18176c63389SBarry Smith This value is used by `SNESCheckFunctionDomainError()` to determine if the `SNESConvergedReason` is set to `SNES_DIVERGED_FUNCTION_DOMAIN` 18276c63389SBarry Smith 18376c63389SBarry Smith .seealso: [](ch_snes), `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetJacobianDomainError()`, `SNESVISetVariableBounds()`, 18476c63389SBarry Smith `SNESVISetComputeVariableBounds()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, 18576c63389SBarry Smith `SNES_DIVERGED_FUNCTION_DOMAIN`, `SNESSetFunctionDomainError()` 18676c63389SBarry Smith @*/ 18776c63389SBarry Smith PetscErrorCode SNESSetObjectiveDomainError(SNES snes) 18876c63389SBarry Smith { 18976c63389SBarry Smith PetscFunctionBegin; 19076c63389SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 19176c63389SBarry 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 /*@ 22676c63389SBarry Smith SNESSetCheckJacobianDomainError - tells `SNESSolve()` whether to check if the user called `SNESSetJacobianDomainError()` to indicate a Jacobian domain error after 22776c63389SBarry 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 23776c63389SBarry Smith Notes: 23876c63389SBarry Smith By default, it checks for the Jacobian domain error in the debug mode, and does not check it in the optimized mode. 23976c63389SBarry 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 6472a8381b2SBarry Smith static PetscErrorCode DMRestrictHook_SNESVecSol(DM dmfine, Mat Restrict, Vec Rscale, Mat Inject, DM dmcoarse, PetscCtx 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 6782a8381b2SBarry Smith static PetscErrorCode DMCoarsenHook_SNESVecSol(DM dm, DM dmc, PetscCtx 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. */ 6872a8381b2SBarry Smith static PetscErrorCode KSPComputeOperators_SNES(KSP ksp, Mat A, Mat B, PetscCtx 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)); 72976c63389SBarry 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)); 8692a8381b2SBarry Smith PetscCall(SNESMonitorSet(snes, (PetscErrorCode (*)(SNES, PetscInt, PetscReal, PetscCtx))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) { 11422a8381b2SBarry Smith PetscCtx 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 @*/ 12272a8381b2SBarry Smith PetscErrorCode SNESSetComputeApplicationContext(SNES snes, PetscErrorCode (*compute)(SNES snes, PetscCtxRt ctx), PetscCtxDestroyFn *destroy) 1228d71ae5a4SJacob Faibussowitsch { 1229d25893d9SBarry Smith PetscFunctionBegin; 1230d25893d9SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 12312a8381b2SBarry Smith snes->ops->ctxcompute = 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 @*/ 12602a8381b2SBarry Smith PetscErrorCode SNESSetApplicationContext(SNES snes, PetscCtx 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: 12822a8381b2SBarry Smith . ctx - the application context 12839b94acceSBarry Smith 128436851e7fSLois Curfman McInnes Level: intermediate 128536851e7fSLois Curfman McInnes 1286ce78bad3SBarry Smith Fortran Notes: 12872a8381b2SBarry Smith This only works when the context is a Fortran derived type or a `PetscObject`. Declare `ctx` with 1288ce78bad3SBarry Smith .vb 1289ce78bad3SBarry Smith type(tUsertype), pointer :: ctx 1290ce78bad3SBarry Smith .ve 1291dc4c0fb0SBarry Smith 1292420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESSetApplicationContext()`, `SNESSetComputeApplicationContext()` 12939b94acceSBarry Smith @*/ 12942a8381b2SBarry Smith PetscErrorCode SNESGetApplicationContext(SNES snes, PetscCtxRt ctx) 1295d71ae5a4SJacob Faibussowitsch { 12963a40ed3dSBarry Smith PetscFunctionBegin; 12970700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 129849abdd8aSBarry Smith *(void **)ctx = snes->ctx; 12993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13009b94acceSBarry Smith } 130174679c65SBarry Smith 13029b94acceSBarry Smith /*@ 1303420bcc1bSBarry Smith SNESSetUseMatrixFree - indicates that `SNES` should use matrix-free finite difference matrix-vector products to apply the Jacobian. 13043565c898SBarry Smith 1305dc4c0fb0SBarry Smith Logically Collective 13063565c898SBarry Smith 13073565c898SBarry Smith Input Parameters: 1308f6dfbefdSBarry Smith + snes - `SNES` context 1309f6dfbefdSBarry Smith . mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used 1310f6dfbefdSBarry 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 1311420bcc1bSBarry Smith this option no matrix-element based preconditioners can be used in the linear solve since the matrix won't be explicitly available 13123565c898SBarry Smith 1313f6dfbefdSBarry Smith Options Database Keys: 131401c1178eSBarry Smith + -snes_mf_operator - use matrix-free only for the mat operator 1315f6dfbefdSBarry Smith . -snes_mf - use matrix-free for both the mat and pmat operator 1316ec5066bdSBarry Smith . -snes_fd_color - compute the Jacobian via coloring and finite differences. 1317ec5066bdSBarry Smith - -snes_fd - compute the Jacobian via finite differences (slow) 13183565c898SBarry Smith 13193565c898SBarry Smith Level: intermediate 13203565c898SBarry Smith 1321f6dfbefdSBarry Smith Note: 1322420bcc1bSBarry Smith `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`, 1323420bcc1bSBarry Smith and computing explicitly with 1324f6dfbefdSBarry Smith finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object. 1325ec5066bdSBarry Smith 1326420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetUseMatrixFree()`, `MatCreateSNESMF()`, `SNESComputeJacobianDefaultColor()`, `MatFDColoring` 13273565c898SBarry Smith @*/ 1328d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUseMatrixFree(SNES snes, PetscBool mf_operator, PetscBool mf) 1329d71ae5a4SJacob Faibussowitsch { 13303565c898SBarry Smith PetscFunctionBegin; 13313565c898SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 133288b4c220SStefano Zampini PetscValidLogicalCollectiveBool(snes, mf_operator, 2); 133388b4c220SStefano Zampini PetscValidLogicalCollectiveBool(snes, mf, 3); 13344ddffce6SLisandro Dalcin snes->mf = mf_operator ? PETSC_TRUE : mf; 13353565c898SBarry Smith snes->mf_operator = mf_operator; 13363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13373565c898SBarry Smith } 13383565c898SBarry Smith 13393565c898SBarry Smith /*@ 1340dc4c0fb0SBarry Smith SNESGetUseMatrixFree - indicates if the `SNES` uses matrix-free finite difference matrix vector products to apply the Jacobian. 13413565c898SBarry Smith 1342420bcc1bSBarry Smith Not Collective, but the resulting flags will be the same on all MPI processes 13433565c898SBarry Smith 13443565c898SBarry Smith Input Parameter: 1345f6dfbefdSBarry Smith . snes - `SNES` context 13463565c898SBarry Smith 13473565c898SBarry Smith Output Parameters: 1348f6dfbefdSBarry Smith + mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used 1349f6dfbefdSBarry 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 13503565c898SBarry Smith 13513565c898SBarry Smith Level: intermediate 13523565c898SBarry Smith 13531cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUseMatrixFree()`, `MatCreateSNESMF()` 13543565c898SBarry Smith @*/ 1355d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUseMatrixFree(SNES snes, PetscBool *mf_operator, PetscBool *mf) 1356d71ae5a4SJacob Faibussowitsch { 13573565c898SBarry Smith PetscFunctionBegin; 13583565c898SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 13593565c898SBarry Smith if (mf) *mf = snes->mf; 13603565c898SBarry Smith if (mf_operator) *mf_operator = snes->mf_operator; 13613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13623565c898SBarry Smith } 13633565c898SBarry Smith 13643565c898SBarry Smith /*@ 1365420bcc1bSBarry Smith SNESGetIterationNumber - Gets the number of nonlinear iterations completed in the current or most recent `SNESSolve()` 13669b94acceSBarry Smith 1367c7afd0dbSLois Curfman McInnes Not Collective 1368c7afd0dbSLois Curfman McInnes 13699b94acceSBarry Smith Input Parameter: 1370f6dfbefdSBarry Smith . snes - `SNES` context 13719b94acceSBarry Smith 13729b94acceSBarry Smith Output Parameter: 13739b94acceSBarry Smith . iter - iteration number 13749b94acceSBarry Smith 1375dc4c0fb0SBarry Smith Level: intermediate 1376dc4c0fb0SBarry Smith 1377c8228a4eSBarry Smith Notes: 1378c8228a4eSBarry Smith For example, during the computation of iteration 2 this would return 1. 1379c8228a4eSBarry Smith 1380c8228a4eSBarry Smith This is useful for using lagged Jacobians (where one does not recompute the 1381f6dfbefdSBarry Smith Jacobian at each `SNES` iteration). For example, the code 138208405cd6SLois Curfman McInnes .vb 138308405cd6SLois Curfman McInnes ierr = SNESGetIterationNumber(snes,&it); 138408405cd6SLois Curfman McInnes if (!(it % 2)) { 138508405cd6SLois Curfman McInnes [compute Jacobian here] 138608405cd6SLois Curfman McInnes } 138708405cd6SLois Curfman McInnes .ve 1388f6dfbefdSBarry Smith can be used in your function that computes the Jacobian to cause the Jacobian to be 1389f6dfbefdSBarry Smith recomputed every second `SNES` iteration. See also `SNESSetLagJacobian()` 1390c8228a4eSBarry Smith 1391f6dfbefdSBarry Smith After the `SNES` solve is complete this will return the number of nonlinear iterations used. 1392c04deec6SBarry Smith 1393420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetLagJacobian()`, `SNESGetLinearSolveIterations()`, `SNESSetMonitor()` 13949b94acceSBarry Smith @*/ 1395d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetIterationNumber(SNES snes, PetscInt *iter) 1396d71ae5a4SJacob Faibussowitsch { 13973a40ed3dSBarry Smith PetscFunctionBegin; 13980700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 13994f572ea9SToby Isaac PetscAssertPointer(iter, 2); 14009b94acceSBarry Smith *iter = snes->iter; 14013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14029b94acceSBarry Smith } 140374679c65SBarry Smith 1404360c497dSPeter Brune /*@ 1405360c497dSPeter Brune SNESSetIterationNumber - Sets the current iteration number. 1406360c497dSPeter Brune 1407360c497dSPeter Brune Not Collective 1408360c497dSPeter Brune 1409d8d19677SJose E. Roman Input Parameters: 1410f6dfbefdSBarry Smith + snes - `SNES` context 1411a2b725a8SWilliam Gropp - iter - iteration number 1412360c497dSPeter Brune 1413360c497dSPeter Brune Level: developer 1414360c497dSPeter Brune 1415420bcc1bSBarry Smith Note: 1416420bcc1bSBarry Smith This should only be called inside a `SNES` nonlinear solver. 1417420bcc1bSBarry Smith 14181cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetLinearSolveIterations()` 1419360c497dSPeter Brune @*/ 1420d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetIterationNumber(SNES snes, PetscInt iter) 1421d71ae5a4SJacob Faibussowitsch { 1422360c497dSPeter Brune PetscFunctionBegin; 1423360c497dSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 14249566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes)); 1425360c497dSPeter Brune snes->iter = iter; 14269566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes)); 14273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1428360c497dSPeter Brune } 1429360c497dSPeter Brune 14309b94acceSBarry Smith /*@ 1431b850b91aSLisandro Dalcin SNESGetNonlinearStepFailures - Gets the number of unsuccessful steps 143276c63389SBarry Smith taken by the nonlinear solver in the current or most recent `SNESSolve()` . 14339b94acceSBarry Smith 1434c7afd0dbSLois Curfman McInnes Not Collective 1435c7afd0dbSLois Curfman McInnes 14369b94acceSBarry Smith Input Parameter: 1437f6dfbefdSBarry Smith . snes - `SNES` context 14389b94acceSBarry Smith 14399b94acceSBarry Smith Output Parameter: 14409b94acceSBarry Smith . nfails - number of unsuccessful steps attempted 14419b94acceSBarry Smith 1442dc4c0fb0SBarry Smith Level: intermediate 1443dc4c0fb0SBarry Smith 144476c63389SBarry Smith Notes: 144576c63389SBarry Smith A failed step is a step that was generated and taken but did not satisfy the requested step criteria. For example, 144676c63389SBarry Smith the `SNESLineSearchApply()` could not generate a sufficient decrease in the function norm (in fact it may have produced an increase). 144776c63389SBarry Smith 144876c63389SBarry Smith Taken steps that produce a infinity or NaN in the function evaluation or generate a `SNESSetFunctionDomainError()` 144976c63389SBarry Smith will always immediately terminate the `SNESSolve()` regardless of the value of `maxFails`. 145076c63389SBarry Smith 145176c63389SBarry Smith `SNESSetMaxNonlinearStepFailures()` determines how many unsuccessful steps are allowed before the `SNESSolve()` terminates 145276c63389SBarry Smith 1453f6dfbefdSBarry Smith This counter is reset to zero for each successive call to `SNESSolve()`. 1454c96a6f78SLois Curfman McInnes 14551cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, 1456db781477SPatrick Sanan `SNESSetMaxNonlinearStepFailures()`, `SNESGetMaxNonlinearStepFailures()` 14579b94acceSBarry Smith @*/ 1458d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNonlinearStepFailures(SNES snes, PetscInt *nfails) 1459d71ae5a4SJacob Faibussowitsch { 14603a40ed3dSBarry Smith PetscFunctionBegin; 14610700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 14624f572ea9SToby Isaac PetscAssertPointer(nfails, 2); 146350ffb88aSMatthew Knepley *nfails = snes->numFailures; 14643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 146550ffb88aSMatthew Knepley } 146650ffb88aSMatthew Knepley 146750ffb88aSMatthew Knepley /*@ 1468b850b91aSLisandro Dalcin SNESSetMaxNonlinearStepFailures - Sets the maximum number of unsuccessful steps 1469420bcc1bSBarry Smith attempted by the nonlinear solver before it gives up and returns unconverged or generates an error 147050ffb88aSMatthew Knepley 147150ffb88aSMatthew Knepley Not Collective 147250ffb88aSMatthew Knepley 147350ffb88aSMatthew Knepley Input Parameters: 1474f6dfbefdSBarry Smith + snes - `SNES` context 147577e5a1f9SBarry Smith - maxFails - maximum of unsuccessful steps allowed, use `PETSC_UNLIMITED` to have no limit on the number of failures 147650ffb88aSMatthew Knepley 1477420bcc1bSBarry Smith Options Database Key: 1478420bcc1bSBarry Smith . -snes_max_fail <n> - maximum number of unsuccessful steps allowed 1479420bcc1bSBarry Smith 148050ffb88aSMatthew Knepley Level: intermediate 148150ffb88aSMatthew Knepley 148276c63389SBarry Smith Note: 148376c63389SBarry Smith A failed step is a step that was generated and taken but did not satisfy the requested criteria. For example, 148476c63389SBarry Smith the `SNESLineSearchApply()` could not generate a sufficient decrease in the function norm (in fact it may have produced an increase). 148576c63389SBarry Smith 148676c63389SBarry Smith Taken steps that produce a infinity or NaN in the function evaluation or generate a `SNESSetFunctionDomainError()` 148776c63389SBarry Smith will always immediately terminate the `SNESSolve()` regardless of the value of `maxFails`. 148876c63389SBarry Smith 1489420bcc1bSBarry Smith Developer Note: 1490420bcc1bSBarry Smith The options database key is wrong for this function name 1491420bcc1bSBarry Smith 149276c63389SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, 149376c63389SBarry Smith `SNESGetLinearSolveFailures()`, `SNESGetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`, `SNESCheckLineSearchFailure()` 149450ffb88aSMatthew Knepley @*/ 1495d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxNonlinearStepFailures(SNES snes, PetscInt maxFails) 1496d71ae5a4SJacob Faibussowitsch { 149750ffb88aSMatthew Knepley PetscFunctionBegin; 14980700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 149977e5a1f9SBarry Smith 150077e5a1f9SBarry Smith if (maxFails == PETSC_UNLIMITED) { 15011690c2aeSBarry Smith snes->maxFailures = PETSC_INT_MAX; 150277e5a1f9SBarry Smith } else { 150377e5a1f9SBarry Smith PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures"); 150450ffb88aSMatthew Knepley snes->maxFailures = maxFails; 150577e5a1f9SBarry Smith } 15063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 150750ffb88aSMatthew Knepley } 150850ffb88aSMatthew Knepley 150950ffb88aSMatthew Knepley /*@ 1510b850b91aSLisandro Dalcin SNESGetMaxNonlinearStepFailures - Gets the maximum number of unsuccessful steps 1511420bcc1bSBarry Smith attempted by the nonlinear solver before it gives up and returns unconverged or generates an error 151250ffb88aSMatthew Knepley 151350ffb88aSMatthew Knepley Not Collective 151450ffb88aSMatthew Knepley 151550ffb88aSMatthew Knepley Input Parameter: 151620f4b53cSBarry Smith . snes - `SNES` context 151750ffb88aSMatthew Knepley 151850ffb88aSMatthew Knepley Output Parameter: 151950ffb88aSMatthew Knepley . maxFails - maximum of unsuccessful steps 152050ffb88aSMatthew Knepley 152150ffb88aSMatthew Knepley Level: intermediate 152250ffb88aSMatthew Knepley 15231cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, 1524db781477SPatrick Sanan `SNESSetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()` 152550ffb88aSMatthew Knepley @*/ 1526d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxNonlinearStepFailures(SNES snes, PetscInt *maxFails) 1527d71ae5a4SJacob Faibussowitsch { 152850ffb88aSMatthew Knepley PetscFunctionBegin; 15290700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 15304f572ea9SToby Isaac PetscAssertPointer(maxFails, 2); 153150ffb88aSMatthew Knepley *maxFails = snes->maxFailures; 15323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15339b94acceSBarry Smith } 1534a847f771SSatish Balay 15352541af92SBarry Smith /*@ 15362541af92SBarry Smith SNESGetNumberFunctionEvals - Gets the number of user provided function evaluations 1537420bcc1bSBarry Smith done by the `SNES` object in the current or most recent `SNESSolve()` 15382541af92SBarry Smith 15392541af92SBarry Smith Not Collective 15402541af92SBarry Smith 15412541af92SBarry Smith Input Parameter: 1542f6dfbefdSBarry Smith . snes - `SNES` context 15432541af92SBarry Smith 15442541af92SBarry Smith Output Parameter: 15452541af92SBarry Smith . nfuncs - number of evaluations 15462541af92SBarry Smith 15472541af92SBarry Smith Level: intermediate 15482541af92SBarry Smith 1549f6dfbefdSBarry Smith Note: 1550f6dfbefdSBarry Smith Reset every time `SNESSolve()` is called unless `SNESSetCountersReset()` is used. 1551971e163fSPeter Brune 15521cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, `SNESSetCountersReset()` 15532541af92SBarry Smith @*/ 1554d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNumberFunctionEvals(SNES snes, PetscInt *nfuncs) 1555d71ae5a4SJacob Faibussowitsch { 15562541af92SBarry Smith PetscFunctionBegin; 15570700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 15584f572ea9SToby Isaac PetscAssertPointer(nfuncs, 2); 15592541af92SBarry Smith *nfuncs = snes->nfuncs; 15603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15612541af92SBarry Smith } 15622541af92SBarry Smith 15633d4c4710SBarry Smith /*@ 15643d4c4710SBarry Smith SNESGetLinearSolveFailures - Gets the number of failed (non-converged) 1565420bcc1bSBarry Smith linear solvers in the current or most recent `SNESSolve()` 15663d4c4710SBarry Smith 15673d4c4710SBarry Smith Not Collective 15683d4c4710SBarry Smith 15693d4c4710SBarry Smith Input Parameter: 1570f6dfbefdSBarry Smith . snes - `SNES` context 15713d4c4710SBarry Smith 15723d4c4710SBarry Smith Output Parameter: 15733d4c4710SBarry Smith . nfails - number of failed solves 15743d4c4710SBarry Smith 1575f6dfbefdSBarry Smith Options Database Key: 15769d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated 15779d85da0cSMatthew G. Knepley 1578f6dfbefdSBarry Smith Level: intermediate 1579f6dfbefdSBarry Smith 1580f6dfbefdSBarry Smith Note: 1581f6dfbefdSBarry Smith This counter is reset to zero for each successive call to `SNESSolve()`. 15823d4c4710SBarry Smith 15831cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()` 15843d4c4710SBarry Smith @*/ 1585d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveFailures(SNES snes, PetscInt *nfails) 1586d71ae5a4SJacob Faibussowitsch { 15873d4c4710SBarry Smith PetscFunctionBegin; 15880700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 15894f572ea9SToby Isaac PetscAssertPointer(nfails, 2); 15903d4c4710SBarry Smith *nfails = snes->numLinearSolveFailures; 15913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15923d4c4710SBarry Smith } 15933d4c4710SBarry Smith 15943d4c4710SBarry Smith /*@ 15953d4c4710SBarry Smith SNESSetMaxLinearSolveFailures - the number of failed linear solve attempts 1596f6dfbefdSBarry Smith allowed before `SNES` returns with a diverged reason of `SNES_DIVERGED_LINEAR_SOLVE` 15973d4c4710SBarry Smith 1598c3339decSBarry Smith Logically Collective 15993d4c4710SBarry Smith 16003d4c4710SBarry Smith Input Parameters: 1601f6dfbefdSBarry Smith + snes - `SNES` context 160277e5a1f9SBarry Smith - maxFails - maximum allowed linear solve failures, use `PETSC_UNLIMITED` to have no limit on the number of failures 16033d4c4710SBarry Smith 1604f6dfbefdSBarry Smith Options Database Key: 16059d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated 16069d85da0cSMatthew G. Knepley 1607dc4c0fb0SBarry Smith Level: intermediate 1608dc4c0fb0SBarry Smith 1609f6dfbefdSBarry Smith Note: 1610f6dfbefdSBarry Smith By default this is 0; that is `SNES` returns on the first failed linear solve 16113d4c4710SBarry Smith 1612420bcc1bSBarry Smith Developer Note: 1613420bcc1bSBarry Smith The options database key is wrong for this function name 1614420bcc1bSBarry Smith 16151cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()` 16163d4c4710SBarry Smith @*/ 1617d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxLinearSolveFailures(SNES snes, PetscInt maxFails) 1618d71ae5a4SJacob Faibussowitsch { 16193d4c4710SBarry Smith PetscFunctionBegin; 16200700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1621c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, maxFails, 2); 162277e5a1f9SBarry Smith 162377e5a1f9SBarry Smith if (maxFails == PETSC_UNLIMITED) { 16241690c2aeSBarry Smith snes->maxLinearSolveFailures = PETSC_INT_MAX; 162577e5a1f9SBarry Smith } else { 162677e5a1f9SBarry Smith PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures"); 16273d4c4710SBarry Smith snes->maxLinearSolveFailures = maxFails; 162877e5a1f9SBarry Smith } 16293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16303d4c4710SBarry Smith } 16313d4c4710SBarry Smith 16323d4c4710SBarry Smith /*@ 16333d4c4710SBarry Smith SNESGetMaxLinearSolveFailures - gets the maximum number of linear solve failures that 1634f6dfbefdSBarry Smith are allowed before `SNES` returns as unsuccessful 16353d4c4710SBarry Smith 16363d4c4710SBarry Smith Not Collective 16373d4c4710SBarry Smith 16383d4c4710SBarry Smith Input Parameter: 1639f6dfbefdSBarry Smith . snes - `SNES` context 16403d4c4710SBarry Smith 16413d4c4710SBarry Smith Output Parameter: 16423d4c4710SBarry Smith . maxFails - maximum of unsuccessful solves allowed 16433d4c4710SBarry Smith 16443d4c4710SBarry Smith Level: intermediate 16453d4c4710SBarry Smith 1646f6dfbefdSBarry Smith Note: 1647f6dfbefdSBarry Smith By default this is 1; that is `SNES` returns on the first failed linear solve 16483d4c4710SBarry Smith 16491cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, 16503d4c4710SBarry Smith @*/ 1651d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxLinearSolveFailures(SNES snes, PetscInt *maxFails) 1652d71ae5a4SJacob Faibussowitsch { 16533d4c4710SBarry Smith PetscFunctionBegin; 16540700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 16554f572ea9SToby Isaac PetscAssertPointer(maxFails, 2); 16563d4c4710SBarry Smith *maxFails = snes->maxLinearSolveFailures; 16573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16583d4c4710SBarry Smith } 16593d4c4710SBarry Smith 1660c96a6f78SLois Curfman McInnes /*@ 1661b850b91aSLisandro Dalcin SNESGetLinearSolveIterations - Gets the total number of linear iterations 1662420bcc1bSBarry Smith used by the nonlinear solver in the most recent `SNESSolve()` 1663c96a6f78SLois Curfman McInnes 1664c7afd0dbSLois Curfman McInnes Not Collective 1665c7afd0dbSLois Curfman McInnes 1666c96a6f78SLois Curfman McInnes Input Parameter: 1667f6dfbefdSBarry Smith . snes - `SNES` context 1668c96a6f78SLois Curfman McInnes 1669c96a6f78SLois Curfman McInnes Output Parameter: 1670c96a6f78SLois Curfman McInnes . lits - number of linear iterations 1671c96a6f78SLois Curfman McInnes 1672dc4c0fb0SBarry Smith Level: intermediate 1673dc4c0fb0SBarry Smith 1674c96a6f78SLois Curfman McInnes Notes: 1675f6dfbefdSBarry Smith This counter is reset to zero for each successive call to `SNESSolve()` unless `SNESSetCountersReset()` is used. 1676c96a6f78SLois Curfman McInnes 1677f6dfbefdSBarry 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 1678f6dfbefdSBarry Smith then call `KSPGetIterationNumber()` after the failed solve. 1679010be392SBarry Smith 16801cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetIterationNumber()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESSetCountersReset()` 1681c96a6f78SLois Curfman McInnes @*/ 1682d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveIterations(SNES snes, PetscInt *lits) 1683d71ae5a4SJacob Faibussowitsch { 16843a40ed3dSBarry Smith PetscFunctionBegin; 16850700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 16864f572ea9SToby Isaac PetscAssertPointer(lits, 2); 1687c96a6f78SLois Curfman McInnes *lits = snes->linear_its; 16883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1689c96a6f78SLois Curfman McInnes } 1690c96a6f78SLois Curfman McInnes 1691971e163fSPeter Brune /*@ 1692971e163fSPeter Brune SNESSetCountersReset - Sets whether or not the counters for linear iterations and function evaluations 1693f6dfbefdSBarry Smith are reset every time `SNESSolve()` is called. 1694971e163fSPeter Brune 1695c3339decSBarry Smith Logically Collective 1696971e163fSPeter Brune 1697d8d19677SJose E. Roman Input Parameters: 1698f6dfbefdSBarry Smith + snes - `SNES` context 1699f6dfbefdSBarry Smith - reset - whether to reset the counters or not, defaults to `PETSC_TRUE` 1700971e163fSPeter Brune 1701971e163fSPeter Brune Level: developer 1702971e163fSPeter Brune 17031cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()` 1704971e163fSPeter Brune @*/ 1705d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCountersReset(SNES snes, PetscBool reset) 1706d71ae5a4SJacob Faibussowitsch { 1707971e163fSPeter Brune PetscFunctionBegin; 1708971e163fSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1709971e163fSPeter Brune PetscValidLogicalCollectiveBool(snes, reset, 2); 1710971e163fSPeter Brune snes->counters_reset = reset; 17113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1712971e163fSPeter Brune } 1713971e163fSPeter Brune 17142999313aSBarry Smith /*@ 171512b1dd1aSStefano Zampini SNESResetCounters - Reset counters for linear iterations and function evaluations. 171612b1dd1aSStefano Zampini 171712b1dd1aSStefano Zampini Logically Collective 171812b1dd1aSStefano Zampini 171912b1dd1aSStefano Zampini Input Parameters: 172012b1dd1aSStefano Zampini . snes - `SNES` context 172112b1dd1aSStefano Zampini 172212b1dd1aSStefano Zampini Level: developer 172312b1dd1aSStefano Zampini 172412b1dd1aSStefano Zampini Note: 172512b1dd1aSStefano Zampini It honors the flag set with `SNESSetCountersReset()` 172612b1dd1aSStefano Zampini 172712b1dd1aSStefano Zampini .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()` 172812b1dd1aSStefano Zampini @*/ 172912b1dd1aSStefano Zampini PetscErrorCode SNESResetCounters(SNES snes) 173012b1dd1aSStefano Zampini { 173112b1dd1aSStefano Zampini PetscFunctionBegin; 173212b1dd1aSStefano Zampini PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 173312b1dd1aSStefano Zampini if (snes->counters_reset) { 173412b1dd1aSStefano Zampini snes->nfuncs = 0; 173512b1dd1aSStefano Zampini snes->linear_its = 0; 173612b1dd1aSStefano Zampini snes->numFailures = 0; 173712b1dd1aSStefano Zampini } 173812b1dd1aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 173912b1dd1aSStefano Zampini } 174012b1dd1aSStefano Zampini 174112b1dd1aSStefano Zampini /*@ 1742f6dfbefdSBarry Smith SNESSetKSP - Sets a `KSP` context for the `SNES` object to use 17432999313aSBarry Smith 1744420bcc1bSBarry Smith Not Collective, but the `SNES` and `KSP` objects must live on the same `MPI_Comm` 17452999313aSBarry Smith 17462999313aSBarry Smith Input Parameters: 1747f6dfbefdSBarry Smith + snes - the `SNES` context 1748f6dfbefdSBarry Smith - ksp - the `KSP` context 17492999313aSBarry Smith 1750dc4c0fb0SBarry Smith Level: developer 1751dc4c0fb0SBarry Smith 17522999313aSBarry Smith Notes: 1753f6dfbefdSBarry Smith The `SNES` object already has its `KSP` object, you can obtain with `SNESGetKSP()` 17542999313aSBarry Smith so this routine is rarely needed. 17552999313aSBarry Smith 1756f6dfbefdSBarry Smith The `KSP` object that is already in the `SNES` object has its reference count 1757420bcc1bSBarry Smith decreased by one when this is called. 17582999313aSBarry Smith 175942747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `KSP`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()` 17602999313aSBarry Smith @*/ 1761d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetKSP(SNES snes, KSP ksp) 1762d71ae5a4SJacob Faibussowitsch { 17632999313aSBarry Smith PetscFunctionBegin; 17640700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 17650700a824SBarry Smith PetscValidHeaderSpecific(ksp, KSP_CLASSID, 2); 17662999313aSBarry Smith PetscCheckSameComm(snes, 1, ksp, 2); 17679566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)ksp)); 17689566063dSJacob Faibussowitsch if (snes->ksp) PetscCall(PetscObjectDereference((PetscObject)snes->ksp)); 17692999313aSBarry Smith snes->ksp = ksp; 17703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17712999313aSBarry Smith } 17722999313aSBarry Smith 177352baeb72SSatish Balay /*@ 177477e5a1f9SBarry Smith SNESParametersInitialize - Sets all the parameters in `snes` to their default value (when `SNESCreate()` was called) if they 177577e5a1f9SBarry Smith currently contain default values 177677e5a1f9SBarry Smith 177777e5a1f9SBarry Smith Collective 177877e5a1f9SBarry Smith 177977e5a1f9SBarry Smith Input Parameter: 178077e5a1f9SBarry Smith . snes - the `SNES` object 178177e5a1f9SBarry Smith 178277e5a1f9SBarry Smith Level: developer 178377e5a1f9SBarry Smith 178477e5a1f9SBarry Smith Developer Note: 178577e5a1f9SBarry Smith This is called by all the `SNESCreate_XXX()` routines. 178677e5a1f9SBarry Smith 178777e5a1f9SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`, 178877e5a1f9SBarry Smith `PetscObjectParameterSetDefault()` 178977e5a1f9SBarry Smith @*/ 179077e5a1f9SBarry Smith PetscErrorCode SNESParametersInitialize(SNES snes) 179177e5a1f9SBarry Smith { 179277e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, max_its, 50); 179377e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, max_funcs, 10000); 179477e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, rtol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8); 179577e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, abstol, PetscDefined(USE_REAL_SINGLE) ? 1.e-25 : 1.e-50); 179677e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, stol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8); 179777e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, divtol, 1.e4); 179877e5a1f9SBarry Smith return PETSC_SUCCESS; 179977e5a1f9SBarry Smith } 180077e5a1f9SBarry Smith 180177e5a1f9SBarry Smith /*@ 1802dc4c0fb0SBarry Smith SNESCreate - Creates a nonlinear solver context used to manage a set of nonlinear solves 18039b94acceSBarry Smith 1804d083f849SBarry Smith Collective 1805c7afd0dbSLois Curfman McInnes 1806f6dfbefdSBarry Smith Input Parameter: 1807906ed7ccSBarry Smith . comm - MPI communicator 18089b94acceSBarry Smith 18099b94acceSBarry Smith Output Parameter: 181020f4b53cSBarry Smith . outsnes - the new `SNES` context 18119b94acceSBarry Smith 1812c7afd0dbSLois Curfman McInnes Options Database Keys: 18137addb90fSBarry Smith + -snes_mf - Activates default matrix-free Jacobian-vector products, and no matrix to construct a preconditioner 18147addb90fSBarry Smith . -snes_mf_operator - Activates default matrix-free Jacobian-vector products, and a user-provided matrix as set by `SNESSetJacobian()` 1815dc4c0fb0SBarry Smith . -snes_fd_coloring - uses a relative fast computation of the Jacobian using finite differences and a graph coloring 1816c7afd0dbSLois Curfman McInnes - -snes_fd - Uses (slow!) finite differences to compute Jacobian 1817c1f60f51SBarry Smith 181836851e7fSLois Curfman McInnes Level: beginner 181936851e7fSLois Curfman McInnes 182095452b02SPatrick Sanan Developer Notes: 1821f6dfbefdSBarry Smith `SNES` always creates a `KSP` object even though many `SNES` methods do not use it. This is 1822efd4aadfSBarry Smith unfortunate and should be fixed at some point. The flag snes->usesksp indicates if the 1823f6dfbefdSBarry Smith particular method does use `KSP` and regulates if the information about the `KSP` is printed 1824f6dfbefdSBarry Smith in `SNESView()`. 1825efd4aadfSBarry Smith 1826f6dfbefdSBarry Smith `TSSetFromOptions()` does call `SNESSetFromOptions()` which can lead to users being confused 1827f6dfbefdSBarry Smith by help messages about meaningless `SNES` options. 1828f6dfbefdSBarry Smith 18297addb90fSBarry Smith `SNES` always creates the `snes->kspconvctx` even though it is used by only one type. This should be fixed. 1830efd4aadfSBarry Smith 1831e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()` 18329b94acceSBarry Smith @*/ 1833d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESCreate(MPI_Comm comm, SNES *outsnes) 1834d71ae5a4SJacob Faibussowitsch { 18359b94acceSBarry Smith SNES snes; 1836fa9f3622SBarry Smith SNESKSPEW *kctx; 183737fcc0dbSBarry Smith 18383a40ed3dSBarry Smith PetscFunctionBegin; 18394f572ea9SToby Isaac PetscAssertPointer(outsnes, 2); 18409566063dSJacob Faibussowitsch PetscCall(SNESInitializePackage()); 18418ba1e511SMatthew Knepley 18429566063dSJacob Faibussowitsch PetscCall(PetscHeaderCreate(snes, SNES_CLASSID, "SNES", "Nonlinear solver", "SNES", comm, SNESDestroy, SNESView)); 18438d359177SBarry Smith snes->ops->converged = SNESConvergedDefault; 18442c155ee1SBarry Smith snes->usesksp = PETSC_TRUE; 18459b94acceSBarry Smith snes->norm = 0.0; 1846c1e67a49SFande Kong snes->xnorm = 0.0; 1847c1e67a49SFande Kong snes->ynorm = 0.0; 1848365a6726SPeter Brune snes->normschedule = SNES_NORM_ALWAYS; 18496c67d002SPeter Brune snes->functype = SNES_FUNCTION_DEFAULT; 1850b4874afaSBarry Smith snes->ttol = 0.0; 185177e5a1f9SBarry Smith 1852e37c518bSBarry Smith snes->rnorm0 = 0; 18539b94acceSBarry Smith snes->nfuncs = 0; 185450ffb88aSMatthew Knepley snes->numFailures = 0; 185550ffb88aSMatthew Knepley snes->maxFailures = 1; 18567a00f4a9SLois Curfman McInnes snes->linear_its = 0; 1857e35cf81dSBarry Smith snes->lagjacobian = 1; 185837ec4e1aSPeter Brune snes->jac_iter = 0; 185937ec4e1aSPeter Brune snes->lagjac_persist = PETSC_FALSE; 1860a8054027SBarry Smith snes->lagpreconditioner = 1; 186137ec4e1aSPeter Brune snes->pre_iter = 0; 186237ec4e1aSPeter Brune snes->lagpre_persist = PETSC_FALSE; 1863639f9d9dSBarry Smith snes->numbermonitors = 0; 1864c4421ceaSFande Kong snes->numberreasonviews = 0; 18659e5d0892SLisandro Dalcin snes->data = NULL; 18664dc4c822SBarry Smith snes->setupcalled = PETSC_FALSE; 1867186905e3SBarry Smith snes->ksp_ewconv = PETSC_FALSE; 18686f24a144SLois Curfman McInnes snes->nwork = 0; 18699e5d0892SLisandro Dalcin snes->work = NULL; 187058c9b817SLisandro Dalcin snes->nvwork = 0; 18719e5d0892SLisandro Dalcin snes->vwork = NULL; 1872758f92a0SBarry Smith snes->conv_hist_len = 0; 1873758f92a0SBarry Smith snes->conv_hist_max = 0; 18740298fd71SBarry Smith snes->conv_hist = NULL; 18750298fd71SBarry Smith snes->conv_hist_its = NULL; 1876758f92a0SBarry Smith snes->conv_hist_reset = PETSC_TRUE; 1877971e163fSPeter Brune snes->counters_reset = PETSC_TRUE; 1878e4ed7901SPeter Brune snes->vec_func_init_set = PETSC_FALSE; 1879184914b5SBarry Smith snes->reason = SNES_CONVERGED_ITERATING; 1880efd4aadfSBarry Smith snes->npcside = PC_RIGHT; 1881b3cd9a81SMatthew G. Knepley snes->setfromoptionscalled = 0; 1882c40d0f55SPeter Brune 1883d8f46077SPeter Brune snes->mf = PETSC_FALSE; 1884d8f46077SPeter Brune snes->mf_operator = PETSC_FALSE; 1885d8f46077SPeter Brune snes->mf_version = 1; 1886d8f46077SPeter Brune 18873d4c4710SBarry Smith snes->numLinearSolveFailures = 0; 18883d4c4710SBarry Smith snes->maxLinearSolveFailures = 1; 18893d4c4710SBarry Smith 1890349187a7SBarry Smith snes->vizerotolerance = 1.e-8; 189176bd3646SJed Brown snes->checkjacdomainerror = PetscDefined(USE_DEBUG) ? PETSC_TRUE : PETSC_FALSE; 1892349187a7SBarry Smith 18934fc747eaSLawrence Mitchell /* Set this to true if the implementation of SNESSolve_XXX does compute the residual at the final solution. */ 18944fc747eaSLawrence Mitchell snes->alwayscomputesfinalresidual = PETSC_FALSE; 18954fc747eaSLawrence Mitchell 18969b94acceSBarry Smith /* Create context to compute Eisenstat-Walker relative tolerance for KSP */ 18974dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&kctx)); 1898f5af7f23SKarl Rupp 1899835f2295SStefano Zampini snes->kspconvctx = kctx; 19009b94acceSBarry Smith kctx->version = 2; 19010f0abf79SStefano Zampini kctx->rtol_0 = 0.3; /* Eisenstat and Walker suggest rtol_0=.5, but 19029b94acceSBarry Smith this was too large for some test cases */ 190375567043SBarry Smith kctx->rtol_last = 0.0; 19040f0abf79SStefano Zampini kctx->rtol_max = 0.9; 19059b94acceSBarry Smith kctx->gamma = 1.0; 19060f0abf79SStefano Zampini kctx->alpha = 0.5 * (1.0 + PetscSqrtReal(5.0)); 190771f87433Sdalcinl kctx->alpha2 = kctx->alpha; 19080f0abf79SStefano Zampini kctx->threshold = 0.1; 190975567043SBarry Smith kctx->lresid_last = 0.0; 191075567043SBarry Smith kctx->norm_last = 0.0; 19119b94acceSBarry Smith 19120f0abf79SStefano Zampini kctx->rk_last = 0.0; 19130f0abf79SStefano Zampini kctx->rk_last_2 = 0.0; 19140f0abf79SStefano Zampini kctx->rtol_last_2 = 0.0; 19150f0abf79SStefano Zampini kctx->v4_p1 = 0.1; 19160f0abf79SStefano Zampini kctx->v4_p2 = 0.4; 19170f0abf79SStefano Zampini kctx->v4_p3 = 0.7; 19180f0abf79SStefano Zampini kctx->v4_m1 = 0.8; 19190f0abf79SStefano Zampini kctx->v4_m2 = 0.5; 19200f0abf79SStefano Zampini kctx->v4_m3 = 0.1; 19210f0abf79SStefano Zampini kctx->v4_m4 = 0.5; 19220f0abf79SStefano Zampini 1923b50c806fSBarry Smith PetscCall(SNESParametersInitialize(snes)); 19249b94acceSBarry Smith *outsnes = snes; 19253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19269b94acceSBarry Smith } 19279b94acceSBarry Smith 19289b94acceSBarry Smith /*@C 19299b94acceSBarry Smith SNESSetFunction - Sets the function evaluation routine and function 1930f6dfbefdSBarry Smith vector for use by the `SNES` routines in solving systems of nonlinear 19319b94acceSBarry Smith equations. 19329b94acceSBarry Smith 1933c3339decSBarry Smith Logically Collective 1934fee21e36SBarry Smith 1935c7afd0dbSLois Curfman McInnes Input Parameters: 1936f6dfbefdSBarry Smith + snes - the `SNES` context 1937dc4c0fb0SBarry Smith . r - vector to store function values, may be `NULL` 19388434afd1SBarry Smith . f - function evaluation routine; for calling sequence see `SNESFunctionFn` 1939c7afd0dbSLois Curfman McInnes - ctx - [optional] user-defined context for private data for the 1940dc4c0fb0SBarry Smith function evaluation routine (may be `NULL`) 19419b94acceSBarry Smith 194236851e7fSLois Curfman McInnes Level: beginner 194336851e7fSLois Curfman McInnes 19448434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetPicard()`, `SNESFunctionFn` 19459b94acceSBarry Smith @*/ 19462a8381b2SBarry Smith PetscErrorCode SNESSetFunction(SNES snes, Vec r, SNESFunctionFn *f, PetscCtx ctx) 1947d71ae5a4SJacob Faibussowitsch { 19486cab3a1bSJed Brown DM dm; 19496cab3a1bSJed Brown 19503a40ed3dSBarry Smith PetscFunctionBegin; 19510700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1952d2a683ecSLisandro Dalcin if (r) { 1953d2a683ecSLisandro Dalcin PetscValidHeaderSpecific(r, VEC_CLASSID, 2); 1954d2a683ecSLisandro Dalcin PetscCheckSameComm(snes, 1, r, 2); 19559566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)r)); 19569566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_func)); 195785385478SLisandro Dalcin snes->vec_func = r; 1958d2a683ecSLisandro Dalcin } 19599566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 19609566063dSJacob Faibussowitsch PetscCall(DMSNESSetFunction(dm, f, ctx)); 196148a46eb9SPierre Jolivet if (f == SNESPicardComputeFunction) PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx)); 19623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19639b94acceSBarry Smith } 19649b94acceSBarry Smith 1965e4ed7901SPeter Brune /*@C 19660b4db180SJacob Faibussowitsch SNESSetInitialFunction - Set an already computed function evaluation at the initial guess to be reused by `SNESSolve()`. 1967e4ed7901SPeter Brune 1968c3339decSBarry Smith Logically Collective 1969e4ed7901SPeter Brune 1970e4ed7901SPeter Brune Input Parameters: 1971f6dfbefdSBarry Smith + snes - the `SNES` context 1972e4ed7901SPeter Brune - f - vector to store function value 1973e4ed7901SPeter Brune 1974dc4c0fb0SBarry Smith Level: developer 1975dc4c0fb0SBarry Smith 1976e4ed7901SPeter Brune Notes: 1977e4ed7901SPeter Brune This should not be modified during the solution procedure. 1978e4ed7901SPeter Brune 1979f6dfbefdSBarry Smith This is used extensively in the `SNESFAS` hierarchy and in nonlinear preconditioning. 1980e4ed7901SPeter Brune 19811cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetInitialFunctionNorm()` 1982e4ed7901SPeter Brune @*/ 1983d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetInitialFunction(SNES snes, Vec f) 1984d71ae5a4SJacob Faibussowitsch { 1985e4ed7901SPeter Brune Vec vec_func; 1986e4ed7901SPeter Brune 1987e4ed7901SPeter Brune PetscFunctionBegin; 1988e4ed7901SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1989e4ed7901SPeter Brune PetscValidHeaderSpecific(f, VEC_CLASSID, 2); 1990e4ed7901SPeter Brune PetscCheckSameComm(snes, 1, f, 2); 1991efd4aadfSBarry Smith if (snes->npcside == PC_LEFT && snes->functype == SNES_FUNCTION_PRECONDITIONED) { 1992902f982fSPeter Brune snes->vec_func_init_set = PETSC_FALSE; 19933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1994902f982fSPeter Brune } 19959566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &vec_func, NULL, NULL)); 19969566063dSJacob Faibussowitsch PetscCall(VecCopy(f, vec_func)); 1997f5af7f23SKarl Rupp 1998217b9c2eSPeter Brune snes->vec_func_init_set = PETSC_TRUE; 19993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2000e4ed7901SPeter Brune } 2001e4ed7901SPeter Brune 2002534ebe21SPeter Brune /*@ 2003f6dfbefdSBarry Smith SNESSetNormSchedule - Sets the `SNESNormSchedule` used in convergence and monitoring 2004f6dfbefdSBarry Smith of the `SNES` method, when norms are computed in the solving process 2005534ebe21SPeter Brune 2006c3339decSBarry Smith Logically Collective 2007534ebe21SPeter Brune 2008534ebe21SPeter Brune Input Parameters: 2009f6dfbefdSBarry Smith + snes - the `SNES` context 2010365a6726SPeter Brune - normschedule - the frequency of norm computation 2011534ebe21SPeter Brune 2012517f1916SMatthew G. Knepley Options Database Key: 201367b8a455SSatish Balay . -snes_norm_schedule <none, always, initialonly, finalonly, initialfinalonly> - set the schedule 2014517f1916SMatthew G. Knepley 2015dc4c0fb0SBarry Smith Level: advanced 2016dc4c0fb0SBarry Smith 2017534ebe21SPeter Brune Notes: 2018f6dfbefdSBarry Smith Only certain `SNES` methods support certain `SNESNormSchedules`. Most require evaluation 2019534ebe21SPeter Brune of the nonlinear function and the taking of its norm at every iteration to 2020534ebe21SPeter Brune even ensure convergence at all. However, methods such as custom Gauss-Seidel methods 2021f6dfbefdSBarry Smith `SNESNGS` and the like do not require the norm of the function to be computed, and therefore 2022534ebe21SPeter Brune may either be monitored for convergence or not. As these are often used as nonlinear 2023534ebe21SPeter Brune preconditioners, monitoring the norm of their error is not a useful enterprise within 2024534ebe21SPeter Brune their solution. 2025534ebe21SPeter Brune 2026e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNESNormSchedule`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()` 2027534ebe21SPeter Brune @*/ 2028d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNormSchedule(SNES snes, SNESNormSchedule normschedule) 2029d71ae5a4SJacob Faibussowitsch { 2030534ebe21SPeter Brune PetscFunctionBegin; 2031534ebe21SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2032365a6726SPeter Brune snes->normschedule = normschedule; 20333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2034534ebe21SPeter Brune } 2035534ebe21SPeter Brune 2036534ebe21SPeter Brune /*@ 2037f6dfbefdSBarry Smith SNESGetNormSchedule - Gets the `SNESNormSchedule` used in convergence and monitoring 2038f6dfbefdSBarry Smith of the `SNES` method. 2039534ebe21SPeter Brune 2040c3339decSBarry Smith Logically Collective 2041534ebe21SPeter Brune 2042534ebe21SPeter Brune Input Parameters: 2043f6dfbefdSBarry Smith + snes - the `SNES` context 2044365a6726SPeter Brune - normschedule - the type of the norm used 2045534ebe21SPeter Brune 2046534ebe21SPeter Brune Level: advanced 2047534ebe21SPeter Brune 20481cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 2049534ebe21SPeter Brune @*/ 2050d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNormSchedule(SNES snes, SNESNormSchedule *normschedule) 2051d71ae5a4SJacob Faibussowitsch { 2052534ebe21SPeter Brune PetscFunctionBegin; 2053534ebe21SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2054365a6726SPeter Brune *normschedule = snes->normschedule; 20553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2056534ebe21SPeter Brune } 2057534ebe21SPeter Brune 2058c5ce4427SMatthew G. Knepley /*@ 2059c5ce4427SMatthew G. Knepley SNESSetFunctionNorm - Sets the last computed residual norm. 2060c5ce4427SMatthew G. Knepley 2061c3339decSBarry Smith Logically Collective 2062c5ce4427SMatthew G. Knepley 2063c5ce4427SMatthew G. Knepley Input Parameters: 2064f6dfbefdSBarry Smith + snes - the `SNES` context 2065f6dfbefdSBarry Smith - norm - the value of the norm 2066c5ce4427SMatthew G. Knepley 2067c5ce4427SMatthew G. Knepley Level: developer 2068c5ce4427SMatthew G. Knepley 20691cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 2070c5ce4427SMatthew G. Knepley @*/ 2071d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionNorm(SNES snes, PetscReal norm) 2072d71ae5a4SJacob Faibussowitsch { 2073c5ce4427SMatthew G. Knepley PetscFunctionBegin; 2074c5ce4427SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2075c5ce4427SMatthew G. Knepley snes->norm = norm; 20763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2077c5ce4427SMatthew G. Knepley } 2078c5ce4427SMatthew G. Knepley 2079c5ce4427SMatthew G. Knepley /*@ 2080c5ce4427SMatthew G. Knepley SNESGetFunctionNorm - Gets the last computed norm of the residual 2081c5ce4427SMatthew G. Knepley 2082c5ce4427SMatthew G. Knepley Not Collective 2083c5ce4427SMatthew G. Knepley 2084c5ce4427SMatthew G. Knepley Input Parameter: 2085f6dfbefdSBarry Smith . snes - the `SNES` context 2086c5ce4427SMatthew G. Knepley 2087c5ce4427SMatthew G. Knepley Output Parameter: 2088c5ce4427SMatthew G. Knepley . norm - the last computed residual norm 2089c5ce4427SMatthew G. Knepley 2090c5ce4427SMatthew G. Knepley Level: developer 2091c5ce4427SMatthew G. Knepley 20921cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 2093c5ce4427SMatthew G. Knepley @*/ 2094d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionNorm(SNES snes, PetscReal *norm) 2095d71ae5a4SJacob Faibussowitsch { 2096c5ce4427SMatthew G. Knepley PetscFunctionBegin; 2097c5ce4427SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 20984f572ea9SToby Isaac PetscAssertPointer(norm, 2); 2099c5ce4427SMatthew G. Knepley *norm = snes->norm; 21003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2101c5ce4427SMatthew G. Knepley } 2102c5ce4427SMatthew G. Knepley 2103c1e67a49SFande Kong /*@ 2104f6dfbefdSBarry Smith SNESGetUpdateNorm - Gets the last computed norm of the solution update 2105c1e67a49SFande Kong 2106c1e67a49SFande Kong Not Collective 2107c1e67a49SFande Kong 2108c1e67a49SFande Kong Input Parameter: 2109f6dfbefdSBarry Smith . snes - the `SNES` context 2110c1e67a49SFande Kong 2111c1e67a49SFande Kong Output Parameter: 2112c1e67a49SFande Kong . ynorm - the last computed update norm 2113c1e67a49SFande Kong 2114c1e67a49SFande Kong Level: developer 2115c1e67a49SFande Kong 2116f6dfbefdSBarry Smith Note: 2117f6dfbefdSBarry Smith The new solution is the current solution plus the update, so this norm is an indication of the size of the update 2118f6dfbefdSBarry Smith 21191cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()` 2120c1e67a49SFande Kong @*/ 2121d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUpdateNorm(SNES snes, PetscReal *ynorm) 2122d71ae5a4SJacob Faibussowitsch { 2123c1e67a49SFande Kong PetscFunctionBegin; 2124c1e67a49SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 21254f572ea9SToby Isaac PetscAssertPointer(ynorm, 2); 2126c1e67a49SFande Kong *ynorm = snes->ynorm; 21273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2128c1e67a49SFande Kong } 2129c1e67a49SFande Kong 2130c1e67a49SFande Kong /*@ 21314591eaf2SFande Kong SNESGetSolutionNorm - Gets the last computed norm of the solution 2132c1e67a49SFande Kong 2133c1e67a49SFande Kong Not Collective 2134c1e67a49SFande Kong 2135c1e67a49SFande Kong Input Parameter: 2136f6dfbefdSBarry Smith . snes - the `SNES` context 2137c1e67a49SFande Kong 2138c1e67a49SFande Kong Output Parameter: 2139c1e67a49SFande Kong . xnorm - the last computed solution norm 2140c1e67a49SFande Kong 2141c1e67a49SFande Kong Level: developer 2142c1e67a49SFande Kong 21431cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`, `SNESGetUpdateNorm()` 2144c1e67a49SFande Kong @*/ 2145d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionNorm(SNES snes, PetscReal *xnorm) 2146d71ae5a4SJacob Faibussowitsch { 2147c1e67a49SFande Kong PetscFunctionBegin; 2148c1e67a49SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 21494f572ea9SToby Isaac PetscAssertPointer(xnorm, 2); 2150c1e67a49SFande Kong *xnorm = snes->xnorm; 21513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2152c1e67a49SFande Kong } 2153c1e67a49SFande Kong 2154cc4c1da9SBarry Smith /*@ 2155f6dfbefdSBarry Smith SNESSetFunctionType - Sets the `SNESFunctionType` 2156f6dfbefdSBarry Smith of the `SNES` method. 215747073ea2SPeter Brune 2158c3339decSBarry Smith Logically Collective 215947073ea2SPeter Brune 216047073ea2SPeter Brune Input Parameters: 2161f6dfbefdSBarry Smith + snes - the `SNES` context 2162f6dfbefdSBarry Smith - type - the function type 216347073ea2SPeter Brune 216447073ea2SPeter Brune Level: developer 216547073ea2SPeter Brune 2166420bcc1bSBarry Smith Values of the function type\: 2167f6dfbefdSBarry Smith + `SNES_FUNCTION_DEFAULT` - the default for the given `SNESType` 2168f6dfbefdSBarry Smith . `SNES_FUNCTION_UNPRECONDITIONED` - an unpreconditioned function evaluation (this is the function provided with `SNESSetFunction()` 2169f6dfbefdSBarry Smith - `SNES_FUNCTION_PRECONDITIONED` - a transformation of the function provided with `SNESSetFunction()` 2170f6dfbefdSBarry Smith 2171420bcc1bSBarry Smith Note: 2172f6dfbefdSBarry Smith Different `SNESType`s use this value in different ways 2173f6dfbefdSBarry Smith 21741cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFunctionType`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 217547073ea2SPeter Brune @*/ 2176d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionType(SNES snes, SNESFunctionType type) 2177d71ae5a4SJacob Faibussowitsch { 217847073ea2SPeter Brune PetscFunctionBegin; 217947073ea2SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 218047073ea2SPeter Brune snes->functype = type; 21813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 218247073ea2SPeter Brune } 218347073ea2SPeter Brune 2184cc4c1da9SBarry Smith /*@ 2185f6dfbefdSBarry Smith SNESGetFunctionType - Gets the `SNESFunctionType` used in convergence and monitoring set with `SNESSetFunctionType()` 218647073ea2SPeter Brune of the SNES method. 218747073ea2SPeter Brune 2188c3339decSBarry Smith Logically Collective 218947073ea2SPeter Brune 219047073ea2SPeter Brune Input Parameters: 2191f6dfbefdSBarry Smith + snes - the `SNES` context 2192f6dfbefdSBarry Smith - type - the type of the function evaluation, see `SNESSetFunctionType()` 219347073ea2SPeter Brune 219447073ea2SPeter Brune Level: advanced 219547073ea2SPeter Brune 21961cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetFunctionType()`, `SNESFunctionType`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 219747073ea2SPeter Brune @*/ 2198d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionType(SNES snes, SNESFunctionType *type) 2199d71ae5a4SJacob Faibussowitsch { 220047073ea2SPeter Brune PetscFunctionBegin; 220147073ea2SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 220247073ea2SPeter Brune *type = snes->functype; 22033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2204534ebe21SPeter Brune } 2205534ebe21SPeter Brune 2206c79ef259SPeter Brune /*@C 2207be95d8f1SBarry Smith SNESSetNGS - Sets the user nonlinear Gauss-Seidel routine for 2208c79ef259SPeter Brune use with composed nonlinear solvers. 2209c79ef259SPeter Brune 2210c79ef259SPeter Brune Input Parameters: 22119bcc50f1SBarry Smith + snes - the `SNES` context, usually of the `SNESType` `SNESNGS` 22128434afd1SBarry Smith . f - function evaluation routine to apply Gauss-Seidel, see `SNESNGSFn` for calling sequence 221377e5a1f9SBarry Smith - ctx - [optional] user-defined context for private data for the smoother evaluation routine (may be `NULL`) 2214c79ef259SPeter Brune 2215dc4c0fb0SBarry Smith Level: intermediate 2216dc4c0fb0SBarry Smith 2217f6dfbefdSBarry Smith Note: 2218f6dfbefdSBarry Smith The `SNESNGS` routines are used by the composed nonlinear solver to generate 2219f6dfbefdSBarry Smith a problem appropriate update to the solution, particularly `SNESFAS`. 2220c79ef259SPeter Brune 22218434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGS`, `SNESGetNGS()`, `SNESNCG`, `SNESGetFunction()`, `SNESComputeNGS()`, `SNESNGSFn` 2222c79ef259SPeter Brune @*/ 22232a8381b2SBarry Smith PetscErrorCode SNESSetNGS(SNES snes, SNESNGSFn *f, PetscCtx ctx) 2224d71ae5a4SJacob Faibussowitsch { 22256cab3a1bSJed Brown DM dm; 22266cab3a1bSJed Brown 2227646217ecSPeter Brune PetscFunctionBegin; 22286cab3a1bSJed Brown PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 22299566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 22309566063dSJacob Faibussowitsch PetscCall(DMSNESSetNGS(dm, f, ctx)); 22313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2232646217ecSPeter Brune } 2233646217ecSPeter Brune 2234bbc1464cSBarry Smith /* 2235bbc1464cSBarry Smith This is used for -snes_mf_operator; it uses a duplicate of snes->jacobian_pre because snes->jacobian_pre cannot be 2236bbc1464cSBarry Smith changed during the KSPSolve() 2237bbc1464cSBarry Smith */ 22382a8381b2SBarry Smith PetscErrorCode SNESPicardComputeMFFunction(SNES snes, Vec x, Vec f, PetscCtx ctx) 2239d71ae5a4SJacob Faibussowitsch { 2240bbc1464cSBarry Smith DM dm; 2241bbc1464cSBarry Smith DMSNES sdm; 2242bbc1464cSBarry Smith 2243bbc1464cSBarry Smith PetscFunctionBegin; 22449566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 22459566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 2246bbc1464cSBarry Smith /* A(x)*x - b(x) */ 2247bbc1464cSBarry Smith if (sdm->ops->computepfunction) { 2248792fecdfSBarry Smith PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx)); 22499566063dSJacob Faibussowitsch PetscCall(VecScale(f, -1.0)); 22500df40c35SBarry Smith /* Cannot share nonzero pattern because of the possible use of SNESComputeJacobianDefault() */ 2251ef1023bdSBarry Smith if (!snes->picard) PetscCall(MatDuplicate(snes->jacobian_pre, MAT_DO_NOT_COPY_VALUES, &snes->picard)); 2252792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx)); 22539566063dSJacob Faibussowitsch PetscCall(MatMultAdd(snes->picard, x, f, f)); 2254bbc1464cSBarry Smith } else { 2255792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx)); 22569566063dSJacob Faibussowitsch PetscCall(MatMult(snes->picard, x, f)); 2257bbc1464cSBarry Smith } 22583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2259bbc1464cSBarry Smith } 2260bbc1464cSBarry Smith 22612a8381b2SBarry Smith PetscErrorCode SNESPicardComputeFunction(SNES snes, Vec x, Vec f, PetscCtx ctx) 2262d71ae5a4SJacob Faibussowitsch { 2263e03ab78fSPeter Brune DM dm; 2264942e3340SBarry Smith DMSNES sdm; 22656cab3a1bSJed Brown 22668b0a5094SBarry Smith PetscFunctionBegin; 22679566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 22689566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 22698b0a5094SBarry Smith /* A(x)*x - b(x) */ 2270bbc1464cSBarry Smith if (sdm->ops->computepfunction) { 2271792fecdfSBarry Smith PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx)); 22729566063dSJacob Faibussowitsch PetscCall(VecScale(f, -1.0)); 2273792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx)); 22749566063dSJacob Faibussowitsch PetscCall(MatMultAdd(snes->jacobian_pre, x, f, f)); 2275bbc1464cSBarry Smith } else { 2276792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx)); 22779566063dSJacob Faibussowitsch PetscCall(MatMult(snes->jacobian_pre, x, f)); 2278bbc1464cSBarry Smith } 22793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22808b0a5094SBarry Smith } 22818b0a5094SBarry Smith 22822a8381b2SBarry Smith PetscErrorCode SNESPicardComputeJacobian(SNES snes, Vec x1, Mat J, Mat B, PetscCtx ctx) 2283d71ae5a4SJacob Faibussowitsch { 22848b0a5094SBarry Smith PetscFunctionBegin; 2285e03ab78fSPeter Brune /* the jacobian matrix should be pre-filled in SNESPicardComputeFunction */ 2286bbc1464cSBarry Smith /* must assembly if matrix-free to get the last SNES solution */ 22879566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 22889566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 22893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22908b0a5094SBarry Smith } 22918b0a5094SBarry Smith 22928b0a5094SBarry Smith /*@C 22931d27aa22SBarry Smith SNESSetPicard - Use `SNES` to solve the system $A(x) x = bp(x) + b $ via a Picard type iteration (Picard linearization) 22948b0a5094SBarry Smith 2295c3339decSBarry Smith Logically Collective 22968b0a5094SBarry Smith 22978b0a5094SBarry Smith Input Parameters: 2298f6dfbefdSBarry Smith + snes - the `SNES` context 2299dc4c0fb0SBarry Smith . r - vector to store function values, may be `NULL` 23008434afd1SBarry Smith . bp - function evaluation routine, may be `NULL`, for the calling sequence see `SNESFunctionFn` 230126a11704SBarry Smith . Amat - matrix with which $A(x) x - bp(x) - b$ is to be computed 2302dc4c0fb0SBarry Smith . Pmat - matrix from which preconditioner is computed (usually the same as `Amat`) 23038434afd1SBarry Smith . J - function to compute matrix values, for the calling sequence see `SNESJacobianFn` 2304dc4c0fb0SBarry Smith - ctx - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`) 2305dc4c0fb0SBarry Smith 2306dc4c0fb0SBarry Smith Level: intermediate 23078b0a5094SBarry Smith 23088b0a5094SBarry Smith Notes: 230926a11704SBarry Smith It is often better to provide the nonlinear function $F()$ and some approximation to its Jacobian directly and use 2310f450aa47SBarry 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. 2311f450aa47SBarry Smith 2312f6dfbefdSBarry Smith One can call `SNESSetPicard()` or `SNESSetFunction()` (and possibly `SNESSetJacobian()`) but cannot call both 23138b0a5094SBarry Smith 23141d27aa22SBarry 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}$. 23151d27aa22SBarry Smith When an exact solver is used this corresponds to the "classic" Picard $A(x^{n}) x^{n+1} = bp(x^{n}) + b$ iteration. 23168b0a5094SBarry Smith 231726a11704SBarry Smith Run with `-snes_mf_operator` to solve the system with Newton's method using $A(x^{n})$ to construct the preconditioner. 23188b0a5094SBarry Smith 23190d04baf8SBarry Smith We implement the defect correction form of the Picard iteration because it converges much more generally when inexact linear solvers are used then 23201d27aa22SBarry Smith the direct Picard iteration $A(x^n) x^{n+1} = bp(x^n) + b$ 23218b0a5094SBarry Smith 23228b0a5094SBarry 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 23231d27aa22SBarry 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 23241d27aa22SBarry Smith different please contact us at petsc-dev@mcs.anl.gov and we'll have an entirely new argument \:-). 23258b0a5094SBarry Smith 23261d27aa22SBarry 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 232726a11704SBarry Smith $A(x^{n})$ is used to build the preconditioner 23286b7fb656SBarry Smith 232915229ffcSPierre 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. 23306b7fb656SBarry Smith 2331dc4c0fb0SBarry 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 233226a11704SBarry 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 233326a11704SBarry 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`. 2334aaa8cc7dSPierre Jolivet See the comment in src/snes/tutorials/ex15.c. 2335bbc1464cSBarry Smith 23369bcc50f1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESGetPicard()`, `SNESLineSearchPreCheckPicard()`, 23378434afd1SBarry Smith `SNESFunctionFn`, `SNESJacobianFn` 23388b0a5094SBarry Smith @*/ 23392a8381b2SBarry Smith PetscErrorCode SNESSetPicard(SNES snes, Vec r, SNESFunctionFn *bp, Mat Amat, Mat Pmat, SNESJacobianFn *J, PetscCtx ctx) 2340d71ae5a4SJacob Faibussowitsch { 2341e03ab78fSPeter Brune DM dm; 2342e03ab78fSPeter Brune 23438b0a5094SBarry Smith PetscFunctionBegin; 23448b0a5094SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 23459566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 23469566063dSJacob Faibussowitsch PetscCall(DMSNESSetPicard(dm, bp, J, ctx)); 23479566063dSJacob Faibussowitsch PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx)); 23489566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes, r, SNESPicardComputeFunction, ctx)); 23499566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESPicardComputeJacobian, ctx)); 23503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23518b0a5094SBarry Smith } 23528b0a5094SBarry Smith 23537971a8bfSPeter Brune /*@C 23547971a8bfSPeter Brune SNESGetPicard - Returns the context for the Picard iteration 23557971a8bfSPeter Brune 2356f6dfbefdSBarry Smith Not Collective, but `Vec` is parallel if `SNES` is parallel. Collective if `Vec` is requested, but has not been created yet. 23577971a8bfSPeter Brune 23587971a8bfSPeter Brune Input Parameter: 2359f6dfbefdSBarry Smith . snes - the `SNES` context 23607971a8bfSPeter Brune 2361d8d19677SJose E. Roman Output Parameters: 2362dc4c0fb0SBarry Smith + r - the function (or `NULL`) 23638434afd1SBarry Smith . f - the function (or `NULL`); for calling sequence see `SNESFunctionFn` 2364dc4c0fb0SBarry Smith . Amat - the matrix used to defined the operation A(x) x - b(x) (or `NULL`) 2365dc4c0fb0SBarry Smith . Pmat - the matrix from which the preconditioner will be constructed (or `NULL`) 23668434afd1SBarry Smith . J - the function for matrix evaluation (or `NULL`); for calling sequence see `SNESJacobianFn` 2367dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`) 23687971a8bfSPeter Brune 23697971a8bfSPeter Brune Level: advanced 23707971a8bfSPeter Brune 23718434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetFunction()`, `SNESSetPicard()`, `SNESGetFunction()`, `SNESGetJacobian()`, `SNESGetDM()`, `SNESFunctionFn`, `SNESJacobianFn` 23727971a8bfSPeter Brune @*/ 23732a8381b2SBarry Smith PetscErrorCode SNESGetPicard(SNES snes, Vec *r, SNESFunctionFn **f, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, PetscCtxRt ctx) 2374d71ae5a4SJacob Faibussowitsch { 23757971a8bfSPeter Brune DM dm; 23767971a8bfSPeter Brune 23777971a8bfSPeter Brune PetscFunctionBegin; 23787971a8bfSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 23799566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, r, NULL, NULL)); 23809566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL)); 23819566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 23829566063dSJacob Faibussowitsch PetscCall(DMSNESGetPicard(dm, f, J, ctx)); 23833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23847971a8bfSPeter Brune } 23857971a8bfSPeter Brune 2386d25893d9SBarry Smith /*@C 2387dc4c0fb0SBarry Smith SNESSetComputeInitialGuess - Sets a routine used to compute an initial guess for the nonlinear problem 2388d25893d9SBarry Smith 2389c3339decSBarry Smith Logically Collective 2390d25893d9SBarry Smith 2391d25893d9SBarry Smith Input Parameters: 2392f6dfbefdSBarry Smith + snes - the `SNES` context 23938434afd1SBarry Smith . func - function evaluation routine, see `SNESInitialGuessFn` for the calling sequence 2394d25893d9SBarry Smith - ctx - [optional] user-defined context for private data for the 2395dc4c0fb0SBarry Smith function evaluation routine (may be `NULL`) 2396d25893d9SBarry Smith 2397d25893d9SBarry Smith Level: intermediate 2398d25893d9SBarry Smith 23998434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESInitialGuessFn` 2400d25893d9SBarry Smith @*/ 24012a8381b2SBarry Smith PetscErrorCode SNESSetComputeInitialGuess(SNES snes, SNESInitialGuessFn *func, PetscCtx ctx) 2402d71ae5a4SJacob Faibussowitsch { 2403d25893d9SBarry Smith PetscFunctionBegin; 2404d25893d9SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2405d25893d9SBarry Smith if (func) snes->ops->computeinitialguess = func; 2406d25893d9SBarry Smith if (ctx) snes->initialguessP = ctx; 24073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2408d25893d9SBarry Smith } 2409d25893d9SBarry Smith 24101096aae1SMatthew Knepley /*@C 2411dc4c0fb0SBarry Smith SNESGetRhs - Gets the vector for solving F(x) = `rhs`. If `rhs` is not set 2412dd8e379bSPierre Jolivet it assumes a zero right-hand side. 24131096aae1SMatthew Knepley 2414c3339decSBarry Smith Logically Collective 24151096aae1SMatthew Knepley 24161096aae1SMatthew Knepley Input Parameter: 2417f6dfbefdSBarry Smith . snes - the `SNES` context 24181096aae1SMatthew Knepley 24191096aae1SMatthew Knepley Output Parameter: 2420dd8e379bSPierre Jolivet . rhs - the right-hand side vector or `NULL` if there is no right-hand side vector 24211096aae1SMatthew Knepley 24221096aae1SMatthew Knepley Level: intermediate 24231096aae1SMatthew Knepley 24241cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetFunction()` 24251096aae1SMatthew Knepley @*/ 2426d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetRhs(SNES snes, Vec *rhs) 2427d71ae5a4SJacob Faibussowitsch { 24281096aae1SMatthew Knepley PetscFunctionBegin; 24290700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 24304f572ea9SToby Isaac PetscAssertPointer(rhs, 2); 243185385478SLisandro Dalcin *rhs = snes->vec_rhs; 24323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24331096aae1SMatthew Knepley } 24341096aae1SMatthew Knepley 24359b94acceSBarry Smith /*@ 2436f6dfbefdSBarry Smith SNESComputeFunction - Calls the function that has been set with `SNESSetFunction()`. 24379b94acceSBarry Smith 2438c3339decSBarry Smith Collective 2439c7afd0dbSLois Curfman McInnes 24409b94acceSBarry Smith Input Parameters: 2441f6dfbefdSBarry Smith + snes - the `SNES` context 2442c7afd0dbSLois Curfman McInnes - x - input vector 24439b94acceSBarry Smith 24449b94acceSBarry Smith Output Parameter: 244576c63389SBarry Smith . f - function vector, as set by `SNESSetFunction()` 24469b94acceSBarry Smith 2447dc4c0fb0SBarry Smith Level: developer 2448dc4c0fb0SBarry Smith 244900677de2SStefano Zampini Notes: 2450f6dfbefdSBarry Smith `SNESComputeFunction()` is typically used within nonlinear solvers 2451bbc1464cSBarry Smith implementations, so users would not generally call this routine themselves. 245236851e7fSLois Curfman McInnes 245376c63389SBarry Smith When solving for $F(x) = b$, this routine computes $f = F(x) - b$. 245400677de2SStefano Zampini 245576c63389SBarry Smith This function usually appears in the pattern. 245676c63389SBarry Smith .vb 245776c63389SBarry Smith SNESComputeFunction(snes, x, f); 245876c63389SBarry Smith VecNorm(f, &fnorm); 245976c63389SBarry Smith SNESCheckFunctionDomainError(snes, fnorm); or SNESLineSearchCheckFunctionDomainError(ls, fnorm); 246076c63389SBarry Smith .ve 246176c63389SBarry Smith to collectively handle the use of `SNESSetFunctionDomainError()` in the provided callback function. 246276c63389SBarry Smith 246376c63389SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeMFFunction()`, `SNESSetFunctionDomainError()` 24649b94acceSBarry Smith @*/ 246576c63389SBarry Smith PetscErrorCode SNESComputeFunction(SNES snes, Vec x, Vec f) 2466d71ae5a4SJacob Faibussowitsch { 24676cab3a1bSJed Brown DM dm; 2468942e3340SBarry Smith DMSNES sdm; 24699b94acceSBarry Smith 24703a40ed3dSBarry Smith PetscFunctionBegin; 24710700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 24720700a824SBarry Smith PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 247376c63389SBarry Smith PetscValidHeaderSpecific(f, VEC_CLASSID, 3); 2474c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, x, 2); 247576c63389SBarry Smith PetscCheckSameComm(snes, 1, f, 3); 2476e0f629ddSJacob Faibussowitsch PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2477184914b5SBarry Smith 24789566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 24799566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 24800fdf79fbSJacob 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()."); 248132f3f7c2SPeter Brune if (sdm->ops->computefunction) { 248276c63389SBarry Smith if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, f, 0)); 24839566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(x)); 24848ddeebeaSSteve Benbow /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */ 248576c63389SBarry Smith snes->functiondomainerror = PETSC_FALSE; 2486800f99ffSJeremy L Thompson { 2487800f99ffSJeremy L Thompson void *ctx; 24888434afd1SBarry Smith SNESFunctionFn *computefunction; 2489800f99ffSJeremy L Thompson PetscCall(DMSNESGetFunction(dm, &computefunction, &ctx)); 249076c63389SBarry Smith PetscCallBack("SNES callback function", (*computefunction)(snes, x, f, ctx)); 2491800f99ffSJeremy L Thompson } 24929566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(x)); 249376c63389SBarry Smith if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, f, 0)); 24940fdf79fbSJacob Faibussowitsch } else /* if (snes->vec_rhs) */ { 249576c63389SBarry Smith PetscCall(MatMult(snes->jacobian, x, f)); 24960fdf79fbSJacob Faibussowitsch } 249776c63389SBarry Smith if (snes->vec_rhs) PetscCall(VecAXPY(f, -1.0, snes->vec_rhs)); 2498ae3c334cSLois Curfman McInnes snes->nfuncs++; 2499422a814eSBarry Smith /* 250076c63389SBarry Smith domainerror might not be set on all processes; so we tag vector locally with infinity and the next inner product or norm will 2501422a814eSBarry Smith propagate the value to all processes 2502422a814eSBarry Smith */ 250376c63389SBarry Smith PetscCall(VecFlag(f, snes->functiondomainerror)); 25043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 25059b94acceSBarry Smith } 25069b94acceSBarry Smith 2507c79ef259SPeter Brune /*@ 25080b4b7b1cSBarry Smith SNESComputeMFFunction - Calls the function that has been set with `DMSNESSetMFFunction()`. 2509bbc1464cSBarry Smith 2510c3339decSBarry Smith Collective 2511bbc1464cSBarry Smith 2512bbc1464cSBarry Smith Input Parameters: 2513f6dfbefdSBarry Smith + snes - the `SNES` context 2514bbc1464cSBarry Smith - x - input vector 2515bbc1464cSBarry Smith 2516bbc1464cSBarry Smith Output Parameter: 25170b4b7b1cSBarry Smith . y - output vector 2518bbc1464cSBarry Smith 2519dc4c0fb0SBarry Smith Level: developer 2520dc4c0fb0SBarry Smith 2521bbc1464cSBarry Smith Notes: 2522420bcc1bSBarry Smith `SNESComputeMFFunction()` is used within the matrix-vector products called by the matrix created with `MatCreateSNESMF()` 2523bbc1464cSBarry Smith so users would not generally call this routine themselves. 2524bbc1464cSBarry Smith 2525dd8e379bSPierre Jolivet Since this function is intended for use with finite differencing it does not subtract the right-hand side vector provided with `SNESSolve()` 2526f6dfbefdSBarry Smith while `SNESComputeFunction()` does. As such, this routine cannot be used with `MatMFFDSetBase()` with a provided F function value even if it applies the 2527dd8e379bSPierre 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. 2528bbc1464cSBarry Smith 25290b4b7b1cSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `MatCreateSNESMF()`, `DMSNESSetMFFunction()` 2530bbc1464cSBarry Smith @*/ 2531d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeMFFunction(SNES snes, Vec x, Vec y) 2532d71ae5a4SJacob Faibussowitsch { 2533bbc1464cSBarry Smith DM dm; 2534bbc1464cSBarry Smith DMSNES sdm; 2535bbc1464cSBarry Smith 2536bbc1464cSBarry Smith PetscFunctionBegin; 2537bbc1464cSBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2538bbc1464cSBarry Smith PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2539bbc1464cSBarry Smith PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2540bbc1464cSBarry Smith PetscCheckSameComm(snes, 1, x, 2); 2541bbc1464cSBarry Smith PetscCheckSameComm(snes, 1, y, 3); 2542e0f629ddSJacob Faibussowitsch PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2543bbc1464cSBarry Smith 25449566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 25459566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 25469566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0)); 25479566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(x)); 2548bbc1464cSBarry Smith /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */ 254976c63389SBarry Smith snes->functiondomainerror = PETSC_FALSE; 2550792fecdfSBarry Smith PetscCallBack("SNES callback function", (*sdm->ops->computemffunction)(snes, x, y, sdm->mffunctionctx)); 25519566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(x)); 25529566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0)); 2553bbc1464cSBarry Smith snes->nfuncs++; 2554bbc1464cSBarry Smith /* 255576c63389SBarry Smith domainerror might not be set on all processes; so we tag vector locally with infinity and the next inner product or norm will 2556bbc1464cSBarry Smith propagate the value to all processes 2557bbc1464cSBarry Smith */ 255876c63389SBarry Smith PetscCall(VecFlag(y, snes->functiondomainerror)); 25593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2560bbc1464cSBarry Smith } 2561bbc1464cSBarry Smith 2562bbc1464cSBarry Smith /*@ 2563f6dfbefdSBarry Smith SNESComputeNGS - Calls the Gauss-Seidel function that has been set with `SNESSetNGS()`. 2564c79ef259SPeter Brune 2565c3339decSBarry Smith Collective 2566c79ef259SPeter Brune 2567c79ef259SPeter Brune Input Parameters: 2568f6dfbefdSBarry Smith + snes - the `SNES` context 2569c79ef259SPeter Brune . x - input vector 2570c79ef259SPeter Brune - b - rhs vector 2571c79ef259SPeter Brune 2572c79ef259SPeter Brune Output Parameter: 2573c79ef259SPeter Brune . x - new solution vector 2574c79ef259SPeter Brune 2575dc4c0fb0SBarry Smith Level: developer 2576dc4c0fb0SBarry Smith 2577f6dfbefdSBarry Smith Note: 2578f6dfbefdSBarry Smith `SNESComputeNGS()` is typically used within composed nonlinear solver 2579c79ef259SPeter Brune implementations, so most users would not generally call this routine 2580c79ef259SPeter Brune themselves. 2581c79ef259SPeter Brune 25828434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGSFn`, `SNESSetNGS()`, `SNESComputeFunction()`, `SNESNGS` 2583c79ef259SPeter Brune @*/ 2584d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeNGS(SNES snes, Vec b, Vec x) 2585d71ae5a4SJacob Faibussowitsch { 25866cab3a1bSJed Brown DM dm; 2587942e3340SBarry Smith DMSNES sdm; 2588646217ecSPeter Brune 2589646217ecSPeter Brune PetscFunctionBegin; 2590646217ecSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2591064a246eSJacob Faibussowitsch PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 2592064a246eSJacob Faibussowitsch if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 2593064a246eSJacob Faibussowitsch PetscCheckSameComm(snes, 1, x, 3); 2594064a246eSJacob Faibussowitsch if (b) PetscCheckSameComm(snes, 1, b, 2); 2595e0f629ddSJacob Faibussowitsch if (b) PetscCall(VecValidValues_Internal(b, 2, PETSC_TRUE)); 25969566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_NGSEval, snes, x, b, 0)); 25979566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 25989566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 25990fdf79fbSJacob Faibussowitsch PetscCheck(sdm->ops->computegs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetNGS() before SNESComputeNGS(), likely called from SNESSolve()."); 26009566063dSJacob Faibussowitsch if (b) PetscCall(VecLockReadPush(b)); 2601792fecdfSBarry Smith PetscCallBack("SNES callback NGS", (*sdm->ops->computegs)(snes, x, b, sdm->gsctx)); 26029566063dSJacob Faibussowitsch if (b) PetscCall(VecLockReadPop(b)); 26039566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_NGSEval, snes, x, b, 0)); 26043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2605646217ecSPeter Brune } 2606646217ecSPeter Brune 2607494a190aSStefano Zampini static PetscErrorCode SNESComputeFunction_FD(SNES snes, Vec Xin, Vec G) 2608494a190aSStefano Zampini { 2609494a190aSStefano Zampini Vec X; 2610494a190aSStefano Zampini PetscScalar *g; 2611494a190aSStefano Zampini PetscReal f, f2; 2612494a190aSStefano Zampini PetscInt low, high, N, i; 2613494a190aSStefano Zampini PetscBool flg; 2614494a190aSStefano Zampini PetscReal h = .5 * PETSC_SQRT_MACHINE_EPSILON; 2615494a190aSStefano Zampini 2616494a190aSStefano Zampini PetscFunctionBegin; 2617494a190aSStefano Zampini PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_fd_delta", &h, &flg)); 2618494a190aSStefano Zampini PetscCall(VecDuplicate(Xin, &X)); 2619494a190aSStefano Zampini PetscCall(VecCopy(Xin, X)); 2620494a190aSStefano Zampini PetscCall(VecGetSize(X, &N)); 2621494a190aSStefano Zampini PetscCall(VecGetOwnershipRange(X, &low, &high)); 2622494a190aSStefano Zampini PetscCall(VecSetOption(X, VEC_IGNORE_OFF_PROC_ENTRIES, PETSC_TRUE)); 2623494a190aSStefano Zampini PetscCall(VecGetArray(G, &g)); 2624494a190aSStefano Zampini for (i = 0; i < N; i++) { 2625494a190aSStefano Zampini PetscCall(VecSetValue(X, i, -h, ADD_VALUES)); 2626494a190aSStefano Zampini PetscCall(VecAssemblyBegin(X)); 2627494a190aSStefano Zampini PetscCall(VecAssemblyEnd(X)); 2628494a190aSStefano Zampini PetscCall(SNESComputeObjective(snes, X, &f)); 2629494a190aSStefano Zampini PetscCall(VecSetValue(X, i, 2.0 * h, ADD_VALUES)); 2630494a190aSStefano Zampini PetscCall(VecAssemblyBegin(X)); 2631494a190aSStefano Zampini PetscCall(VecAssemblyEnd(X)); 2632494a190aSStefano Zampini PetscCall(SNESComputeObjective(snes, X, &f2)); 2633494a190aSStefano Zampini PetscCall(VecSetValue(X, i, -h, ADD_VALUES)); 2634494a190aSStefano Zampini PetscCall(VecAssemblyBegin(X)); 2635494a190aSStefano Zampini PetscCall(VecAssemblyEnd(X)); 2636494a190aSStefano Zampini if (i >= low && i < high) g[i - low] = (f2 - f) / (2.0 * h); 2637494a190aSStefano Zampini } 2638494a190aSStefano Zampini PetscCall(VecRestoreArray(G, &g)); 2639494a190aSStefano Zampini PetscCall(VecDestroy(&X)); 2640494a190aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2641494a190aSStefano Zampini } 2642494a190aSStefano Zampini 26431dfd7622SMatthew Knepley /*@ 26441dfd7622SMatthew Knepley SNESTestFunction - Computes the difference between the computed and finite-difference functions 26451dfd7622SMatthew Knepley 26461dfd7622SMatthew Knepley Collective 26471dfd7622SMatthew Knepley 2648d5bfe6baSJose E. Roman Input Parameter: 26491dfd7622SMatthew Knepley . snes - the `SNES` context 26501dfd7622SMatthew Knepley 26511dfd7622SMatthew Knepley Options Database Keys: 26521dfd7622SMatthew Knepley + -snes_test_function - compare the user provided function with one compute via finite differences to check for errors. 26531dfd7622SMatthew Knepley - -snes_test_function_view - display the user provided function, the finite difference function and the difference 26541dfd7622SMatthew Knepley 26551dfd7622SMatthew Knepley Level: developer 26561dfd7622SMatthew Knepley 26571dfd7622SMatthew Knepley .seealso: [](ch_snes), `SNESTestJacobian()`, `SNESSetFunction()`, `SNESComputeFunction()` 26581dfd7622SMatthew Knepley @*/ 2659494a190aSStefano Zampini PetscErrorCode SNESTestFunction(SNES snes) 2660494a190aSStefano Zampini { 2661494a190aSStefano Zampini Vec x, g1, g2, g3; 26621dfd7622SMatthew Knepley PetscBool complete_print = PETSC_FALSE; 2663494a190aSStefano Zampini PetscReal hcnorm, fdnorm, hcmax, fdmax, diffmax, diffnorm; 2664494a190aSStefano Zampini PetscScalar dot; 2665494a190aSStefano Zampini MPI_Comm comm; 2666494a190aSStefano Zampini PetscViewer viewer, mviewer; 2667494a190aSStefano Zampini PetscViewerFormat format; 2668494a190aSStefano Zampini PetscInt tabs; 2669494a190aSStefano Zampini static PetscBool directionsprinted = PETSC_FALSE; 26708434afd1SBarry Smith SNESObjectiveFn *objective; 2671494a190aSStefano Zampini 2672494a190aSStefano Zampini PetscFunctionBegin; 2673494a190aSStefano Zampini PetscCall(SNESGetObjective(snes, &objective, NULL)); 2674494a190aSStefano Zampini if (!objective) PetscFunctionReturn(PETSC_SUCCESS); 2675494a190aSStefano Zampini 2676494a190aSStefano Zampini PetscObjectOptionsBegin((PetscObject)snes); 2677494a190aSStefano Zampini PetscCall(PetscOptionsViewer("-snes_test_function_view", "View difference between hand-coded and finite difference function element entries", "None", &mviewer, &format, &complete_print)); 2678494a190aSStefano Zampini PetscOptionsEnd(); 2679494a190aSStefano Zampini 2680494a190aSStefano Zampini PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 2681494a190aSStefano Zampini PetscCall(PetscViewerASCIIGetStdout(comm, &viewer)); 2682494a190aSStefano Zampini PetscCall(PetscViewerASCIIGetTab(viewer, &tabs)); 2683494a190aSStefano Zampini PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel)); 2684494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Function -------------\n")); 2685494a190aSStefano Zampini if (!complete_print && !directionsprinted) { 2686494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Run with -snes_test_function_view and optionally -snes_test_function <threshold> to show difference\n")); 2687494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " of hand-coded and finite difference function entries greater than <threshold>.\n")); 2688494a190aSStefano Zampini } 2689494a190aSStefano Zampini if (!directionsprinted) { 2690494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Testing hand-coded Function, if (for double precision runs) ||F - Ffd||/||F|| is\n")); 2691494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " O(1.e-8), the hand-coded Function is probably correct.\n")); 2692494a190aSStefano Zampini directionsprinted = PETSC_TRUE; 2693494a190aSStefano Zampini } 2694494a190aSStefano Zampini if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format)); 2695494a190aSStefano Zampini 2696494a190aSStefano Zampini PetscCall(SNESGetSolution(snes, &x)); 2697494a190aSStefano Zampini PetscCall(VecDuplicate(x, &g1)); 2698494a190aSStefano Zampini PetscCall(VecDuplicate(x, &g2)); 2699494a190aSStefano Zampini PetscCall(VecDuplicate(x, &g3)); 270076c63389SBarry Smith PetscCall(SNESComputeFunction(snes, x, g1)); /* does not handle use of SNESSetFunctionDomainError() corrrectly */ 2701494a190aSStefano Zampini PetscCall(SNESComputeFunction_FD(snes, x, g2)); 2702494a190aSStefano Zampini 2703494a190aSStefano Zampini PetscCall(VecNorm(g2, NORM_2, &fdnorm)); 2704494a190aSStefano Zampini PetscCall(VecNorm(g1, NORM_2, &hcnorm)); 2705494a190aSStefano Zampini PetscCall(VecNorm(g2, NORM_INFINITY, &fdmax)); 2706494a190aSStefano Zampini PetscCall(VecNorm(g1, NORM_INFINITY, &hcmax)); 2707494a190aSStefano Zampini PetscCall(VecDot(g1, g2, &dot)); 2708494a190aSStefano Zampini PetscCall(VecCopy(g1, g3)); 2709494a190aSStefano Zampini PetscCall(VecAXPY(g3, -1.0, g2)); 2710494a190aSStefano Zampini PetscCall(VecNorm(g3, NORM_2, &diffnorm)); 2711494a190aSStefano Zampini PetscCall(VecNorm(g3, NORM_INFINITY, &diffmax)); 2712494a190aSStefano 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)))); 2713494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " 2-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffnorm / PetscMax(hcnorm, fdnorm)), (double)diffnorm)); 2714494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " max-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffmax / PetscMax(hcmax, fdmax)), (double)diffmax)); 2715494a190aSStefano Zampini 2716494a190aSStefano Zampini if (complete_print) { 2717494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded function ----------\n")); 2718494a190aSStefano Zampini PetscCall(VecView(g1, mviewer)); 2719494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Finite difference function ----------\n")); 2720494a190aSStefano Zampini PetscCall(VecView(g2, mviewer)); 2721494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded minus finite-difference function ----------\n")); 2722494a190aSStefano Zampini PetscCall(VecView(g3, mviewer)); 2723494a190aSStefano Zampini } 2724494a190aSStefano Zampini PetscCall(VecDestroy(&g1)); 2725494a190aSStefano Zampini PetscCall(VecDestroy(&g2)); 2726494a190aSStefano Zampini PetscCall(VecDestroy(&g3)); 2727494a190aSStefano Zampini 2728494a190aSStefano Zampini if (complete_print) { 2729494a190aSStefano Zampini PetscCall(PetscViewerPopFormat(mviewer)); 2730494a190aSStefano Zampini PetscCall(PetscViewerDestroy(&mviewer)); 2731494a190aSStefano Zampini } 2732494a190aSStefano Zampini PetscCall(PetscViewerASCIISetTab(viewer, tabs)); 2733494a190aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2734494a190aSStefano Zampini } 2735494a190aSStefano Zampini 2736cbf8f02cSMatthew G. Knepley /*@ 2737cbf8f02cSMatthew G. Knepley SNESTestJacobian - Computes the difference between the computed and finite-difference Jacobians 2738cbf8f02cSMatthew G. Knepley 2739cbf8f02cSMatthew G. Knepley Collective 2740cbf8f02cSMatthew G. Knepley 2741d5bfe6baSJose E. Roman Input Parameter: 2742cbf8f02cSMatthew G. Knepley . snes - the `SNES` context 2743cbf8f02cSMatthew G. Knepley 2744cbf8f02cSMatthew G. Knepley Output Parameters: 27451dfd7622SMatthew Knepley + Jnorm - the Frobenius norm of the computed Jacobian, or `NULL` 27461dfd7622SMatthew Knepley - diffNorm - the Frobenius norm of the difference of the computed and finite-difference Jacobians, or `NULL` 2747cbf8f02cSMatthew G. Knepley 2748cbf8f02cSMatthew G. Knepley Options Database Keys: 2749cbf8f02cSMatthew 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. 2750cbf8f02cSMatthew G. Knepley - -snes_test_jacobian_view - display the user provided Jacobian, the finite difference Jacobian and the difference 2751cbf8f02cSMatthew G. Knepley 2752cbf8f02cSMatthew G. Knepley Level: developer 2753cbf8f02cSMatthew G. Knepley 27541dfd7622SMatthew Knepley Note: 27551dfd7622SMatthew Knepley Directions and norms are printed to stdout if `diffNorm` is `NULL`. 27561dfd7622SMatthew Knepley 27571dfd7622SMatthew Knepley .seealso: [](ch_snes), `SNESTestFunction()`, `SNESSetJacobian()`, `SNESComputeJacobian()` 2758cbf8f02cSMatthew G. Knepley @*/ 2759cbf8f02cSMatthew G. Knepley PetscErrorCode SNESTestJacobian(SNES snes, PetscReal *Jnorm, PetscReal *diffNorm) 2760d71ae5a4SJacob Faibussowitsch { 276112837594SBarry Smith Mat A, B, C, D, jacobian; 27624df93895SStefano Zampini Vec x = snes->vec_sol, f; 2763e885f1abSBarry Smith PetscReal nrm, gnorm; 276481e7118cSBarry Smith PetscReal threshold = 1.e-5; 27650e276705SLisandro Dalcin MatType mattype; 2766e885f1abSBarry Smith PetscInt m, n, M, N; 2767e885f1abSBarry Smith void *functx; 27681dfd7622SMatthew Knepley PetscBool complete_print = PETSC_FALSE, threshold_print = PETSC_FALSE, flg, istranspose; 27691dfd7622SMatthew Knepley PetscBool silent = diffNorm != PETSC_NULLPTR ? PETSC_TRUE : PETSC_FALSE; 27703325ff46SBarry Smith PetscViewer viewer, mviewer; 2771e885f1abSBarry Smith MPI_Comm comm; 2772e885f1abSBarry Smith PetscInt tabs; 277312837594SBarry Smith static PetscBool directionsprinted = PETSC_FALSE; 27743325ff46SBarry Smith PetscViewerFormat format; 2775e885f1abSBarry Smith 2776e885f1abSBarry Smith PetscFunctionBegin; 2777d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)snes); 27789566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-snes_test_jacobian", "Threshold for element difference between hand-coded and finite difference being meaningful", "None", threshold, &threshold, NULL)); 27799566063dSJacob Faibussowitsch PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display", "-snes_test_jacobian_view", "3.13", NULL)); 27804ead3382SBarry Smith PetscCall(PetscOptionsViewer("-snes_test_jacobian_view", "View difference between hand-coded and finite difference Jacobians element entries", "None", &mviewer, &format, &complete_print)); 27819566063dSJacob Faibussowitsch PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display_threshold", "-snes_test_jacobian", "3.13", "-snes_test_jacobian accepts an optional threshold (since v3.10)")); 27829566063dSJacob 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)); 2783d0609cedSBarry Smith PetscOptionsEnd(); 2784e885f1abSBarry Smith 27859566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 27869566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(comm, &viewer)); 27879566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetTab(viewer, &tabs)); 27889566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel)); 27891dfd7622SMatthew Knepley if (!silent) PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Jacobian -------------\n")); 27901dfd7622SMatthew Knepley if (!complete_print && !silent && !directionsprinted) { 27919566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Run with -snes_test_jacobian_view and optionally -snes_test_jacobian <threshold> to show difference\n")); 27929566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " of hand-coded and finite difference Jacobian entries greater than <threshold>.\n")); 279312837594SBarry Smith } 27941dfd7622SMatthew Knepley if (!directionsprinted && !silent) { 27959566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Testing hand-coded Jacobian, if (for double precision runs) ||J - Jfd||_F/||J||_F is\n")); 27969566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " O(1.e-8), the hand-coded Jacobian is probably correct.\n")); 279712837594SBarry Smith directionsprinted = PETSC_TRUE; 2798e885f1abSBarry Smith } 27991baa6e33SBarry Smith if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format)); 2800e885f1abSBarry Smith 28019566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes->jacobian, MATMFFD, &flg)); 280212837594SBarry Smith if (!flg) jacobian = snes->jacobian; 280312837594SBarry Smith else jacobian = snes->jacobian_pre; 280412837594SBarry Smith 28054df93895SStefano Zampini if (!x) PetscCall(MatCreateVecs(jacobian, &x, NULL)); 28064df93895SStefano Zampini else PetscCall(PetscObjectReference((PetscObject)x)); 28079566063dSJacob Faibussowitsch PetscCall(VecDuplicate(x, &f)); 28084df93895SStefano Zampini 2809a82339d0SMatthew G. Knepley /* evaluate the function at this point because SNESComputeJacobianDefault() assumes that the function has been evaluated and put into snes->vec_func */ 28109566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, x, f)); 28119566063dSJacob Faibussowitsch PetscCall(VecDestroy(&f)); 28129566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESKSPTRANSPOSEONLY, &istranspose)); 281312837594SBarry Smith while (jacobian) { 28142cd624f9SStefano Zampini Mat JT = NULL, Jsave = NULL; 28152cd624f9SStefano Zampini 28162cd624f9SStefano Zampini if (istranspose) { 28179566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(jacobian, &JT)); 28182cd624f9SStefano Zampini Jsave = jacobian; 28192cd624f9SStefano Zampini jacobian = JT; 28202cd624f9SStefano Zampini } 28219566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)jacobian, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, "")); 282212837594SBarry Smith if (flg) { 282312837594SBarry Smith A = jacobian; 28249566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 282512837594SBarry Smith } else { 28269566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(jacobian, MATAIJ, &A)); 282712837594SBarry Smith } 2828e885f1abSBarry Smith 28299566063dSJacob Faibussowitsch PetscCall(MatGetType(A, &mattype)); 28309566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &M, &N)); 28319566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &m, &n)); 28329566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B)); 28339566063dSJacob Faibussowitsch PetscCall(MatSetType(B, mattype)); 28349566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, m, n, M, N)); 28359566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(B, A, A)); 28369566063dSJacob Faibussowitsch PetscCall(MatSetUp(B)); 28379566063dSJacob Faibussowitsch PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 2838e885f1abSBarry Smith 28399566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, NULL, &functx)); 28409566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobianDefault(snes, x, B, B, functx)); 284112837594SBarry Smith 28429566063dSJacob Faibussowitsch PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &D)); 28439566063dSJacob Faibussowitsch PetscCall(MatAYPX(D, -1.0, A, DIFFERENT_NONZERO_PATTERN)); 28449566063dSJacob Faibussowitsch PetscCall(MatNorm(D, NORM_FROBENIUS, &nrm)); 28459566063dSJacob Faibussowitsch PetscCall(MatNorm(A, NORM_FROBENIUS, &gnorm)); 28469566063dSJacob Faibussowitsch PetscCall(MatDestroy(&D)); 284712837594SBarry Smith if (!gnorm) gnorm = 1; /* just in case */ 28481dfd7622SMatthew Knepley if (!silent) PetscCall(PetscViewerASCIIPrintf(viewer, " ||J - Jfd||_F/||J||_F = %g, ||J - Jfd||_F = %g\n", (double)(nrm / gnorm), (double)nrm)); 2849e885f1abSBarry Smith if (complete_print) { 28509566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded Jacobian ----------\n")); 28519566063dSJacob Faibussowitsch PetscCall(MatView(A, mviewer)); 28529566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Finite difference Jacobian ----------\n")); 28539566063dSJacob Faibussowitsch PetscCall(MatView(B, mviewer)); 2854e885f1abSBarry Smith } 2855e885f1abSBarry Smith 2856df10fb39SFande Kong if (threshold_print || complete_print) { 2857e885f1abSBarry Smith PetscInt Istart, Iend, *ccols, bncols, cncols, j, row; 2858e885f1abSBarry Smith PetscScalar *cvals; 2859e885f1abSBarry Smith const PetscInt *bcols; 2860e885f1abSBarry Smith const PetscScalar *bvals; 2861e885f1abSBarry Smith 28629566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C)); 28639566063dSJacob Faibussowitsch PetscCall(MatSetType(C, mattype)); 28649566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, m, n, M, N)); 28659566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(C, A, A)); 28669566063dSJacob Faibussowitsch PetscCall(MatSetUp(C)); 28679566063dSJacob Faibussowitsch PetscCall(MatSetOption(C, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 28680e276705SLisandro Dalcin 28699566063dSJacob Faibussowitsch PetscCall(MatAYPX(B, -1.0, A, DIFFERENT_NONZERO_PATTERN)); 28709566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(B, &Istart, &Iend)); 2871e885f1abSBarry Smith 2872e885f1abSBarry Smith for (row = Istart; row < Iend; row++) { 28739566063dSJacob Faibussowitsch PetscCall(MatGetRow(B, row, &bncols, &bcols, &bvals)); 28749566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(bncols, &ccols, bncols, &cvals)); 2875e885f1abSBarry Smith for (j = 0, cncols = 0; j < bncols; j++) { 287623a52b1dSBarry Smith if (PetscAbsScalar(bvals[j]) > threshold) { 2877e885f1abSBarry Smith ccols[cncols] = bcols[j]; 2878e885f1abSBarry Smith cvals[cncols] = bvals[j]; 2879e885f1abSBarry Smith cncols += 1; 2880e885f1abSBarry Smith } 2881e885f1abSBarry Smith } 288248a46eb9SPierre Jolivet if (cncols) PetscCall(MatSetValues(C, 1, &row, cncols, ccols, cvals, INSERT_VALUES)); 28839566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(B, row, &bncols, &bcols, &bvals)); 28849566063dSJacob Faibussowitsch PetscCall(PetscFree2(ccols, cvals)); 2885e885f1abSBarry Smith } 28869566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 28879566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 28889566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded minus finite-difference Jacobian with tolerance %g ----------\n", (double)threshold)); 28899566063dSJacob Faibussowitsch PetscCall(MatView(C, complete_print ? mviewer : viewer)); 28909566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C)); 2891e885f1abSBarry Smith } 28929566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A)); 28939566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 28949566063dSJacob Faibussowitsch PetscCall(MatDestroy(&JT)); 28952cd624f9SStefano Zampini if (Jsave) jacobian = Jsave; 289612837594SBarry Smith if (jacobian != snes->jacobian_pre) { 289712837594SBarry Smith jacobian = snes->jacobian_pre; 28981dfd7622SMatthew Knepley if (!silent) PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Jacobian for preconditioner -------------\n")); 28999371c9d4SSatish Balay } else jacobian = NULL; 290012837594SBarry Smith } 29019566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); 29021baa6e33SBarry Smith if (complete_print) PetscCall(PetscViewerPopFormat(mviewer)); 2903648c30bcSBarry Smith if (mviewer) PetscCall(PetscViewerDestroy(&mviewer)); 29049566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISetTab(viewer, tabs)); 2905cbf8f02cSMatthew G. Knepley 2906cbf8f02cSMatthew G. Knepley if (Jnorm) *Jnorm = gnorm; 2907cbf8f02cSMatthew G. Knepley if (diffNorm) *diffNorm = nrm; 29083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2909e885f1abSBarry Smith } 2910e885f1abSBarry Smith 291162fef451SLois Curfman McInnes /*@ 2912f6dfbefdSBarry Smith SNESComputeJacobian - Computes the Jacobian matrix that has been set with `SNESSetJacobian()`. 291362fef451SLois Curfman McInnes 2914c3339decSBarry Smith Collective 2915c7afd0dbSLois Curfman McInnes 291662fef451SLois Curfman McInnes Input Parameters: 2917f6dfbefdSBarry Smith + snes - the `SNES` context 2918e4094ef1SJacob Faibussowitsch - X - input vector 291962fef451SLois Curfman McInnes 292062fef451SLois Curfman McInnes Output Parameters: 2921c7afd0dbSLois Curfman McInnes + A - Jacobian matrix 2922420bcc1bSBarry Smith - B - optional matrix for building the preconditioner, usually the same as `A` 2923fee21e36SBarry Smith 2924e35cf81dSBarry Smith Options Database Keys: 292567b8a455SSatish Balay + -snes_lag_preconditioner <lag> - how often to rebuild preconditioner 292667b8a455SSatish Balay . -snes_lag_jacobian <lag> - how often to rebuild Jacobian 2927455a5933SJed 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. 2928455a5933SJed 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 2929693365a8SJed Brown . -snes_compare_explicit - Compare the computed Jacobian to the finite difference Jacobian and output the differences 2930693365a8SJed Brown . -snes_compare_explicit_draw - Compare the computed Jacobian to the finite difference Jacobian and draw the result 2931693365a8SJed Brown . -snes_compare_explicit_contour - Compare the computed Jacobian to the finite difference Jacobian and draw a contour plot with the result 29327addb90fSBarry Smith . -snes_compare_operator - Make the comparison options above use the operator instead of the matrix used to construct the preconditioner 293394d6a431SBarry Smith . -snes_compare_coloring - Compute the finite difference Jacobian using coloring and display norms of difference 2934a5b23f4aSJose E. Roman . -snes_compare_coloring_display - Compute the finite difference Jacobian using coloring and display verbose differences 2935c01495d3SJed Brown . -snes_compare_coloring_threshold - Display only those matrix entries that differ by more than a given threshold 2936dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_atol - Absolute tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold` 2937dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_rtol - Relative tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold` 2938a5b23f4aSJose E. Roman . -snes_compare_coloring_draw - Compute the finite difference Jacobian using coloring and draw differences 2939a5b23f4aSJose E. Roman - -snes_compare_coloring_draw_contour - Compute the finite difference Jacobian using coloring and show contours of matrices and differences 2940c01495d3SJed Brown 2941dc4c0fb0SBarry Smith Level: developer 2942dc4c0fb0SBarry Smith 2943f6dfbefdSBarry Smith Note: 294462fef451SLois Curfman McInnes Most users should not need to explicitly call this routine, as it 294562fef451SLois Curfman McInnes is used internally within the nonlinear solvers. 294662fef451SLois Curfman McInnes 2947420bcc1bSBarry Smith Developer Note: 2948dc4c0fb0SBarry 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 2949420bcc1bSBarry Smith with the `SNESType` of test that has been removed. 2950e885f1abSBarry Smith 295176c63389SBarry Smith .seealso: [](ch_snes), `SNESSetJacobian()`, `KSPSetOperators()`, `MatStructure`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`, 295276c63389SBarry Smith `SNESSetJacobianDomainError()`, `SNESCheckJacobianDomainError()`, `SNESSetCheckJacobianDomainError()` 295362fef451SLois Curfman McInnes @*/ 2954d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeJacobian(SNES snes, Vec X, Mat A, Mat B) 2955d71ae5a4SJacob Faibussowitsch { 2956ace3abfcSBarry Smith PetscBool flag; 29576cab3a1bSJed Brown DM dm; 2958942e3340SBarry Smith DMSNES sdm; 2959e0e3a89bSBarry Smith KSP ksp; 29603a40ed3dSBarry Smith 29613a40ed3dSBarry Smith PetscFunctionBegin; 29620700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 29630700a824SBarry Smith PetscValidHeaderSpecific(X, VEC_CLASSID, 2); 2964c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, X, 2); 2965e0f629ddSJacob Faibussowitsch PetscCall(VecValidValues_Internal(X, 2, PETSC_TRUE)); 29669566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 29679566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 29683232da50SPeter Brune 296901c1178eSBarry Smith /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix-free */ 2970fe3ffe1eSBarry Smith if (snes->lagjacobian == -2) { 2971fe3ffe1eSBarry Smith snes->lagjacobian = -1; 2972f5af7f23SKarl Rupp 29739566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n")); 2974fe3ffe1eSBarry Smith } else if (snes->lagjacobian == -1) { 29759566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is -1\n")); 29769566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag)); 2977ebd3b9afSBarry Smith if (flag) { 29789566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 29799566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 2980ebd3b9afSBarry Smith } 29813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 298237ec4e1aSPeter Brune } else if (snes->lagjacobian > 1 && (snes->iter + snes->jac_iter) % snes->lagjacobian) { 298363a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagjacobian, snes->iter)); 29849566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag)); 2985ebd3b9afSBarry Smith if (flag) { 29869566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 29879566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 2988ebd3b9afSBarry Smith } 29893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2990e35cf81dSBarry Smith } 2991efd4aadfSBarry Smith if (snes->npc && snes->npcside == PC_LEFT) { 29929566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 29939566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 29943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2995d728fb7dSPeter Brune } 2996e35cf81dSBarry Smith 29979566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_JacobianEval, snes, X, A, B)); 29989566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(X)); 2999800f99ffSJeremy L Thompson { 3000800f99ffSJeremy L Thompson void *ctx; 30018434afd1SBarry Smith SNESJacobianFn *J; 3002800f99ffSJeremy L Thompson PetscCall(DMSNESGetJacobian(dm, &J, &ctx)); 3003800f99ffSJeremy L Thompson PetscCallBack("SNES callback Jacobian", (*J)(snes, X, A, B, ctx)); 3004800f99ffSJeremy L Thompson } 30059566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(X)); 30069566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_JacobianEval, snes, X, A, B)); 300728d58a37SPierre Jolivet 30087addb90fSBarry Smith /* attach latest linearization point to the matrix used to construct the preconditioner */ 30099566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)B, "__SNES_latest_X", (PetscObject)X)); 3010a8054027SBarry Smith 3011e0e3a89bSBarry Smith /* the next line ensures that snes->ksp exists */ 30129566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 30133b4f5425SBarry Smith if (snes->lagpreconditioner == -2) { 30149566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Rebuilding preconditioner exactly once since lag is -2\n")); 30159566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE)); 30163b4f5425SBarry Smith snes->lagpreconditioner = -1; 30173b4f5425SBarry Smith } else if (snes->lagpreconditioner == -1) { 30189566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is -1\n")); 30199566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE)); 302037ec4e1aSPeter Brune } else if (snes->lagpreconditioner > 1 && (snes->iter + snes->pre_iter) % snes->lagpreconditioner) { 302163a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagpreconditioner, snes->iter)); 30229566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE)); 3023d1e9a80fSBarry Smith } else { 30249566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Rebuilding preconditioner\n")); 30259566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE)); 3026a8054027SBarry Smith } 3027a8054027SBarry Smith 30284df93895SStefano Zampini /* monkey business to allow testing Jacobians in multilevel solvers. 30294df93895SStefano Zampini This is needed because the SNESTestXXX interface does not accept vectors and matrices */ 30304df93895SStefano Zampini { 30314df93895SStefano Zampini Vec xsave = snes->vec_sol; 30324df93895SStefano Zampini Mat jacobiansave = snes->jacobian; 30334df93895SStefano Zampini Mat jacobian_presave = snes->jacobian_pre; 30344df93895SStefano Zampini 30354df93895SStefano Zampini snes->vec_sol = X; 30364df93895SStefano Zampini snes->jacobian = A; 30374df93895SStefano Zampini snes->jacobian_pre = B; 30381dfd7622SMatthew Knepley if (snes->testFunc) PetscCall(SNESTestFunction(snes)); 30391dfd7622SMatthew Knepley if (snes->testJac) PetscCall(SNESTestJacobian(snes, NULL, NULL)); 3040494a190aSStefano Zampini 30414df93895SStefano Zampini snes->vec_sol = xsave; 30424df93895SStefano Zampini snes->jacobian = jacobiansave; 30434df93895SStefano Zampini snes->jacobian_pre = jacobian_presave; 30444df93895SStefano Zampini } 30454df93895SStefano Zampini 3046693365a8SJed Brown { 3047693365a8SJed Brown PetscBool flag = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_operator = PETSC_FALSE; 3048648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit", NULL, NULL, &flag)); 3049648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw", NULL, NULL, &flag_draw)); 3050648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw_contour", NULL, NULL, &flag_contour)); 3051648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_operator", NULL, NULL, &flag_operator)); 3052693365a8SJed Brown if (flag || flag_draw || flag_contour) { 30530298fd71SBarry Smith Mat Bexp_mine = NULL, Bexp, FDexp; 3054693365a8SJed Brown PetscViewer vdraw, vstdout; 30556b3a5b13SJed Brown PetscBool flg; 3056693365a8SJed Brown if (flag_operator) { 30579566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(A, MATAIJ, &Bexp_mine)); 3058693365a8SJed Brown Bexp = Bexp_mine; 3059693365a8SJed Brown } else { 30607addb90fSBarry Smith /* See if the matrix used to construct the preconditioner can be viewed and added directly */ 30612b2f8cc6SPierre Jolivet PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)B, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, "")); 306294ab13aaSBarry Smith if (flg) Bexp = B; 3063693365a8SJed Brown else { 3064693365a8SJed Brown /* If the "preconditioning" matrix is itself MATSHELL or some other type without direct support */ 30659566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(B, MATAIJ, &Bexp_mine)); 3066693365a8SJed Brown Bexp = Bexp_mine; 3067693365a8SJed Brown } 3068693365a8SJed Brown } 30699566063dSJacob Faibussowitsch PetscCall(MatConvert(Bexp, MATSAME, MAT_INITIAL_MATRIX, &FDexp)); 30709566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobianDefault(snes, X, FDexp, FDexp, NULL)); 30719566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout)); 3072693365a8SJed Brown if (flag_draw || flag_contour) { 30739566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Explicit Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw)); 30749566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 30750298fd71SBarry Smith } else vdraw = NULL; 30769566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit %s\n", flag_operator ? "Jacobian" : "preconditioning Jacobian")); 30779566063dSJacob Faibussowitsch if (flag) PetscCall(MatView(Bexp, vstdout)); 30789566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(Bexp, vdraw)); 30799566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Finite difference Jacobian\n")); 30809566063dSJacob Faibussowitsch if (flag) PetscCall(MatView(FDexp, vstdout)); 30819566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(FDexp, vdraw)); 30829566063dSJacob Faibussowitsch PetscCall(MatAYPX(FDexp, -1.0, Bexp, SAME_NONZERO_PATTERN)); 30839566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian\n")); 30849566063dSJacob Faibussowitsch if (flag) PetscCall(MatView(FDexp, vstdout)); 3085693365a8SJed Brown if (vdraw) { /* Always use contour for the difference */ 30869566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 30879566063dSJacob Faibussowitsch PetscCall(MatView(FDexp, vdraw)); 30889566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(vdraw)); 3089693365a8SJed Brown } 30909566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw)); 30919566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&vdraw)); 30929566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bexp_mine)); 30939566063dSJacob Faibussowitsch PetscCall(MatDestroy(&FDexp)); 3094693365a8SJed Brown } 3095693365a8SJed Brown } 30964c30e9fbSJed Brown { 30976719d8e4SJed Brown PetscBool flag = PETSC_FALSE, flag_display = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_threshold = PETSC_FALSE; 30986719d8e4SJed Brown PetscReal threshold_atol = PETSC_SQRT_MACHINE_EPSILON, threshold_rtol = 10 * PETSC_SQRT_MACHINE_EPSILON; 3099648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring", NULL, NULL, &flag)); 3100648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_display", NULL, NULL, &flag_display)); 3101648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw", NULL, NULL, &flag_draw)); 3102648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw_contour", NULL, NULL, &flag_contour)); 3103648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold", NULL, NULL, &flag_threshold)); 310427b0f280SBarry Smith if (flag_threshold) { 31059566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_rtol", &threshold_rtol, NULL)); 31069566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_atol", &threshold_atol, NULL)); 310727b0f280SBarry Smith } 31086719d8e4SJed Brown if (flag || flag_display || flag_draw || flag_contour || flag_threshold) { 31094c30e9fbSJed Brown Mat Bfd; 31104c30e9fbSJed Brown PetscViewer vdraw, vstdout; 3111335efc43SPeter Brune MatColoring coloring; 31124c30e9fbSJed Brown ISColoring iscoloring; 31134c30e9fbSJed Brown MatFDColoring matfdcoloring; 31148434afd1SBarry Smith SNESFunctionFn *func; 31154c30e9fbSJed Brown void *funcctx; 31166719d8e4SJed Brown PetscReal norm1, norm2, normmax; 31174c30e9fbSJed Brown 31189566063dSJacob Faibussowitsch PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &Bfd)); 31199566063dSJacob Faibussowitsch PetscCall(MatColoringCreate(Bfd, &coloring)); 31209566063dSJacob Faibussowitsch PetscCall(MatColoringSetType(coloring, MATCOLORINGSL)); 31219566063dSJacob Faibussowitsch PetscCall(MatColoringSetFromOptions(coloring)); 31229566063dSJacob Faibussowitsch PetscCall(MatColoringApply(coloring, &iscoloring)); 31239566063dSJacob Faibussowitsch PetscCall(MatColoringDestroy(&coloring)); 31249566063dSJacob Faibussowitsch PetscCall(MatFDColoringCreate(Bfd, iscoloring, &matfdcoloring)); 31259566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFromOptions(matfdcoloring)); 31269566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetUp(Bfd, iscoloring, matfdcoloring)); 31279566063dSJacob Faibussowitsch PetscCall(ISColoringDestroy(&iscoloring)); 31284c30e9fbSJed Brown 31294c30e9fbSJed Brown /* This method of getting the function is currently unreliable since it doesn't work for DM local functions. */ 31309566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, &func, &funcctx)); 31312ba42892SBarry Smith PetscCall(MatFDColoringSetFunction(matfdcoloring, (MatFDColoringFn *)func, funcctx)); 31329566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)matfdcoloring, ((PetscObject)snes)->prefix)); 31339566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)matfdcoloring, "coloring_")); 31349566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFromOptions(matfdcoloring)); 31359566063dSJacob Faibussowitsch PetscCall(MatFDColoringApply(Bfd, matfdcoloring, X, snes)); 31369566063dSJacob Faibussowitsch PetscCall(MatFDColoringDestroy(&matfdcoloring)); 31374c30e9fbSJed Brown 31389566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout)); 31394c30e9fbSJed Brown if (flag_draw || flag_contour) { 31409566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Colored Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw)); 31419566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 31420298fd71SBarry Smith } else vdraw = NULL; 31439566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit preconditioning Jacobian\n")); 31449566063dSJacob Faibussowitsch if (flag_display) PetscCall(MatView(B, vstdout)); 31459566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(B, vdraw)); 31469566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Colored Finite difference Jacobian\n")); 31479566063dSJacob Faibussowitsch if (flag_display) PetscCall(MatView(Bfd, vstdout)); 31489566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(Bfd, vdraw)); 31499566063dSJacob Faibussowitsch PetscCall(MatAYPX(Bfd, -1.0, B, SAME_NONZERO_PATTERN)); 31509566063dSJacob Faibussowitsch PetscCall(MatNorm(Bfd, NORM_1, &norm1)); 31519566063dSJacob Faibussowitsch PetscCall(MatNorm(Bfd, NORM_FROBENIUS, &norm2)); 31529566063dSJacob Faibussowitsch PetscCall(MatNorm(Bfd, NORM_MAX, &normmax)); 31539566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian, norm1=%g normFrob=%g normmax=%g\n", (double)norm1, (double)norm2, (double)normmax)); 31549566063dSJacob Faibussowitsch if (flag_display) PetscCall(MatView(Bfd, vstdout)); 31554c30e9fbSJed Brown if (vdraw) { /* Always use contour for the difference */ 31569566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 31579566063dSJacob Faibussowitsch PetscCall(MatView(Bfd, vdraw)); 31589566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(vdraw)); 31594c30e9fbSJed Brown } 31609566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw)); 31616719d8e4SJed Brown 31626719d8e4SJed Brown if (flag_threshold) { 31636719d8e4SJed Brown PetscInt bs, rstart, rend, i; 31649566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(B, &bs)); 31659566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(B, &rstart, &rend)); 31666719d8e4SJed Brown for (i = rstart; i < rend; i++) { 31676719d8e4SJed Brown const PetscScalar *ba, *ca; 31686719d8e4SJed Brown const PetscInt *bj, *cj; 31696719d8e4SJed Brown PetscInt bn, cn, j, maxentrycol = -1, maxdiffcol = -1, maxrdiffcol = -1; 31706719d8e4SJed Brown PetscReal maxentry = 0, maxdiff = 0, maxrdiff = 0; 31719566063dSJacob Faibussowitsch PetscCall(MatGetRow(B, i, &bn, &bj, &ba)); 31729566063dSJacob Faibussowitsch PetscCall(MatGetRow(Bfd, i, &cn, &cj, &ca)); 31735f80ce2aSJacob Faibussowitsch PetscCheck(bn == cn, ((PetscObject)A)->comm, PETSC_ERR_PLIB, "Unexpected different nonzero pattern in -snes_compare_coloring_threshold"); 31746719d8e4SJed Brown for (j = 0; j < bn; j++) { 31756719d8e4SJed Brown PetscReal rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j])); 31766719d8e4SJed Brown if (PetscAbsScalar(ba[j]) > PetscAbs(maxentry)) { 31776719d8e4SJed Brown maxentrycol = bj[j]; 31786719d8e4SJed Brown maxentry = PetscRealPart(ba[j]); 31796719d8e4SJed Brown } 31806719d8e4SJed Brown if (PetscAbsScalar(ca[j]) > PetscAbs(maxdiff)) { 31816719d8e4SJed Brown maxdiffcol = bj[j]; 31826719d8e4SJed Brown maxdiff = PetscRealPart(ca[j]); 31836719d8e4SJed Brown } 31846719d8e4SJed Brown if (rdiff > maxrdiff) { 31856719d8e4SJed Brown maxrdiffcol = bj[j]; 31866719d8e4SJed Brown maxrdiff = rdiff; 31876719d8e4SJed Brown } 31886719d8e4SJed Brown } 31896719d8e4SJed Brown if (maxrdiff > 1) { 319063a3b9bcSJacob 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)); 31916719d8e4SJed Brown for (j = 0; j < bn; j++) { 31926719d8e4SJed Brown PetscReal rdiff; 31936719d8e4SJed Brown rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j])); 319448a46eb9SPierre Jolivet if (rdiff > 1) PetscCall(PetscViewerASCIIPrintf(vstdout, " (%" PetscInt_FMT ",%g:%g)", bj[j], (double)PetscRealPart(ba[j]), (double)PetscRealPart(ca[j]))); 31956719d8e4SJed Brown } 319663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "\n")); 31976719d8e4SJed Brown } 31989566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(B, i, &bn, &bj, &ba)); 31999566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(Bfd, i, &cn, &cj, &ca)); 32006719d8e4SJed Brown } 32016719d8e4SJed Brown } 32029566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&vdraw)); 32039566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bfd)); 32044c30e9fbSJed Brown } 32054c30e9fbSJed Brown } 32063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 32079b94acceSBarry Smith } 32089b94acceSBarry Smith 32099b94acceSBarry Smith /*@C 32109b94acceSBarry Smith SNESSetJacobian - Sets the function to compute Jacobian as well as the 3211044dda88SLois Curfman McInnes location to store the matrix. 32129b94acceSBarry Smith 3213c3339decSBarry Smith Logically Collective 3214c7afd0dbSLois Curfman McInnes 32159b94acceSBarry Smith Input Parameters: 3216f6dfbefdSBarry Smith + snes - the `SNES` context 3217e5d3d808SBarry Smith . Amat - the matrix that defines the (approximate) Jacobian 3218dc4c0fb0SBarry Smith . Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`. 32198434afd1SBarry Smith . J - Jacobian evaluation routine (if `NULL` then `SNES` retains any previously set value), see `SNESJacobianFn` for details 3220c7afd0dbSLois Curfman McInnes - ctx - [optional] user-defined context for private data for the 3221dc4c0fb0SBarry Smith Jacobian evaluation routine (may be `NULL`) (if `NULL` then `SNES` retains any previously set value) 3222dc4c0fb0SBarry Smith 3223dc4c0fb0SBarry Smith Level: beginner 32249b94acceSBarry Smith 32259b94acceSBarry Smith Notes: 3226dc4c0fb0SBarry Smith If the `Amat` matrix and `Pmat` matrix are different you must call `MatAssemblyBegin()`/`MatAssemblyEnd()` on 322716913363SBarry Smith each matrix. 322816913363SBarry Smith 3229dc4c0fb0SBarry Smith If you know the operator `Amat` has a null space you can use `MatSetNullSpace()` and `MatSetTransposeNullSpace()` to supply the null 3230dc4c0fb0SBarry Smith space to `Amat` and the `KSP` solvers will automatically use that null space as needed during the solution process. 3231895c21f2SBarry Smith 3232dc4c0fb0SBarry Smith If using `SNESComputeJacobianDefaultColor()` to assemble a Jacobian, the `ctx` argument 3233f6dfbefdSBarry Smith must be a `MatFDColoring`. 3234a8a26c1eSJed Brown 3235c3cc8fd1SJed Brown Other defect-correction schemes can be used by computing a different matrix in place of the Jacobian. One common 3236f6dfbefdSBarry Smith example is to use the "Picard linearization" which only differentiates through the highest order parts of each term using `SNESSetPicard()` 3237c3cc8fd1SJed Brown 32381cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSPSetOperators()`, `SNESSetFunction()`, `MatMFFDComputeJacobian()`, `SNESComputeJacobianDefaultColor()`, `MatStructure`, 32398434afd1SBarry Smith `SNESSetPicard()`, `SNESJacobianFn`, `SNESFunctionFn` 32409b94acceSBarry Smith @*/ 32412a8381b2SBarry Smith PetscErrorCode SNESSetJacobian(SNES snes, Mat Amat, Mat Pmat, SNESJacobianFn *J, PetscCtx ctx) 3242d71ae5a4SJacob Faibussowitsch { 32436cab3a1bSJed Brown DM dm; 32443a7fca6bSBarry Smith 32453a40ed3dSBarry Smith PetscFunctionBegin; 32460700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3247e5d3d808SBarry Smith if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2); 3248e5d3d808SBarry Smith if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3); 3249e5d3d808SBarry Smith if (Amat) PetscCheckSameComm(snes, 1, Amat, 2); 3250e5d3d808SBarry Smith if (Pmat) PetscCheckSameComm(snes, 1, Pmat, 3); 32519566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 32529566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, J, ctx)); 3253e5d3d808SBarry Smith if (Amat) { 32549566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)Amat)); 32559566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian)); 3256f5af7f23SKarl Rupp 3257e5d3d808SBarry Smith snes->jacobian = Amat; 32583a7fca6bSBarry Smith } 3259e5d3d808SBarry Smith if (Pmat) { 32609566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)Pmat)); 32619566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian_pre)); 3262f5af7f23SKarl Rupp 3263e5d3d808SBarry Smith snes->jacobian_pre = Pmat; 32643a7fca6bSBarry Smith } 32653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 32669b94acceSBarry Smith } 326762fef451SLois Curfman McInnes 3268c2aafc4cSSatish Balay /*@C 3269b4fd4287SBarry Smith SNESGetJacobian - Returns the Jacobian matrix and optionally the user 3270b4fd4287SBarry Smith provided context for evaluating the Jacobian. 3271b4fd4287SBarry Smith 3272420bcc1bSBarry Smith Not Collective, but `Mat` object will be parallel if `SNES` is 3273c7afd0dbSLois Curfman McInnes 3274b4fd4287SBarry Smith Input Parameter: 3275b4fd4287SBarry Smith . snes - the nonlinear solver context 3276b4fd4287SBarry Smith 3277b4fd4287SBarry Smith Output Parameters: 3278dc4c0fb0SBarry Smith + Amat - location to stash (approximate) Jacobian matrix (or `NULL`) 3279dc4c0fb0SBarry Smith . Pmat - location to stash matrix used to compute the preconditioner (or `NULL`) 32808434afd1SBarry Smith . J - location to put Jacobian function (or `NULL`), for calling sequence see `SNESJacobianFn` 3281dc4c0fb0SBarry Smith - ctx - location to stash Jacobian ctx (or `NULL`) 3282fee21e36SBarry Smith 328336851e7fSLois Curfman McInnes Level: advanced 328436851e7fSLois Curfman McInnes 32858434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `Mat`, `SNESSetJacobian()`, `SNESComputeJacobian()`, `SNESJacobianFn`, `SNESGetFunction()` 3286b4fd4287SBarry Smith @*/ 32872a8381b2SBarry Smith PetscErrorCode SNESGetJacobian(SNES snes, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, PetscCtxRt ctx) 3288d71ae5a4SJacob Faibussowitsch { 32896cab3a1bSJed Brown DM dm; 32906cab3a1bSJed Brown 32913a40ed3dSBarry Smith PetscFunctionBegin; 32920700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3293e5d3d808SBarry Smith if (Amat) *Amat = snes->jacobian; 3294e5d3d808SBarry Smith if (Pmat) *Pmat = snes->jacobian_pre; 32959566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 3296800f99ffSJeremy L Thompson PetscCall(DMSNESGetJacobian(dm, J, ctx)); 32973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3298b4fd4287SBarry Smith } 3299b4fd4287SBarry Smith 3300d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetDefaultComputeJacobian(SNES snes) 3301d71ae5a4SJacob Faibussowitsch { 330258b371f3SBarry Smith DM dm; 330358b371f3SBarry Smith DMSNES sdm; 330458b371f3SBarry Smith 330558b371f3SBarry Smith PetscFunctionBegin; 33069566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 33079566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 330858b371f3SBarry Smith if (!sdm->ops->computejacobian && snes->jacobian_pre) { 330958b371f3SBarry Smith DM dm; 331058b371f3SBarry Smith PetscBool isdense, ismf; 331158b371f3SBarry Smith 33129566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 33139566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &isdense, MATSEQDENSE, MATMPIDENSE, MATDENSE, NULL)); 33149566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &ismf, MATMFFD, MATSHELL, NULL)); 331558b371f3SBarry Smith if (isdense) { 33169566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefault, NULL)); 331758b371f3SBarry Smith } else if (!ismf) { 33189566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefaultColor, NULL)); 331958b371f3SBarry Smith } 332058b371f3SBarry Smith } 33213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 332258b371f3SBarry Smith } 332358b371f3SBarry Smith 33249b94acceSBarry Smith /*@ 33259b94acceSBarry Smith SNESSetUp - Sets up the internal data structures for the later use 33260b4b7b1cSBarry Smith of a nonlinear solver `SNESSolve()`. 33279b94acceSBarry Smith 3328c3339decSBarry Smith Collective 3329fee21e36SBarry Smith 33302fe279fdSBarry Smith Input Parameter: 3331f6dfbefdSBarry Smith . snes - the `SNES` context 3332c7afd0dbSLois Curfman McInnes 3333dc4c0fb0SBarry Smith Level: advanced 3334dc4c0fb0SBarry Smith 3335f6dfbefdSBarry Smith Note: 33360b4b7b1cSBarry Smith For basic use of the `SNES` solvers the user does not need to explicitly call 3337f6dfbefdSBarry Smith `SNESSetUp()`, since these actions will automatically occur during 3338f6dfbefdSBarry Smith the call to `SNESSolve()`. However, if one wishes to control this 3339f6dfbefdSBarry Smith phase separately, `SNESSetUp()` should be called after `SNESCreate()` 3340f6dfbefdSBarry Smith and optional routines of the form SNESSetXXX(), but before `SNESSolve()`. 3341272ac6f2SLois Curfman McInnes 33420b4b7b1cSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`, `SNESDestroy()`, `SNESSetFromOptions()` 33439b94acceSBarry Smith @*/ 3344d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUp(SNES snes) 3345d71ae5a4SJacob Faibussowitsch { 33466cab3a1bSJed Brown DM dm; 3347942e3340SBarry Smith DMSNES sdm; 3348c35f09e5SBarry Smith SNESLineSearch linesearch, pclinesearch; 33496e2a1849SPeter Brune void *lsprectx, *lspostctx; 33509b5c1c08SStefano Zampini PetscBool mf_operator, mf; 33519b5c1c08SStefano Zampini Vec f, fpc; 33529b5c1c08SStefano Zampini void *funcctx; 33539b5c1c08SStefano Zampini void *jacctx, *appctx; 33549b5c1c08SStefano Zampini Mat j, jpre; 33556b2b7091SBarry Smith PetscErrorCode (*precheck)(SNESLineSearch, Vec, Vec, PetscBool *, void *); 33566b2b7091SBarry Smith PetscErrorCode (*postcheck)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *); 33578434afd1SBarry Smith SNESFunctionFn *func; 33588434afd1SBarry Smith SNESJacobianFn *jac; 33593a40ed3dSBarry Smith 33603a40ed3dSBarry Smith PetscFunctionBegin; 33610700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 33623ba16761SJacob Faibussowitsch if (snes->setupcalled) PetscFunctionReturn(PETSC_SUCCESS); 3363fc8bc0e3SRichard Tran Mills PetscCall(PetscLogEventBegin(SNES_SetUp, snes, 0, 0, 0)); 33649b94acceSBarry Smith 336548a46eb9SPierre Jolivet if (!((PetscObject)snes)->type_name) PetscCall(SNESSetType(snes, SNESNEWTONLS)); 336685385478SLisandro Dalcin 33679566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &snes->vec_func, NULL, NULL)); 336858c9b817SLisandro Dalcin 33699566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 33709566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 33719566063dSJacob Faibussowitsch PetscCall(SNESSetDefaultComputeJacobian(snes)); 337258b371f3SBarry Smith 337348a46eb9SPierre Jolivet if (!snes->vec_func) PetscCall(DMCreateGlobalVector(dm, &snes->vec_func)); 3374efd51863SBarry Smith 337548a46eb9SPierre Jolivet if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 3376b710008aSBarry Smith 3377d8d34be6SBarry Smith if (snes->linesearch) { 33789566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 33799566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetFunction(snes->linesearch, SNESComputeFunction)); 3380d8d34be6SBarry Smith } 33819e764e56SPeter Brune 33829b5c1c08SStefano Zampini PetscCall(SNESGetUseMatrixFree(snes, &mf_operator, &mf)); 3383b552625fSStefano Zampini if (snes->npc && snes->npcside == PC_LEFT) { 3384172a4300SPeter Brune snes->mf = PETSC_TRUE; 3385172a4300SPeter Brune snes->mf_operator = PETSC_FALSE; 3386172a4300SPeter Brune } 3387d8f46077SPeter Brune 3388efd4aadfSBarry Smith if (snes->npc) { 33896e2a1849SPeter Brune /* copy the DM over */ 33909566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 33919566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes->npc, dm)); 33926e2a1849SPeter Brune 33939566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &f, &func, &funcctx)); 33949566063dSJacob Faibussowitsch PetscCall(VecDuplicate(f, &fpc)); 33959566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes->npc, fpc, func, funcctx)); 33969566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, &j, &jpre, &jac, &jacctx)); 33979566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes->npc, j, jpre, jac, jacctx)); 33989566063dSJacob Faibussowitsch PetscCall(SNESGetApplicationContext(snes, &appctx)); 33999566063dSJacob Faibussowitsch PetscCall(SNESSetApplicationContext(snes->npc, appctx)); 34009b5c1c08SStefano Zampini PetscCall(SNESSetUseMatrixFree(snes->npc, mf_operator, mf)); 34019566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fpc)); 34026e2a1849SPeter Brune 34036e2a1849SPeter Brune /* copy the function pointers over */ 34049566063dSJacob Faibussowitsch PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)snes->npc)); 34056e2a1849SPeter Brune 34066e2a1849SPeter Brune /* default to 1 iteration */ 34079566063dSJacob Faibussowitsch PetscCall(SNESSetTolerances(snes->npc, 0.0, 0.0, 0.0, 1, snes->npc->max_funcs)); 3408efd4aadfSBarry Smith if (snes->npcside == PC_RIGHT) { 34099566063dSJacob Faibussowitsch PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_FINAL_ONLY)); 3410a9936a0cSPeter Brune } else { 34119566063dSJacob Faibussowitsch PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_NONE)); 3412a9936a0cSPeter Brune } 34139566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes->npc)); 34146e2a1849SPeter Brune 34156e2a1849SPeter Brune /* copy the line search context over */ 3416d8d34be6SBarry Smith if (snes->linesearch && snes->npc->linesearch) { 34179566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &linesearch)); 34189566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes->npc, &pclinesearch)); 34199566063dSJacob Faibussowitsch PetscCall(SNESLineSearchGetPreCheck(linesearch, &precheck, &lsprectx)); 34209566063dSJacob Faibussowitsch PetscCall(SNESLineSearchGetPostCheck(linesearch, &postcheck, &lspostctx)); 34219566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetPreCheck(pclinesearch, precheck, lsprectx)); 34229566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetPostCheck(pclinesearch, postcheck, lspostctx)); 34239566063dSJacob Faibussowitsch PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch)); 34246e2a1849SPeter Brune } 3425d8d34be6SBarry Smith } 34261baa6e33SBarry Smith if (snes->mf) PetscCall(SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version)); 34272a8381b2SBarry Smith if (snes->ops->ctxcompute && !snes->ctx) PetscCallBack("SNES callback compute application context", (*snes->ops->ctxcompute)(snes, &snes->ctx)); 34286e2a1849SPeter Brune 342937ec4e1aSPeter Brune snes->jac_iter = 0; 343037ec4e1aSPeter Brune snes->pre_iter = 0; 343137ec4e1aSPeter Brune 3432dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, setup); 343358c9b817SLisandro Dalcin 34349566063dSJacob Faibussowitsch PetscCall(SNESSetDefaultComputeJacobian(snes)); 343558b371f3SBarry Smith 3436b552625fSStefano Zampini if (snes->npc && snes->npcside == PC_LEFT) { 34376c67d002SPeter Brune if (snes->functype == SNES_FUNCTION_PRECONDITIONED) { 3438d8d34be6SBarry Smith if (snes->linesearch) { 34399566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &linesearch)); 34409566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunctionDefaultNPC)); 34416c67d002SPeter Brune } 34426c67d002SPeter Brune } 3443d8d34be6SBarry Smith } 3444fc8bc0e3SRichard Tran Mills PetscCall(PetscLogEventEnd(SNES_SetUp, snes, 0, 0, 0)); 34457aaed0d8SBarry Smith snes->setupcalled = PETSC_TRUE; 34463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 34479b94acceSBarry Smith } 34489b94acceSBarry Smith 344937596af1SLisandro Dalcin /*@ 34500b4b7b1cSBarry 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 345137596af1SLisandro Dalcin 3452c3339decSBarry Smith Collective 345337596af1SLisandro Dalcin 345437596af1SLisandro Dalcin Input Parameter: 34550b4b7b1cSBarry Smith . snes - the nonlinear iterative solver context obtained from `SNESCreate()` 345637596af1SLisandro Dalcin 3457d25893d9SBarry Smith Level: intermediate 3458d25893d9SBarry Smith 345995452b02SPatrick Sanan Notes: 34600b4b7b1cSBarry Smith Any options set on the `SNES` object, including those set with `SNESSetFromOptions()` remain. 34610b4b7b1cSBarry Smith 3462f6dfbefdSBarry Smith Call this if you wish to reuse a `SNES` but with different size vectors 346337596af1SLisandro Dalcin 3464f6dfbefdSBarry Smith Also calls the application context destroy routine set with `SNESSetComputeApplicationContext()` 3465f6dfbefdSBarry Smith 34661cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESDestroy()`, `SNESCreate()`, `SNESSetUp()`, `SNESSolve()` 346737596af1SLisandro Dalcin @*/ 3468d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESReset(SNES snes) 3469d71ae5a4SJacob Faibussowitsch { 347037596af1SLisandro Dalcin PetscFunctionBegin; 347137596af1SLisandro Dalcin PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 347249abdd8aSBarry Smith if (snes->ops->ctxdestroy && snes->ctx) { 3473835f2295SStefano Zampini PetscCallBack("SNES callback destroy application context", (*snes->ops->ctxdestroy)(&snes->ctx)); 347449abdd8aSBarry Smith snes->ctx = NULL; 3475d25893d9SBarry Smith } 34761baa6e33SBarry Smith if (snes->npc) PetscCall(SNESReset(snes->npc)); 34778a23116dSBarry Smith 3478dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, reset); 34791baa6e33SBarry Smith if (snes->ksp) PetscCall(KSPReset(snes->ksp)); 34809e764e56SPeter Brune 34811baa6e33SBarry Smith if (snes->linesearch) PetscCall(SNESLineSearchReset(snes->linesearch)); 34829e764e56SPeter Brune 34839566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_rhs)); 34849566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol)); 34859566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol_update)); 34869566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_func)); 34879566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian)); 34889566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian_pre)); 34899566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->picard)); 34909566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(snes->nwork, &snes->work)); 34919566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(snes->nvwork, &snes->vwork)); 3492f5af7f23SKarl Rupp 349340fdac6aSLawrence Mitchell snes->alwayscomputesfinalresidual = PETSC_FALSE; 349440fdac6aSLawrence Mitchell 349537596af1SLisandro Dalcin snes->nwork = snes->nvwork = 0; 349637596af1SLisandro Dalcin snes->setupcalled = PETSC_FALSE; 34973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 349837596af1SLisandro Dalcin } 349937596af1SLisandro Dalcin 350052baeb72SSatish Balay /*@ 350136d43d94SBarry Smith SNESConvergedReasonViewCancel - Clears all the reason view functions for a `SNES` object provided with `SNESConvergedReasonViewSet()` also 350236d43d94SBarry Smith removes the default viewer. 3503c4421ceaSFande Kong 3504c3339decSBarry Smith Collective 3505c4421ceaSFande Kong 3506c4421ceaSFande Kong Input Parameter: 35070b4b7b1cSBarry Smith . snes - the nonlinear iterative solver context obtained from `SNESCreate()` 3508c4421ceaSFande Kong 3509c4421ceaSFande Kong Level: intermediate 3510c4421ceaSFande Kong 3511420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESReset()`, `SNESConvergedReasonViewSet()` 3512c4421ceaSFande Kong @*/ 3513d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewCancel(SNES snes) 3514d71ae5a4SJacob Faibussowitsch { 3515c4421ceaSFande Kong PetscInt i; 3516c4421ceaSFande Kong 3517c4421ceaSFande Kong PetscFunctionBegin; 3518c4421ceaSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3519c4421ceaSFande Kong for (i = 0; i < snes->numberreasonviews; i++) { 352048a46eb9SPierre Jolivet if (snes->reasonviewdestroy[i]) PetscCall((*snes->reasonviewdestroy[i])(&snes->reasonviewcontext[i])); 3521c4421ceaSFande Kong } 3522c4421ceaSFande Kong snes->numberreasonviews = 0; 3523648c30bcSBarry Smith PetscCall(PetscViewerDestroy(&snes->convergedreasonviewer)); 35243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3525c4421ceaSFande Kong } 3526c4421ceaSFande Kong 35270764c050SBarry Smith /*@ 35289b94acceSBarry Smith SNESDestroy - Destroys the nonlinear solver context that was created 3529f6dfbefdSBarry Smith with `SNESCreate()`. 35309b94acceSBarry Smith 3531c3339decSBarry Smith Collective 3532c7afd0dbSLois Curfman McInnes 35339b94acceSBarry Smith Input Parameter: 3534f6dfbefdSBarry Smith . snes - the `SNES` context 35359b94acceSBarry Smith 353636851e7fSLois Curfman McInnes Level: beginner 353736851e7fSLois Curfman McInnes 35381cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()` 35399b94acceSBarry Smith @*/ 3540d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESDestroy(SNES *snes) 3541d71ae5a4SJacob Faibussowitsch { 354292e852f7SPablo Brubeck DM dm; 354392e852f7SPablo Brubeck 35443a40ed3dSBarry Smith PetscFunctionBegin; 35453ba16761SJacob Faibussowitsch if (!*snes) PetscFunctionReturn(PETSC_SUCCESS); 3546f4f49eeaSPierre Jolivet PetscValidHeaderSpecific(*snes, SNES_CLASSID, 1); 3547f4f49eeaSPierre Jolivet if (--((PetscObject)*snes)->refct > 0) { 35489371c9d4SSatish Balay *snes = NULL; 35493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 35509371c9d4SSatish Balay } 3551d4bb536fSBarry Smith 3552f4f49eeaSPierre Jolivet PetscCall(SNESReset(*snes)); 35539566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&(*snes)->npc)); 35546b8b9a38SLisandro Dalcin 3555e04113cfSBarry Smith /* if memory was published with SAWs then destroy it */ 35569566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsViewOff((PetscObject)*snes)); 3557f4f49eeaSPierre Jolivet PetscTryTypeMethod(*snes, destroy); 35586d4c513bSLisandro Dalcin 355992e852f7SPablo Brubeck dm = (*snes)->dm; 356092e852f7SPablo Brubeck while (dm) { 356192e852f7SPablo Brubeck PetscCall(DMCoarsenHookRemove(dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, *snes)); 356292e852f7SPablo Brubeck PetscCall(DMGetCoarseDM(dm, &dm)); 356392e852f7SPablo Brubeck } 356492e852f7SPablo Brubeck 35659566063dSJacob Faibussowitsch PetscCall(DMDestroy(&(*snes)->dm)); 35669566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&(*snes)->ksp)); 35679566063dSJacob Faibussowitsch PetscCall(SNESLineSearchDestroy(&(*snes)->linesearch)); 35686b8b9a38SLisandro Dalcin 35699566063dSJacob Faibussowitsch PetscCall(PetscFree((*snes)->kspconvctx)); 357012651944SBarry Smith if ((*snes)->ops->convergeddestroy) PetscCall((*(*snes)->ops->convergeddestroy)(&(*snes)->cnvP)); 357148a46eb9SPierre Jolivet if ((*snes)->conv_hist_alloc) PetscCall(PetscFree2((*snes)->conv_hist, (*snes)->conv_hist_its)); 3572f4f49eeaSPierre Jolivet PetscCall(SNESMonitorCancel(*snes)); 3573f4f49eeaSPierre Jolivet PetscCall(SNESConvergedReasonViewCancel(*snes)); 35749566063dSJacob Faibussowitsch PetscCall(PetscHeaderDestroy(snes)); 35753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 35769b94acceSBarry Smith } 35779b94acceSBarry Smith 35789b94acceSBarry Smith /* ----------- Routines to set solver parameters ---------- */ 35799b94acceSBarry Smith 3580a8054027SBarry Smith /*@ 35810b4b7b1cSBarry Smith SNESSetLagPreconditioner - Sets when the preconditioner is rebuilt in the nonlinear solve `SNESSolve()`. 3582a8054027SBarry Smith 3583c3339decSBarry Smith Logically Collective 3584a8054027SBarry Smith 3585a8054027SBarry Smith Input Parameters: 3586f6dfbefdSBarry Smith + snes - the `SNES` context 3587d8e291bfSBarry Smith - lag - 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time 35883b4f5425SBarry Smith the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that 3589a8054027SBarry Smith 3590a8054027SBarry Smith Options Database Keys: 3591420bcc1bSBarry Smith + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple `SNESSolve()` 35923d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 3593420bcc1bSBarry Smith . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple `SNESSolve()` 35943d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 3595a8054027SBarry Smith 3596dc4c0fb0SBarry Smith Level: intermediate 3597dc4c0fb0SBarry Smith 3598420bcc1bSBarry Smith Notes: 3599a8054027SBarry Smith The default is 1 3600420bcc1bSBarry Smith 3601f6dfbefdSBarry Smith The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagPreconditionerPersists()` was called 3602d8e291bfSBarry Smith 3603f6dfbefdSBarry Smith `SNESSetLagPreconditionerPersists()` allows using the same uniform lagging (for example every second linear solve) across multiple nonlinear solves. 3604a8054027SBarry Smith 36053201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetLagPreconditionerPersists()`, 3606f6dfbefdSBarry Smith `SNESSetLagJacobianPersists()`, `SNES`, `SNESSolve()` 3607a8054027SBarry Smith @*/ 3608d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditioner(SNES snes, PetscInt lag) 3609d71ae5a4SJacob Faibussowitsch { 3610a8054027SBarry Smith PetscFunctionBegin; 36110700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 36125f80ce2aSJacob Faibussowitsch PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater"); 36135f80ce2aSJacob Faibussowitsch PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0"); 3614c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, lag, 2); 3615a8054027SBarry Smith snes->lagpreconditioner = lag; 36163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3617a8054027SBarry Smith } 3618a8054027SBarry Smith 3619efd51863SBarry Smith /*@ 3620f6dfbefdSBarry Smith SNESSetGridSequence - sets the number of steps of grid sequencing that `SNES` will do 3621efd51863SBarry Smith 3622c3339decSBarry Smith Logically Collective 3623efd51863SBarry Smith 3624efd51863SBarry Smith Input Parameters: 3625f6dfbefdSBarry Smith + snes - the `SNES` context 3626efd51863SBarry Smith - steps - the number of refinements to do, defaults to 0 3627efd51863SBarry Smith 3628f6dfbefdSBarry Smith Options Database Key: 362967b8a455SSatish Balay . -snes_grid_sequence <steps> - Use grid sequencing to generate initial guess 3630efd51863SBarry Smith 3631efd51863SBarry Smith Level: intermediate 3632efd51863SBarry Smith 36330b4b7b1cSBarry Smith Notes: 36340b4b7b1cSBarry Smith Once grid sequencing is turned on `SNESSolve()` will automatically perform the solve on each grid refinement. 36350b4b7b1cSBarry Smith 3636f6dfbefdSBarry Smith Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing. 3637c0df2a02SJed Brown 36383201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetGridSequence()`, 363954c05997SPierre Jolivet `SNESSetDM()`, `SNESSolve()` 3640efd51863SBarry Smith @*/ 3641d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetGridSequence(SNES snes, PetscInt steps) 3642d71ae5a4SJacob Faibussowitsch { 3643efd51863SBarry Smith PetscFunctionBegin; 3644efd51863SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3645efd51863SBarry Smith PetscValidLogicalCollectiveInt(snes, steps, 2); 3646efd51863SBarry Smith snes->gridsequence = steps; 36473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3648efd51863SBarry Smith } 3649efd51863SBarry Smith 3650fa19ca70SBarry Smith /*@ 3651f6dfbefdSBarry Smith SNESGetGridSequence - gets the number of steps of grid sequencing that `SNES` will do 3652fa19ca70SBarry Smith 3653c3339decSBarry Smith Logically Collective 3654fa19ca70SBarry Smith 3655fa19ca70SBarry Smith Input Parameter: 3656f6dfbefdSBarry Smith . snes - the `SNES` context 3657fa19ca70SBarry Smith 3658fa19ca70SBarry Smith Output Parameter: 3659fa19ca70SBarry Smith . steps - the number of refinements to do, defaults to 0 3660fa19ca70SBarry Smith 3661fa19ca70SBarry Smith Level: intermediate 3662fa19ca70SBarry Smith 36633201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetGridSequence()` 3664fa19ca70SBarry Smith @*/ 3665d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetGridSequence(SNES snes, PetscInt *steps) 3666d71ae5a4SJacob Faibussowitsch { 3667fa19ca70SBarry Smith PetscFunctionBegin; 3668fa19ca70SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3669fa19ca70SBarry Smith *steps = snes->gridsequence; 36703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3671fa19ca70SBarry Smith } 3672fa19ca70SBarry Smith 3673a8054027SBarry Smith /*@ 3674f6dfbefdSBarry Smith SNESGetLagPreconditioner - Return how often the preconditioner is rebuilt 3675a8054027SBarry Smith 36763f9fe445SBarry Smith Not Collective 3677a8054027SBarry Smith 3678a8054027SBarry Smith Input Parameter: 3679f6dfbefdSBarry Smith . snes - the `SNES` context 3680a8054027SBarry Smith 3681a8054027SBarry Smith Output Parameter: 3682a8054027SBarry 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 36833b4f5425SBarry Smith the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that 3684a8054027SBarry Smith 3685dc4c0fb0SBarry Smith Level: intermediate 3686dc4c0fb0SBarry Smith 3687a8054027SBarry Smith Notes: 3688a8054027SBarry Smith The default is 1 3689f6dfbefdSBarry Smith 3690a8054027SBarry Smith The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 3691a8054027SBarry Smith 36923201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3693a8054027SBarry Smith @*/ 3694d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagPreconditioner(SNES snes, PetscInt *lag) 3695d71ae5a4SJacob Faibussowitsch { 3696a8054027SBarry Smith PetscFunctionBegin; 36970700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3698a8054027SBarry Smith *lag = snes->lagpreconditioner; 36993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3700a8054027SBarry Smith } 3701a8054027SBarry Smith 3702e35cf81dSBarry Smith /*@ 3703f6dfbefdSBarry Smith SNESSetLagJacobian - Set when the Jacobian is rebuilt in the nonlinear solve. See `SNESSetLagPreconditioner()` for determining how 3704e35cf81dSBarry Smith often the preconditioner is rebuilt. 3705e35cf81dSBarry Smith 3706c3339decSBarry Smith Logically Collective 3707e35cf81dSBarry Smith 3708e35cf81dSBarry Smith Input Parameters: 3709f6dfbefdSBarry Smith + snes - the `SNES` context 3710e35cf81dSBarry 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 3711fe3ffe1eSBarry Smith the Jacobian is built etc. -2 means rebuild at next chance but then never again 3712e35cf81dSBarry Smith 3713e35cf81dSBarry Smith Options Database Keys: 371479a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 37153d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 371679a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 37173d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag. 3718e35cf81dSBarry Smith 3719dc4c0fb0SBarry Smith Level: intermediate 3720dc4c0fb0SBarry Smith 3721e35cf81dSBarry Smith Notes: 3722e35cf81dSBarry Smith The default is 1 3723f6dfbefdSBarry Smith 3724e35cf81dSBarry Smith The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 3725f6dfbefdSBarry Smith 3726fe3ffe1eSBarry 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 3727fe3ffe1eSBarry Smith at the next Newton step but never again (unless it is reset to another value) 3728e35cf81dSBarry Smith 37293201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagPreconditioner()`, `SNESGetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3730e35cf81dSBarry Smith @*/ 3731d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobian(SNES snes, PetscInt lag) 3732d71ae5a4SJacob Faibussowitsch { 3733e35cf81dSBarry Smith PetscFunctionBegin; 37340700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 37355f80ce2aSJacob Faibussowitsch PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater"); 37365f80ce2aSJacob Faibussowitsch PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0"); 3737c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, lag, 2); 3738e35cf81dSBarry Smith snes->lagjacobian = lag; 37393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3740e35cf81dSBarry Smith } 3741e35cf81dSBarry Smith 3742e35cf81dSBarry Smith /*@ 3743f6dfbefdSBarry Smith SNESGetLagJacobian - Get how often the Jacobian is rebuilt. See `SNESGetLagPreconditioner()` to determine when the preconditioner is rebuilt 3744e35cf81dSBarry Smith 37453f9fe445SBarry Smith Not Collective 3746e35cf81dSBarry Smith 3747e35cf81dSBarry Smith Input Parameter: 3748f6dfbefdSBarry Smith . snes - the `SNES` context 3749e35cf81dSBarry Smith 3750e35cf81dSBarry Smith Output Parameter: 3751e35cf81dSBarry 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 3752e35cf81dSBarry Smith the Jacobian is built etc. 3753e35cf81dSBarry Smith 3754dc4c0fb0SBarry Smith Level: intermediate 3755dc4c0fb0SBarry Smith 3756e35cf81dSBarry Smith Notes: 3757e35cf81dSBarry Smith The default is 1 3758f6dfbefdSBarry Smith 3759f6dfbefdSBarry Smith The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagJacobianPersists()` was called. 3760e35cf81dSBarry Smith 37613201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobian()`, `SNESSetLagPreconditioner()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3762e35cf81dSBarry Smith 3763e35cf81dSBarry Smith @*/ 3764d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagJacobian(SNES snes, PetscInt *lag) 3765d71ae5a4SJacob Faibussowitsch { 3766e35cf81dSBarry Smith PetscFunctionBegin; 37670700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3768e35cf81dSBarry Smith *lag = snes->lagjacobian; 37693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3770e35cf81dSBarry Smith } 3771e35cf81dSBarry Smith 377237ec4e1aSPeter Brune /*@ 3773f6dfbefdSBarry Smith SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple nonlinear solves 377437ec4e1aSPeter Brune 3775c3339decSBarry Smith Logically collective 377637ec4e1aSPeter Brune 3777d8d19677SJose E. Roman Input Parameters: 3778f6dfbefdSBarry Smith + snes - the `SNES` context 37799d7e2deaSPeter Brune - flg - jacobian lagging persists if true 378037ec4e1aSPeter Brune 378137ec4e1aSPeter Brune Options Database Keys: 378279a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 37833d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 378479a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 37853d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 37863d5a8a6aSBarry Smith 3787dc4c0fb0SBarry Smith Level: advanced 3788dc4c0fb0SBarry Smith 378995452b02SPatrick Sanan Notes: 3790420bcc1bSBarry Smith Normally when `SNESSetLagJacobian()` is used, the Jacobian is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior 3791f6dfbefdSBarry Smith 379295452b02SPatrick Sanan This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by 379337ec4e1aSPeter Brune several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several 379437ec4e1aSPeter Brune timesteps may present huge efficiency gains. 379537ec4e1aSPeter Brune 379642747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditionerPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()` 379737ec4e1aSPeter Brune @*/ 3798d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobianPersists(SNES snes, PetscBool flg) 3799d71ae5a4SJacob Faibussowitsch { 380037ec4e1aSPeter Brune PetscFunctionBegin; 380137ec4e1aSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 380237ec4e1aSPeter Brune PetscValidLogicalCollectiveBool(snes, flg, 2); 380337ec4e1aSPeter Brune snes->lagjac_persist = flg; 38043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 380537ec4e1aSPeter Brune } 380637ec4e1aSPeter Brune 380737ec4e1aSPeter Brune /*@ 3808d8e291bfSBarry Smith SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple nonlinear solves 380937ec4e1aSPeter Brune 3810c3339decSBarry Smith Logically Collective 381137ec4e1aSPeter Brune 3812d8d19677SJose E. Roman Input Parameters: 3813f6dfbefdSBarry Smith + snes - the `SNES` context 38149d7e2deaSPeter Brune - flg - preconditioner lagging persists if true 381537ec4e1aSPeter Brune 381637ec4e1aSPeter Brune Options Database Keys: 381779a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 38183d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 381979a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 38203d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 382137ec4e1aSPeter Brune 3822dc4c0fb0SBarry Smith Level: developer 3823dc4c0fb0SBarry Smith 382495452b02SPatrick Sanan Notes: 3825420bcc1bSBarry Smith Normally when `SNESSetLagPreconditioner()` is used, the preconditioner is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior 3826f6dfbefdSBarry Smith 382795452b02SPatrick Sanan This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale 382837ec4e1aSPeter Brune by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over 382937ec4e1aSPeter Brune several timesteps may present huge efficiency gains. 383037ec4e1aSPeter Brune 38311cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobianPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagPreconditioner()` 383237ec4e1aSPeter Brune @*/ 3833d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes, PetscBool flg) 3834d71ae5a4SJacob Faibussowitsch { 383537ec4e1aSPeter Brune PetscFunctionBegin; 383637ec4e1aSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 383737ec4e1aSPeter Brune PetscValidLogicalCollectiveBool(snes, flg, 2); 383837ec4e1aSPeter Brune snes->lagpre_persist = flg; 38393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 384037ec4e1aSPeter Brune } 384137ec4e1aSPeter Brune 38429b94acceSBarry Smith /*@ 3843f6dfbefdSBarry Smith SNESSetForceIteration - force `SNESSolve()` to take at least one iteration regardless of the initial residual norm 3844be5caee7SBarry Smith 3845c3339decSBarry Smith Logically Collective 3846be5caee7SBarry Smith 3847be5caee7SBarry Smith Input Parameters: 3848f6dfbefdSBarry Smith + snes - the `SNES` context 3849f6dfbefdSBarry Smith - force - `PETSC_TRUE` require at least one iteration 3850be5caee7SBarry Smith 3851f6dfbefdSBarry Smith Options Database Key: 3852be5caee7SBarry Smith . -snes_force_iteration <force> - Sets forcing an iteration 3853be5caee7SBarry Smith 3854dc4c0fb0SBarry Smith Level: intermediate 3855dc4c0fb0SBarry Smith 3856f6dfbefdSBarry Smith Note: 3857f6dfbefdSBarry Smith This is used sometimes with `TS` to prevent `TS` from detecting a false steady state solution 3858be5caee7SBarry Smith 38593201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `TS`, `SNESSetDivergenceTolerance()` 3860be5caee7SBarry Smith @*/ 3861d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetForceIteration(SNES snes, PetscBool force) 3862d71ae5a4SJacob Faibussowitsch { 3863be5caee7SBarry Smith PetscFunctionBegin; 3864be5caee7SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3865be5caee7SBarry Smith snes->forceiteration = force; 38663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3867be5caee7SBarry Smith } 3868be5caee7SBarry Smith 386985216dc7SFande Kong /*@ 3870f6dfbefdSBarry Smith SNESGetForceIteration - Check whether or not `SNESSolve()` take at least one iteration regardless of the initial residual norm 387185216dc7SFande Kong 3872c3339decSBarry Smith Logically Collective 387385216dc7SFande Kong 38742fe279fdSBarry Smith Input Parameter: 3875f6dfbefdSBarry Smith . snes - the `SNES` context 387685216dc7SFande Kong 387785216dc7SFande Kong Output Parameter: 3878dc4c0fb0SBarry Smith . force - `PETSC_TRUE` requires at least one iteration. 387985216dc7SFande Kong 388006dd6b0eSSatish Balay Level: intermediate 388106dd6b0eSSatish Balay 38823201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetForceIteration()`, `SNESSetDivergenceTolerance()` 388385216dc7SFande Kong @*/ 3884d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetForceIteration(SNES snes, PetscBool *force) 3885d71ae5a4SJacob Faibussowitsch { 388685216dc7SFande Kong PetscFunctionBegin; 388785216dc7SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 388885216dc7SFande Kong *force = snes->forceiteration; 38893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 389085216dc7SFande Kong } 3891be5caee7SBarry Smith 3892be5caee7SBarry Smith /*@ 38930b4b7b1cSBarry Smith SNESSetTolerances - Sets various parameters used in `SNES` convergence tests. 38949b94acceSBarry Smith 3895c3339decSBarry Smith Logically Collective 3896c7afd0dbSLois Curfman McInnes 38979b94acceSBarry Smith Input Parameters: 3898f6dfbefdSBarry Smith + snes - the `SNES` context 38990b4b7b1cSBarry Smith . abstol - the absolute convergence tolerance, $ F(x^n) \le abstol $ 39000b4b7b1cSBarry Smith . rtol - the relative convergence tolerance, $ F(x^n) \le reltol * F(x^0) $ 39015358d0d4SBarry Smith . stol - convergence tolerance in terms of the norm of the change in the solution between steps, || delta x || < stol*|| x || 39020b4b7b1cSBarry Smith . maxit - the maximum number of iterations allowed in the solver, default 50. 39030b4b7b1cSBarry Smith - maxf - the maximum number of function evaluations allowed in the solver (use `PETSC_UNLIMITED` indicates no limit), default 10,000 3904fee21e36SBarry Smith 390533174efeSLois Curfman McInnes Options Database Keys: 390677e5a1f9SBarry Smith + -snes_atol <abstol> - Sets `abstol` 390777e5a1f9SBarry Smith . -snes_rtol <rtol> - Sets `rtol` 390877e5a1f9SBarry Smith . -snes_stol <stol> - Sets `stol` 390977e5a1f9SBarry Smith . -snes_max_it <maxit> - Sets `maxit` 391077e5a1f9SBarry Smith - -snes_max_funcs <maxf> - Sets `maxf` (use `unlimited` to have no maximum) 39119b94acceSBarry Smith 391236851e7fSLois Curfman McInnes Level: intermediate 391336851e7fSLois Curfman McInnes 391477e5a1f9SBarry Smith Note: 391577e5a1f9SBarry Smith All parameters must be non-negative 391677e5a1f9SBarry Smith 391777e5a1f9SBarry Smith Use `PETSC_CURRENT` to retain the current value of any parameter and `PETSC_DETERMINE` to use the default value for the given `SNES`. 391877e5a1f9SBarry Smith The default value is the value in the object when its type is set. 391977e5a1f9SBarry Smith 392077e5a1f9SBarry Smith Use `PETSC_UNLIMITED` on `maxit` or `maxf` to indicate there is no bound on the number of iterations or number of function evaluations. 392177e5a1f9SBarry Smith 392277e5a1f9SBarry Smith Fortran Note: 392377e5a1f9SBarry Smith Use `PETSC_CURRENT_INTEGER`, `PETSC_CURRENT_REAL`, `PETSC_UNLIMITED_INTEGER`, `PETSC_DETERMINE_INTEGER`, or `PETSC_DETERMINE_REAL` 392477e5a1f9SBarry Smith 39253201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESSolve()`, `SNES`, `SNESSetDivergenceTolerance()`, `SNESSetForceIteration()` 39269b94acceSBarry Smith @*/ 3927d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTolerances(SNES snes, PetscReal abstol, PetscReal rtol, PetscReal stol, PetscInt maxit, PetscInt maxf) 3928d71ae5a4SJacob Faibussowitsch { 39293a40ed3dSBarry Smith PetscFunctionBegin; 39300700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3931c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, abstol, 2); 3932c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, rtol, 3); 3933c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, stol, 4); 3934c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, maxit, 5); 3935c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, maxf, 6); 3936c5eb9154SBarry Smith 393777e5a1f9SBarry Smith if (abstol == (PetscReal)PETSC_DETERMINE) { 393877e5a1f9SBarry Smith snes->abstol = snes->default_abstol; 393977e5a1f9SBarry Smith } else if (abstol != (PetscReal)PETSC_CURRENT) { 39405f80ce2aSJacob Faibussowitsch PetscCheck(abstol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)abstol); 3941ab54825eSJed Brown snes->abstol = abstol; 3942ab54825eSJed Brown } 394377e5a1f9SBarry Smith 394477e5a1f9SBarry Smith if (rtol == (PetscReal)PETSC_DETERMINE) { 394577e5a1f9SBarry Smith snes->rtol = snes->default_rtol; 394677e5a1f9SBarry Smith } else if (rtol != (PetscReal)PETSC_CURRENT) { 39475f80ce2aSJacob 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); 3948ab54825eSJed Brown snes->rtol = rtol; 3949ab54825eSJed Brown } 395077e5a1f9SBarry Smith 395177e5a1f9SBarry Smith if (stol == (PetscReal)PETSC_DETERMINE) { 395277e5a1f9SBarry Smith snes->stol = snes->default_stol; 395377e5a1f9SBarry Smith } else if (stol != (PetscReal)PETSC_CURRENT) { 39545f80ce2aSJacob Faibussowitsch PetscCheck(stol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Step tolerance %g must be non-negative", (double)stol); 3955c60f73f4SPeter Brune snes->stol = stol; 3956ab54825eSJed Brown } 395777e5a1f9SBarry Smith 3958835f2295SStefano Zampini if (maxit == PETSC_DETERMINE) { 395977e5a1f9SBarry Smith snes->max_its = snes->default_max_its; 3960835f2295SStefano Zampini } else if (maxit == PETSC_UNLIMITED) { 396177e5a1f9SBarry Smith snes->max_its = PETSC_INT_MAX; 396277e5a1f9SBarry Smith } else if (maxit != PETSC_CURRENT) { 396363a3b9bcSJacob Faibussowitsch PetscCheck(maxit >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", maxit); 3964ab54825eSJed Brown snes->max_its = maxit; 3965ab54825eSJed Brown } 396677e5a1f9SBarry Smith 3967835f2295SStefano Zampini if (maxf == PETSC_DETERMINE) { 396877e5a1f9SBarry Smith snes->max_funcs = snes->default_max_funcs; 3969835f2295SStefano Zampini } else if (maxf == PETSC_UNLIMITED || maxf == -1) { 397077e5a1f9SBarry Smith snes->max_funcs = PETSC_UNLIMITED; 397177e5a1f9SBarry Smith } else if (maxf != PETSC_CURRENT) { 397277e5a1f9SBarry Smith PetscCheck(maxf >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations %" PetscInt_FMT " must be nonnegative", maxf); 3973ab54825eSJed Brown snes->max_funcs = maxf; 3974ab54825eSJed Brown } 39753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 39769b94acceSBarry Smith } 39779b94acceSBarry Smith 3978e4d06f11SPatrick Farrell /*@ 3979f6dfbefdSBarry Smith SNESSetDivergenceTolerance - Sets the divergence tolerance used for the `SNES` divergence test. 3980e4d06f11SPatrick Farrell 3981c3339decSBarry Smith Logically Collective 3982e4d06f11SPatrick Farrell 3983e4d06f11SPatrick Farrell Input Parameters: 3984f6dfbefdSBarry Smith + snes - the `SNES` context 39850b4b7b1cSBarry 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 39860b4b7b1cSBarry Smith is stopped due to divergence. 3987e4d06f11SPatrick Farrell 3988f6dfbefdSBarry Smith Options Database Key: 3989dc4c0fb0SBarry Smith . -snes_divergence_tolerance <divtol> - Sets `divtol` 3990e4d06f11SPatrick Farrell 3991e4d06f11SPatrick Farrell Level: intermediate 3992e4d06f11SPatrick Farrell 399377e5a1f9SBarry Smith Notes: 399477e5a1f9SBarry Smith Use `PETSC_DETERMINE` to use the default value from when the object's type was set. 3995e5cd489fSStefano Zampini 399677e5a1f9SBarry Smith Fortran Note: 399777e5a1f9SBarry Smith Use ``PETSC_DETERMINE_REAL` or `PETSC_UNLIMITED_REAL` 399877e5a1f9SBarry Smith 399977e5a1f9SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetTolerances()`, `SNESGetDivergenceTolerance()` 4000e4d06f11SPatrick Farrell @*/ 4001d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDivergenceTolerance(SNES snes, PetscReal divtol) 4002d71ae5a4SJacob Faibussowitsch { 4003e4d06f11SPatrick Farrell PetscFunctionBegin; 4004e4d06f11SPatrick Farrell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4005e4d06f11SPatrick Farrell PetscValidLogicalCollectiveReal(snes, divtol, 2); 400677e5a1f9SBarry Smith 400777e5a1f9SBarry Smith if (divtol == (PetscReal)PETSC_DETERMINE) { 400877e5a1f9SBarry Smith snes->divtol = snes->default_divtol; 400977e5a1f9SBarry Smith } else if (divtol == (PetscReal)PETSC_UNLIMITED || divtol == -1) { 401077e5a1f9SBarry Smith snes->divtol = PETSC_UNLIMITED; 401177e5a1f9SBarry Smith } else if (divtol != (PetscReal)PETSC_CURRENT) { 401277e5a1f9SBarry Smith PetscCheck(divtol >= 1.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Divergence tolerance %g must be greater than 1.0", (double)divtol); 401377e5a1f9SBarry Smith snes->divtol = divtol; 401477e5a1f9SBarry Smith } 40153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4016e4d06f11SPatrick Farrell } 4017e4d06f11SPatrick Farrell 40189b94acceSBarry Smith /*@ 40190b4b7b1cSBarry Smith SNESGetTolerances - Gets various parameters used in `SNES` convergence tests. 402033174efeSLois Curfman McInnes 4021c7afd0dbSLois Curfman McInnes Not Collective 4022c7afd0dbSLois Curfman McInnes 402377e5a1f9SBarry Smith Input Parameter: 402477e5a1f9SBarry Smith . snes - the `SNES` context 402577e5a1f9SBarry Smith 402677e5a1f9SBarry Smith Output Parameters: 40270b4b7b1cSBarry Smith + atol - the absolute convergence tolerance 40280b4b7b1cSBarry Smith . rtol - the relative convergence tolerance 402977e5a1f9SBarry Smith . stol - convergence tolerance in terms of the norm of the change in the solution between steps 40300b4b7b1cSBarry Smith . maxit - the maximum number of iterations allowed 40310b4b7b1cSBarry Smith - maxf - the maximum number of function evaluations allowed, `PETSC_UNLIMITED` indicates no bound 4032fee21e36SBarry Smith 403336851e7fSLois Curfman McInnes Level: intermediate 403436851e7fSLois Curfman McInnes 40350b4b7b1cSBarry Smith Notes: 40360b4b7b1cSBarry Smith See `SNESSetTolerances()` for details on the parameters. 40370b4b7b1cSBarry Smith 4038dc4c0fb0SBarry Smith The user can specify `NULL` for any parameter that is not needed. 4039dc4c0fb0SBarry Smith 40401cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTolerances()` 404133174efeSLois Curfman McInnes @*/ 4042d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetTolerances(SNES snes, PetscReal *atol, PetscReal *rtol, PetscReal *stol, PetscInt *maxit, PetscInt *maxf) 4043d71ae5a4SJacob Faibussowitsch { 40443a40ed3dSBarry Smith PetscFunctionBegin; 40450700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 404685385478SLisandro Dalcin if (atol) *atol = snes->abstol; 404733174efeSLois Curfman McInnes if (rtol) *rtol = snes->rtol; 4048c60f73f4SPeter Brune if (stol) *stol = snes->stol; 404933174efeSLois Curfman McInnes if (maxit) *maxit = snes->max_its; 405033174efeSLois Curfman McInnes if (maxf) *maxf = snes->max_funcs; 40513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 405233174efeSLois Curfman McInnes } 405333174efeSLois Curfman McInnes 4054e4d06f11SPatrick Farrell /*@ 4055e4d06f11SPatrick Farrell SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test. 4056e4d06f11SPatrick Farrell 4057e4d06f11SPatrick Farrell Not Collective 4058e4d06f11SPatrick Farrell 4059e4d06f11SPatrick Farrell Input Parameters: 4060f6dfbefdSBarry Smith + snes - the `SNES` context 4061e4d06f11SPatrick Farrell - divtol - divergence tolerance 4062e4d06f11SPatrick Farrell 4063e4d06f11SPatrick Farrell Level: intermediate 4064e4d06f11SPatrick Farrell 40651cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetDivergenceTolerance()` 4066e4d06f11SPatrick Farrell @*/ 4067d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDivergenceTolerance(SNES snes, PetscReal *divtol) 4068d71ae5a4SJacob Faibussowitsch { 4069e4d06f11SPatrick Farrell PetscFunctionBegin; 4070e4d06f11SPatrick Farrell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4071e4d06f11SPatrick Farrell if (divtol) *divtol = snes->divtol; 40723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4073e4d06f11SPatrick Farrell } 4074e4d06f11SPatrick Farrell 40756ba87a44SLisandro Dalcin PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *); 40766ba87a44SLisandro Dalcin 4077d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorLGRange(SNES snes, PetscInt n, PetscReal rnorm, void *monctx) 4078d71ae5a4SJacob Faibussowitsch { 4079b271bb04SBarry Smith PetscDrawLG lg; 4080b271bb04SBarry Smith PetscReal x, y, per; 4081b271bb04SBarry Smith PetscViewer v = (PetscViewer)monctx; 4082b271bb04SBarry Smith static PetscReal prev; /* should be in the context */ 4083b271bb04SBarry Smith PetscDraw draw; 4084b271bb04SBarry Smith 4085459f5d12SBarry Smith PetscFunctionBegin; 40864d4332d5SBarry Smith PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 4); 40879566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 0, &lg)); 40889566063dSJacob Faibussowitsch if (!n) PetscCall(PetscDrawLGReset(lg)); 40899566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 40909566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "Residual norm")); 4091b271bb04SBarry Smith x = (PetscReal)n; 409277b4d14cSPeter Brune if (rnorm > 0.0) y = PetscLog10Real(rnorm); 409394c9c6d3SKarl Rupp else y = -15.0; 40949566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 40956934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 40969566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 40979566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 4098b271bb04SBarry Smith } 4099b271bb04SBarry Smith 41009566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 1, &lg)); 41019566063dSJacob Faibussowitsch if (!n) PetscCall(PetscDrawLGReset(lg)); 41029566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 4103aaa8cc7dSPierre Jolivet PetscCall(PetscDrawSetTitle(draw, "% elements > .2*max element")); 41049566063dSJacob Faibussowitsch PetscCall(SNESMonitorRange_Private(snes, n, &per)); 4105b271bb04SBarry Smith x = (PetscReal)n; 4106b271bb04SBarry Smith y = 100.0 * per; 41079566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 41086934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 41099566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 41109566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 4111b271bb04SBarry Smith } 4112b271bb04SBarry Smith 41139566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 2, &lg)); 41149371c9d4SSatish Balay if (!n) { 41159371c9d4SSatish Balay prev = rnorm; 41169371c9d4SSatish Balay PetscCall(PetscDrawLGReset(lg)); 41179371c9d4SSatish Balay } 41189566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 41199566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm")); 4120b271bb04SBarry Smith x = (PetscReal)n; 4121b271bb04SBarry Smith y = (prev - rnorm) / prev; 41229566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 41236934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 41249566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 41259566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 4126b271bb04SBarry Smith } 4127b271bb04SBarry Smith 41289566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 3, &lg)); 41299566063dSJacob Faibussowitsch if (!n) PetscCall(PetscDrawLGReset(lg)); 41309566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 41319566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm*(% > .2 max)")); 4132b271bb04SBarry Smith x = (PetscReal)n; 4133b271bb04SBarry Smith y = (prev - rnorm) / (prev * per); 4134b271bb04SBarry Smith if (n > 2) { /*skip initial crazy value */ 41359566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 4136b271bb04SBarry Smith } 41376934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 41389566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 41399566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 4140b271bb04SBarry Smith } 4141b271bb04SBarry Smith prev = rnorm; 41423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4143b271bb04SBarry Smith } 4144b271bb04SBarry Smith 4145228d79bcSJed Brown /*@ 41462d157150SStefano Zampini SNESConverged - Run the convergence test and update the `SNESConvergedReason`. 41472d157150SStefano Zampini 41482d157150SStefano Zampini Collective 41492d157150SStefano Zampini 41502d157150SStefano Zampini Input Parameters: 41512d157150SStefano Zampini + snes - the `SNES` context 41522d157150SStefano Zampini . it - current iteration 41532d157150SStefano Zampini . xnorm - 2-norm of current iterate 41542d157150SStefano Zampini . snorm - 2-norm of current step 41552d157150SStefano Zampini - fnorm - 2-norm of function 41562d157150SStefano Zampini 41572d157150SStefano Zampini Level: developer 41582d157150SStefano Zampini 41592d157150SStefano Zampini Note: 4160420bcc1bSBarry Smith This routine is called by the `SNESSolve()` implementations. 41612d157150SStefano Zampini It does not typically need to be called by the user. 41622d157150SStefano Zampini 4163c948abdaSPierre Jolivet .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()` 41642d157150SStefano Zampini @*/ 41652d157150SStefano Zampini PetscErrorCode SNESConverged(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm) 41662d157150SStefano Zampini { 41672d157150SStefano Zampini PetscFunctionBegin; 41682d157150SStefano Zampini if (!snes->reason) { 41692d157150SStefano Zampini if (snes->normschedule == SNES_NORM_ALWAYS) PetscUseTypeMethod(snes, converged, it, xnorm, snorm, fnorm, &snes->reason, snes->cnvP); 41702d157150SStefano Zampini if (it == snes->max_its && !snes->reason) { 41712d157150SStefano Zampini if (snes->normschedule == SNES_NORM_ALWAYS) { 41722d157150SStefano Zampini PetscCall(PetscInfo(snes, "Maximum number of iterations has been reached: %" PetscInt_FMT "\n", snes->max_its)); 41732d157150SStefano Zampini snes->reason = SNES_DIVERGED_MAX_IT; 41742d157150SStefano Zampini } else snes->reason = SNES_CONVERGED_ITS; 41752d157150SStefano Zampini } 41762d157150SStefano Zampini } 41772d157150SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 41782d157150SStefano Zampini } 41792d157150SStefano Zampini 41802d157150SStefano Zampini /*@ 41810b4b7b1cSBarry Smith SNESMonitor - runs any `SNES` monitor routines provided with `SNESMonitor()` or the options database 4182228d79bcSJed Brown 4183c3339decSBarry Smith Collective 4184228d79bcSJed Brown 4185228d79bcSJed Brown Input Parameters: 4186f6dfbefdSBarry Smith + snes - nonlinear solver context obtained from `SNESCreate()` 41870b4b7b1cSBarry Smith . iter - current iteration number 41880b4b7b1cSBarry Smith - rnorm - current relative norm of the residual 4189228d79bcSJed Brown 4190dc4c0fb0SBarry Smith Level: developer 4191dc4c0fb0SBarry Smith 4192f6dfbefdSBarry Smith Note: 4193420bcc1bSBarry Smith This routine is called by the `SNESSolve()` implementations. 4194228d79bcSJed Brown It does not typically need to be called by the user. 4195228d79bcSJed Brown 41961cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorSet()` 4197228d79bcSJed Brown @*/ 4198d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitor(SNES snes, PetscInt iter, PetscReal rnorm) 4199d71ae5a4SJacob Faibussowitsch { 42007a03ce2fSLisandro Dalcin PetscInt i, n = snes->numbermonitors; 42017a03ce2fSLisandro Dalcin 42027a03ce2fSLisandro Dalcin PetscFunctionBegin; 42039566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(snes->vec_sol)); 420448a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall((*snes->monitor[i])(snes, iter, rnorm, snes->monitorcontext[i])); 42059566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(snes->vec_sol)); 42063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 42077a03ce2fSLisandro Dalcin } 42087a03ce2fSLisandro Dalcin 42099b94acceSBarry Smith /* ------------ Routines to set performance monitoring options ----------- */ 42109b94acceSBarry Smith 4211bf388a1fSBarry Smith /*MC 4212f6dfbefdSBarry Smith SNESMonitorFunction - functional form passed to `SNESMonitorSet()` to monitor convergence of nonlinear solver 4213bf388a1fSBarry Smith 4214bf388a1fSBarry Smith Synopsis: 4215aaa7dc30SBarry Smith #include <petscsnes.h> 421637fdd005SBarry Smith PetscErrorCode SNESMonitorFunction(SNES snes, PetscInt its, PetscReal norm, void *mctx) 4217bf388a1fSBarry Smith 4218c3339decSBarry Smith Collective 42191843f636SBarry Smith 42201843f636SBarry Smith Input Parameters: 4221f6dfbefdSBarry Smith + snes - the `SNES` context 4222bf388a1fSBarry Smith . its - iteration number 4223bf388a1fSBarry Smith . norm - 2-norm function value (may be estimated) 4224bf388a1fSBarry Smith - mctx - [optional] monitoring context 4225bf388a1fSBarry Smith 4226878cb397SSatish Balay Level: advanced 4227878cb397SSatish Balay 422856296ac4SStefano Zampini .seealso: [](ch_snes), `SNESMonitorSet()` 4229bf388a1fSBarry Smith M*/ 4230bf388a1fSBarry Smith 42319b94acceSBarry Smith /*@C 4232a6570f20SBarry Smith SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every 42330b4b7b1cSBarry Smith iteration of the `SNES` nonlinear solver to display the iteration's 42349b94acceSBarry Smith progress. 42359b94acceSBarry Smith 4236c3339decSBarry Smith Logically Collective 4237fee21e36SBarry Smith 4238c7afd0dbSLois Curfman McInnes Input Parameters: 4239f6dfbefdSBarry Smith + snes - the `SNES` context 424020f4b53cSBarry Smith . f - the monitor function, for the calling sequence see `SNESMonitorFunction` 4241420bcc1bSBarry Smith . mctx - [optional] user-defined context for private data for the monitor routine (use `NULL` if no context is desired) 424249abdd8aSBarry Smith - monitordestroy - [optional] routine that frees monitor context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence 42439b94acceSBarry Smith 42449665c990SLois Curfman McInnes Options Database Keys: 4245f6dfbefdSBarry Smith + -snes_monitor - sets `SNESMonitorDefault()` 4246798534f6SMatthew G. Knepley . -snes_monitor draw::draw_lg - sets line graph monitor, 4247dc4c0fb0SBarry 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 4248c7afd0dbSLois Curfman McInnes the options database. 42499665c990SLois Curfman McInnes 4250dc4c0fb0SBarry Smith Level: intermediate 4251dc4c0fb0SBarry Smith 4252f6dfbefdSBarry Smith Note: 42536bc08f3fSLois Curfman McInnes Several different monitoring routines may be set by calling 4254f6dfbefdSBarry Smith `SNESMonitorSet()` multiple times; all will be called in the 42556bc08f3fSLois Curfman McInnes order in which they were set. 4256639f9d9dSBarry Smith 4257420bcc1bSBarry Smith Fortran Note: 4258f6dfbefdSBarry Smith Only a single monitor function can be set for each `SNES` object 4259025f1a04SBarry Smith 426049abdd8aSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESMonitorDefault()`, `SNESMonitorCancel()`, `SNESMonitorFunction`, `PetscCtxDestroyFn` 42619b94acceSBarry Smith @*/ 42622a8381b2SBarry Smith PetscErrorCode SNESMonitorSet(SNES snes, PetscErrorCode (*f)(SNES, PetscInt, PetscReal, PetscCtx), PetscCtx mctx, PetscCtxDestroyFn *monitordestroy) 4263d71ae5a4SJacob Faibussowitsch { 42643a40ed3dSBarry Smith PetscFunctionBegin; 42650700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4266453a69bbSBarry Smith for (PetscInt i = 0; i < snes->numbermonitors; i++) { 4267453a69bbSBarry Smith PetscBool identical; 4268453a69bbSBarry Smith 4269453a69bbSBarry Smith PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))(PetscVoidFn *)f, mctx, monitordestroy, (PetscErrorCode (*)(void))(PetscVoidFn *)snes->monitor[i], snes->monitorcontext[i], snes->monitordestroy[i], &identical)); 42703ba16761SJacob Faibussowitsch if (identical) PetscFunctionReturn(PETSC_SUCCESS); 4271649052a6SBarry Smith } 42725f80ce2aSJacob Faibussowitsch PetscCheck(snes->numbermonitors < MAXSNESMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set"); 42736e4dcb14SBarry Smith snes->monitor[snes->numbermonitors] = f; 4274b8a78c4aSBarry Smith snes->monitordestroy[snes->numbermonitors] = monitordestroy; 4275835f2295SStefano Zampini snes->monitorcontext[snes->numbermonitors++] = mctx; 42763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 42779b94acceSBarry Smith } 42789b94acceSBarry Smith 4279a278d85bSSatish Balay /*@ 4280f6dfbefdSBarry Smith SNESMonitorCancel - Clears all the monitor functions for a `SNES` object. 42815cd90555SBarry Smith 4282c3339decSBarry Smith Logically Collective 4283c7afd0dbSLois Curfman McInnes 42842fe279fdSBarry Smith Input Parameter: 4285f6dfbefdSBarry Smith . snes - the `SNES` context 42865cd90555SBarry Smith 42871a480d89SAdministrator Options Database Key: 4288a6570f20SBarry Smith . -snes_monitor_cancel - cancels all monitors that have been hardwired 4289dc4c0fb0SBarry Smith into a code by calls to `SNESMonitorSet()`, but does not cancel those 4290c7afd0dbSLois Curfman McInnes set via the options database 42915cd90555SBarry Smith 4292dc4c0fb0SBarry Smith Level: intermediate 4293dc4c0fb0SBarry Smith 4294f6dfbefdSBarry Smith Note: 4295f6dfbefdSBarry Smith There is no way to clear one specific monitor from a `SNES` object. 42965cd90555SBarry Smith 429756296ac4SStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESMonitorDefault()`, `SNESMonitorSet()` 42985cd90555SBarry Smith @*/ 4299d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorCancel(SNES snes) 4300d71ae5a4SJacob Faibussowitsch { 4301d952e501SBarry Smith PetscInt i; 4302d952e501SBarry Smith 43035cd90555SBarry Smith PetscFunctionBegin; 43040700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4305d952e501SBarry Smith for (i = 0; i < snes->numbermonitors; i++) { 430648a46eb9SPierre Jolivet if (snes->monitordestroy[i]) PetscCall((*snes->monitordestroy[i])(&snes->monitorcontext[i])); 4307d952e501SBarry Smith } 43085cd90555SBarry Smith snes->numbermonitors = 0; 43093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 43105cd90555SBarry Smith } 43115cd90555SBarry Smith 4312bf388a1fSBarry Smith /*MC 4313bf388a1fSBarry Smith SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver 4314bf388a1fSBarry Smith 4315bf388a1fSBarry Smith Synopsis: 4316aaa7dc30SBarry Smith #include <petscsnes.h> 431737fdd005SBarry Smith PetscErrorCode SNESConvergenceTest(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *cctx) 4318bf388a1fSBarry Smith 4319c3339decSBarry Smith Collective 43201843f636SBarry Smith 43211843f636SBarry Smith Input Parameters: 4322f6dfbefdSBarry Smith + snes - the `SNES` context 4323bf388a1fSBarry Smith . it - current iteration (0 is the first and is before any Newton step) 4324bf388a1fSBarry Smith . xnorm - 2-norm of current iterate 4325bf388a1fSBarry Smith . gnorm - 2-norm of current step 43261843f636SBarry Smith . f - 2-norm of function 43271843f636SBarry Smith - cctx - [optional] convergence context 43281843f636SBarry Smith 43291843f636SBarry Smith Output Parameter: 43301843f636SBarry Smith . reason - reason for convergence/divergence, only needs to be set when convergence or divergence is detected 4331bf388a1fSBarry Smith 4332878cb397SSatish Balay Level: intermediate 4333bf388a1fSBarry Smith 4334c948abdaSPierre Jolivet .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()` 4335bf388a1fSBarry Smith M*/ 4336bf388a1fSBarry Smith 43379b94acceSBarry Smith /*@C 43389b94acceSBarry Smith SNESSetConvergenceTest - Sets the function that is to be used 43399b94acceSBarry Smith to test for convergence of the nonlinear iterative solution. 43409b94acceSBarry Smith 4341c3339decSBarry Smith Logically Collective 4342fee21e36SBarry Smith 4343c7afd0dbSLois Curfman McInnes Input Parameters: 4344f6dfbefdSBarry Smith + snes - the `SNES` context 4345e4094ef1SJacob Faibussowitsch . SNESConvergenceTestFunction - routine to test for convergence 43462a8381b2SBarry Smith . ctx - [optional] context for private data for the convergence routine (may be `NULL`) 4347dc4c0fb0SBarry Smith - destroy - [optional] destructor for the context (may be `NULL`; `PETSC_NULL_FUNCTION` in Fortran) 43489b94acceSBarry Smith 434936851e7fSLois Curfman McInnes Level: advanced 435036851e7fSLois Curfman McInnes 43511cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedDefault()`, `SNESConvergedSkip()`, `SNESConvergenceTestFunction` 43529b94acceSBarry Smith @*/ 43532a8381b2SBarry Smith PetscErrorCode SNESSetConvergenceTest(SNES snes, PetscErrorCode (*SNESConvergenceTestFunction)(SNES, PetscInt, PetscReal, PetscReal, PetscReal, SNESConvergedReason *, void *), PetscCtx ctx, PetscCtxDestroyFn *destroy) 4354d71ae5a4SJacob Faibussowitsch { 43553a40ed3dSBarry Smith PetscFunctionBegin; 43560700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4357e2a6519dSDmitry Karpeev if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip; 435812651944SBarry Smith if (snes->ops->convergeddestroy) PetscCall((*snes->ops->convergeddestroy)(&snes->cnvP)); 4359bf388a1fSBarry Smith snes->ops->converged = SNESConvergenceTestFunction; 43607f7931b9SBarry Smith snes->ops->convergeddestroy = destroy; 43612a8381b2SBarry Smith snes->cnvP = ctx; 43623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 43639b94acceSBarry Smith } 43649b94acceSBarry Smith 436552baeb72SSatish Balay /*@ 43660b4b7b1cSBarry Smith SNESGetConvergedReason - Gets the reason the `SNES` iteration was stopped, which may be due to convergence, divergence, or stagnation 4367184914b5SBarry Smith 4368184914b5SBarry Smith Not Collective 4369184914b5SBarry Smith 4370184914b5SBarry Smith Input Parameter: 4371f6dfbefdSBarry Smith . snes - the `SNES` context 4372184914b5SBarry Smith 4373184914b5SBarry Smith Output Parameter: 4374f6dfbefdSBarry Smith . reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` for the individual convergence tests for complete lists 4375184914b5SBarry Smith 4376f6dfbefdSBarry Smith Options Database Key: 43776a4d7782SBarry Smith . -snes_converged_reason - prints the reason to standard out 43786a4d7782SBarry Smith 4379184914b5SBarry Smith Level: intermediate 4380184914b5SBarry Smith 4381f6dfbefdSBarry Smith Note: 4382f6dfbefdSBarry Smith Should only be called after the call the `SNESSolve()` is complete, if it is called earlier it returns the value `SNES__CONVERGED_ITERATING`. 4383184914b5SBarry Smith 43841cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESSetConvergedReason()`, `SNESConvergedReason`, `SNESGetConvergedReasonString()` 4385184914b5SBarry Smith @*/ 4386d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReason(SNES snes, SNESConvergedReason *reason) 4387d71ae5a4SJacob Faibussowitsch { 4388184914b5SBarry Smith PetscFunctionBegin; 43890700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 43904f572ea9SToby Isaac PetscAssertPointer(reason, 2); 4391184914b5SBarry Smith *reason = snes->reason; 43923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4393184914b5SBarry Smith } 4394184914b5SBarry Smith 4395c4421ceaSFande Kong /*@C 4396f6dfbefdSBarry Smith SNESGetConvergedReasonString - Return a human readable string for `SNESConvergedReason` 4397c4421ceaSFande Kong 4398c4421ceaSFande Kong Not Collective 4399c4421ceaSFande Kong 4400c4421ceaSFande Kong Input Parameter: 4401f6dfbefdSBarry Smith . snes - the `SNES` context 4402c4421ceaSFande Kong 4403c4421ceaSFande Kong Output Parameter: 4404dc4c0fb0SBarry Smith . strreason - a human readable string that describes `SNES` converged reason 4405c4421ceaSFande Kong 440699c90e12SSatish Balay Level: beginner 4407c4421ceaSFande Kong 44081cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetConvergedReason()` 4409c4421ceaSFande Kong @*/ 4410d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReasonString(SNES snes, const char **strreason) 4411d71ae5a4SJacob Faibussowitsch { 4412c4421ceaSFande Kong PetscFunctionBegin; 4413c4421ceaSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 44144f572ea9SToby Isaac PetscAssertPointer(strreason, 2); 4415c4421ceaSFande Kong *strreason = SNESConvergedReasons[snes->reason]; 44163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4417c4421ceaSFande Kong } 4418c4421ceaSFande Kong 441933866048SMatthew G. Knepley /*@ 4420f6dfbefdSBarry Smith SNESSetConvergedReason - Sets the reason the `SNES` iteration was stopped. 442133866048SMatthew G. Knepley 442233866048SMatthew G. Knepley Not Collective 442333866048SMatthew G. Knepley 442433866048SMatthew G. Knepley Input Parameters: 4425f6dfbefdSBarry Smith + snes - the `SNES` context 4426f6dfbefdSBarry Smith - reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` or the 442733866048SMatthew G. Knepley manual pages for the individual convergence tests for complete lists 442833866048SMatthew G. Knepley 4429f6dfbefdSBarry Smith Level: developer 4430f6dfbefdSBarry Smith 4431420bcc1bSBarry Smith Developer Note: 4432f6dfbefdSBarry Smith Called inside the various `SNESSolve()` implementations 443333866048SMatthew G. Knepley 44341cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetConvergedReason()`, `SNESSetConvergenceTest()`, `SNESConvergedReason` 443533866048SMatthew G. Knepley @*/ 4436d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergedReason(SNES snes, SNESConvergedReason reason) 4437d71ae5a4SJacob Faibussowitsch { 443833866048SMatthew G. Knepley PetscFunctionBegin; 443933866048SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 44405f3c5e7aSBarry Smith PetscCheck(!snes->errorifnotconverged || reason > 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "SNES code should have previously errored due to negative reason"); 444133866048SMatthew G. Knepley snes->reason = reason; 44423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 444333866048SMatthew G. Knepley } 444433866048SMatthew G. Knepley 4445c9005455SLois Curfman McInnes /*@ 4446420bcc1bSBarry Smith SNESSetConvergenceHistory - Sets the arrays used to hold the convergence history. 4447c9005455SLois Curfman McInnes 4448c3339decSBarry Smith Logically Collective 4449fee21e36SBarry Smith 4450c7afd0dbSLois Curfman McInnes Input Parameters: 4451f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 44528c7482ecSBarry Smith . a - array to hold history, this array will contain the function norms computed at each step 4453cd5578b5SBarry Smith . its - integer array holds the number of linear iterations for each solve. 4454420bcc1bSBarry Smith . na - size of `a` and `its` 4455f6dfbefdSBarry Smith - reset - `PETSC_TRUE` indicates each new nonlinear solve resets the history counter to zero, 4456758f92a0SBarry Smith else it continues storing new values for new nonlinear solves after the old ones 4457c7afd0dbSLois Curfman McInnes 4458dc4c0fb0SBarry Smith Level: intermediate 4459dc4c0fb0SBarry Smith 4460308dcc3eSBarry Smith Notes: 4461ce78bad3SBarry 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 446277e5a1f9SBarry Smith default array of length 1,000 is allocated. 4463308dcc3eSBarry Smith 4464c9005455SLois Curfman McInnes This routine is useful, e.g., when running a code for purposes 4465c9005455SLois Curfman McInnes of accurate performance monitoring, when no I/O should be done 4466c9005455SLois Curfman McInnes during the section of code that is being timed. 4467c9005455SLois Curfman McInnes 4468420bcc1bSBarry Smith If the arrays run out of space after a number of iterations then the later values are not saved in the history 4469420bcc1bSBarry Smith 44701cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetConvergenceHistory()` 4471c9005455SLois Curfman McInnes @*/ 4472d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceHistory(SNES snes, PetscReal a[], PetscInt its[], PetscInt na, PetscBool reset) 4473d71ae5a4SJacob Faibussowitsch { 44743a40ed3dSBarry Smith PetscFunctionBegin; 44750700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 44764f572ea9SToby Isaac if (a) PetscAssertPointer(a, 2); 44774f572ea9SToby Isaac if (its) PetscAssertPointer(its, 3); 44787a1ec6d4SBarry Smith if (!a) { 447977e5a1f9SBarry Smith if (na == PETSC_DECIDE) na = 1000; 44809566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(na, &a, na, &its)); 4481071fcb05SBarry Smith snes->conv_hist_alloc = PETSC_TRUE; 4482308dcc3eSBarry Smith } 4483c9005455SLois Curfman McInnes snes->conv_hist = a; 4484758f92a0SBarry Smith snes->conv_hist_its = its; 4485115dd874SBarry Smith snes->conv_hist_max = (size_t)na; 4486a12bc48fSLisandro Dalcin snes->conv_hist_len = 0; 4487758f92a0SBarry Smith snes->conv_hist_reset = reset; 44883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4489758f92a0SBarry Smith } 4490758f92a0SBarry Smith 4491d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB) 4492c6db04a5SJed Brown #include <engine.h> /* MATLAB include file */ 4493c6db04a5SJed Brown #include <mex.h> /* MATLAB include file */ 449499e0435eSBarry Smith 4495d71ae5a4SJacob Faibussowitsch PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes) 4496d71ae5a4SJacob Faibussowitsch { 4497308dcc3eSBarry Smith mxArray *mat; 4498308dcc3eSBarry Smith PetscInt i; 4499308dcc3eSBarry Smith PetscReal *ar; 4500308dcc3eSBarry Smith 4501308dcc3eSBarry Smith mat = mxCreateDoubleMatrix(snes->conv_hist_len, 1, mxREAL); 4502308dcc3eSBarry Smith ar = (PetscReal *)mxGetData(mat); 4503f5af7f23SKarl Rupp for (i = 0; i < snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i]; 450411cc89d2SBarry Smith return mat; 4505308dcc3eSBarry Smith } 4506308dcc3eSBarry Smith #endif 4507308dcc3eSBarry Smith 45080c4c9dddSBarry Smith /*@C 4509420bcc1bSBarry Smith SNESGetConvergenceHistory - Gets the arrays used to hold the convergence history. 4510758f92a0SBarry Smith 45113f9fe445SBarry Smith Not Collective 4512758f92a0SBarry Smith 4513758f92a0SBarry Smith Input Parameter: 4514f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 4515758f92a0SBarry Smith 4516758f92a0SBarry Smith Output Parameters: 4517f6dfbefdSBarry Smith + a - array to hold history, usually was set with `SNESSetConvergenceHistory()` 4518758f92a0SBarry Smith . its - integer array holds the number of linear iterations (or 4519758f92a0SBarry Smith negative if not converged) for each solve. 452020f4b53cSBarry Smith - na - size of `a` and `its` 4521758f92a0SBarry Smith 4522dc4c0fb0SBarry Smith Level: intermediate 4523dc4c0fb0SBarry Smith 452420f4b53cSBarry Smith Note: 452520f4b53cSBarry Smith This routine is useful, e.g., when running a code for purposes 452620f4b53cSBarry Smith of accurate performance monitoring, when no I/O should be done 452720f4b53cSBarry Smith during the section of code that is being timed. 452820f4b53cSBarry Smith 4529ce78bad3SBarry Smith Fortran Notes: 4530ce78bad3SBarry Smith Return the arrays with ``SNESRestoreConvergenceHistory()` 4531ce78bad3SBarry Smith 4532ce78bad3SBarry Smith Use the arguments 4533dc4c0fb0SBarry Smith .vb 4534ce78bad3SBarry Smith PetscReal, pointer :: a(:) 4535ce78bad3SBarry Smith PetscInt, pointer :: its(:) 4536dc4c0fb0SBarry Smith .ve 4537758f92a0SBarry Smith 45381cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceHistory()` 4539758f92a0SBarry Smith @*/ 4540d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergenceHistory(SNES snes, PetscReal *a[], PetscInt *its[], PetscInt *na) 4541d71ae5a4SJacob Faibussowitsch { 4542758f92a0SBarry Smith PetscFunctionBegin; 45430700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4544758f92a0SBarry Smith if (a) *a = snes->conv_hist; 4545758f92a0SBarry Smith if (its) *its = snes->conv_hist_its; 4546115dd874SBarry Smith if (na) *na = (PetscInt)snes->conv_hist_len; 45473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4548c9005455SLois Curfman McInnes } 4549c9005455SLois Curfman McInnes 4550ac226902SBarry Smith /*@C 455176b2cf59SMatthew Knepley SNESSetUpdate - Sets the general-purpose update function called 4552eec8f646SJed Brown at the beginning of every iteration of the nonlinear solve. Specifically 455353e5d35bSStefano Zampini it is called just before the Jacobian is "evaluated" and after the function 455453e5d35bSStefano Zampini evaluation. 455576b2cf59SMatthew Knepley 4556c3339decSBarry Smith Logically Collective 455776b2cf59SMatthew Knepley 455876b2cf59SMatthew Knepley Input Parameters: 4559a2b725a8SWilliam Gropp + snes - The nonlinear solver context 456053e5d35bSStefano Zampini - func - The update function; for calling sequence see `SNESUpdateFn` 456176b2cf59SMatthew Knepley 4562fe97e370SBarry Smith Level: advanced 4563fe97e370SBarry Smith 4564420bcc1bSBarry Smith Notes: 4565f6dfbefdSBarry 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 4566f6dfbefdSBarry Smith to `SNESSetFunction()`, or `SNESSetPicard()` 456753e5d35bSStefano Zampini This is not used by most users, and it is intended to provide a general hook that is run 456853e5d35bSStefano Zampini right before the direction step is computed. 4569ce78bad3SBarry Smith 457053e5d35bSStefano Zampini Users are free to modify the current residual vector, 457153e5d35bSStefano Zampini the current linearization point, or any other vector associated to the specific solver used. 457253e5d35bSStefano Zampini If such modifications take place, it is the user responsibility to update all the relevant 4573ce78bad3SBarry Smith vectors. For example, if one is adjusting the model parameters at each Newton step their code may look like 4574ce78bad3SBarry Smith .vb 4575ce78bad3SBarry Smith PetscErrorCode update(SNES snes, PetscInt iteration) 4576ce78bad3SBarry Smith { 4577ce78bad3SBarry Smith PetscFunctionBeginUser; 4578ce78bad3SBarry Smith if (iteration > 0) { 4579ce78bad3SBarry Smith // update the model parameters here 4580ce78bad3SBarry Smith Vec x,f; 4581ce78bad3SBarry Smith PetscCall(SNESGetSolution(snes,&x)); 4582ce78bad3SBarry Smith PetcCall(SNESGetFunction(snes,&f,NULL,NULL)); 4583ce78bad3SBarry Smith PetscCall(SNESComputeFunction(snes,x,f)); 4584ce78bad3SBarry Smith } 4585ce78bad3SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 4586ce78bad3SBarry Smith } 4587ce78bad3SBarry Smith .ve 458876b2cf59SMatthew Knepley 4589aaa8cc7dSPierre 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. 45906b7fb656SBarry Smith 4591e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetJacobian()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRSetPostCheck()`, 459253e5d35bSStefano Zampini `SNESMonitorSet()` 459376b2cf59SMatthew Knepley @*/ 459453e5d35bSStefano Zampini PetscErrorCode SNESSetUpdate(SNES snes, SNESUpdateFn *func) 4595d71ae5a4SJacob Faibussowitsch { 459676b2cf59SMatthew Knepley PetscFunctionBegin; 45970700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4598e7788613SBarry Smith snes->ops->update = func; 45993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 460076b2cf59SMatthew Knepley } 460176b2cf59SMatthew Knepley 4602ffeef943SBarry Smith /*@ 4603f6dfbefdSBarry Smith SNESConvergedReasonView - Displays the reason a `SNES` solve converged or diverged to a viewer 46042a359c20SBarry Smith 4605c3339decSBarry Smith Collective 46062a359c20SBarry Smith 4607e4094ef1SJacob Faibussowitsch Input Parameters: 4608f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 46092a359c20SBarry Smith - viewer - the viewer to display the reason 46102a359c20SBarry Smith 46112a359c20SBarry Smith Options Database Keys: 4612ee300463SSatish Balay + -snes_converged_reason - print reason for converged or diverged, also prints number of iterations 4613ee300463SSatish Balay - -snes_converged_reason ::failed - only print reason and number of iterations when diverged 4614eafd5ff0SAlex Lindsay 4615420bcc1bSBarry Smith Level: beginner 4616420bcc1bSBarry Smith 4617f6dfbefdSBarry Smith Note: 4618f6dfbefdSBarry Smith To change the format of the output call `PetscViewerPushFormat`(viewer,format) before this call. Use `PETSC_VIEWER_DEFAULT` for the default, 4619f6dfbefdSBarry Smith use `PETSC_VIEWER_FAILED` to only display a reason if it fails. 46202a359c20SBarry Smith 46211cc06b55SBarry Smith .seealso: [](ch_snes), `SNESConvergedReason`, `PetscViewer`, `SNES`, 4622f6dfbefdSBarry Smith `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, 4623f6dfbefdSBarry Smith `SNESConvergedReasonViewFromOptions()`, 4624db781477SPatrick Sanan `PetscViewerPushFormat()`, `PetscViewerPopFormat()` 46252a359c20SBarry Smith @*/ 4626d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonView(SNES snes, PetscViewer viewer) 4627d71ae5a4SJacob Faibussowitsch { 462875cca76cSMatthew G. Knepley PetscViewerFormat format; 46292a359c20SBarry Smith PetscBool isAscii; 46302a359c20SBarry Smith 46312a359c20SBarry Smith PetscFunctionBegin; 463219a666eeSBarry Smith if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)); 46339566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii)); 46342a359c20SBarry Smith if (isAscii) { 46359566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 463665bf60d2SBarry Smith PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel + 1)); 463775cca76cSMatthew G. Knepley if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 463875cca76cSMatthew G. Knepley DM dm; 463975cca76cSMatthew G. Knepley Vec u; 464075cca76cSMatthew G. Knepley PetscDS prob; 464175cca76cSMatthew G. Knepley PetscInt Nf, f; 464295cbbfd3SMatthew G. Knepley PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *); 464395cbbfd3SMatthew G. Knepley void **exactCtx; 464475cca76cSMatthew G. Knepley PetscReal error; 464575cca76cSMatthew G. Knepley 46469566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 46479566063dSJacob Faibussowitsch PetscCall(SNESGetSolution(snes, &u)); 46489566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob)); 46499566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(prob, &Nf)); 46509566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(Nf, &exactSol, Nf, &exactCtx)); 46519566063dSJacob Faibussowitsch for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f])); 46529566063dSJacob Faibussowitsch PetscCall(DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error)); 46539566063dSJacob Faibussowitsch PetscCall(PetscFree2(exactSol, exactCtx)); 46549566063dSJacob Faibussowitsch if (error < 1.0e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n")); 465563a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", (double)error)); 465675cca76cSMatthew G. Knepley } 4657eafd5ff0SAlex Lindsay if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) { 46582a359c20SBarry Smith if (((PetscObject)snes)->prefix) { 465963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter)); 46602a359c20SBarry Smith } else { 466163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve converged due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter)); 46622a359c20SBarry Smith } 4663eafd5ff0SAlex Lindsay } else if (snes->reason <= 0) { 46642a359c20SBarry Smith if (((PetscObject)snes)->prefix) { 466563a3b9bcSJacob 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)); 46662a359c20SBarry Smith } else { 466763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve did not converge due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter)); 46682a359c20SBarry Smith } 46692a359c20SBarry Smith } 467065bf60d2SBarry Smith PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel + 1)); 46712a359c20SBarry Smith } 46723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 46732a359c20SBarry Smith } 46742a359c20SBarry Smith 4675c4421ceaSFande Kong /*@C 4676c4421ceaSFande Kong SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the 4677aaa8cc7dSPierre Jolivet end of the nonlinear solver to display the convergence reason of the nonlinear solver. 4678c4421ceaSFande Kong 4679c3339decSBarry Smith Logically Collective 4680c4421ceaSFande Kong 4681c4421ceaSFande Kong Input Parameters: 4682f6dfbefdSBarry Smith + snes - the `SNES` context 4683420bcc1bSBarry Smith . f - the `SNESConvergedReason` view function 4684420bcc1bSBarry Smith . vctx - [optional] user-defined context for private data for the `SNESConvergedReason` view function (use `NULL` if no context is desired) 468549abdd8aSBarry Smith - reasonviewdestroy - [optional] routine that frees the context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence 4686420bcc1bSBarry Smith 4687420bcc1bSBarry Smith Calling sequence of `f`: 4688420bcc1bSBarry Smith + snes - the `SNES` context 468949abdd8aSBarry Smith - vctx - [optional] context for private data for the function 4690c4421ceaSFande Kong 4691c4421ceaSFande Kong Options Database Keys: 4692f6dfbefdSBarry Smith + -snes_converged_reason - sets a default `SNESConvergedReasonView()` 4693420bcc1bSBarry Smith - -snes_converged_reason_view_cancel - cancels all converged reason viewers that have been hardwired into a code by 4694420bcc1bSBarry Smith calls to `SNESConvergedReasonViewSet()`, but does not cancel those set via the options database. 4695c4421ceaSFande Kong 4696dc4c0fb0SBarry Smith Level: intermediate 4697dc4c0fb0SBarry Smith 4698f6dfbefdSBarry Smith Note: 4699c4421ceaSFande Kong Several different converged reason view routines may be set by calling 4700f6dfbefdSBarry Smith `SNESConvergedReasonViewSet()` multiple times; all will be called in the 4701c4421ceaSFande Kong order in which they were set. 4702c4421ceaSFande Kong 470349abdd8aSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`, `SNESConvergedReasonViewCancel()`, 470449abdd8aSBarry Smith `PetscCtxDestroyFn` 4705c4421ceaSFande Kong @*/ 470649abdd8aSBarry Smith PetscErrorCode SNESConvergedReasonViewSet(SNES snes, PetscErrorCode (*f)(SNES snes, void *vctx), void *vctx, PetscCtxDestroyFn *reasonviewdestroy) 4707d71ae5a4SJacob Faibussowitsch { 4708c4421ceaSFande Kong PetscFunctionBegin; 4709c4421ceaSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4710453a69bbSBarry Smith for (PetscInt i = 0; i < snes->numberreasonviews; i++) { 4711453a69bbSBarry Smith PetscBool identical; 4712453a69bbSBarry Smith 4713453a69bbSBarry Smith PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))(PetscVoidFn *)f, vctx, reasonviewdestroy, (PetscErrorCode (*)(void))(PetscVoidFn *)snes->reasonview[i], snes->reasonviewcontext[i], snes->reasonviewdestroy[i], &identical)); 47143ba16761SJacob Faibussowitsch if (identical) PetscFunctionReturn(PETSC_SUCCESS); 4715c4421ceaSFande Kong } 47165f80ce2aSJacob Faibussowitsch PetscCheck(snes->numberreasonviews < MAXSNESREASONVIEWS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many SNES reasonview set"); 4717c4421ceaSFande Kong snes->reasonview[snes->numberreasonviews] = f; 4718c4421ceaSFande Kong snes->reasonviewdestroy[snes->numberreasonviews] = reasonviewdestroy; 4719835f2295SStefano Zampini snes->reasonviewcontext[snes->numberreasonviews++] = vctx; 47203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4721c4421ceaSFande Kong } 4722c4421ceaSFande Kong 472391f3e32bSBarry Smith /*@ 4724420bcc1bSBarry Smith SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a `SNESConvergedReason` is to be viewed at the end of `SNESSolve()` 47250b4b7b1cSBarry Smith All the user-provided viewer routines set with `SNESConvergedReasonViewSet()` will be called, if they exist. 47262a359c20SBarry Smith 4727c3339decSBarry Smith Collective 47282a359c20SBarry Smith 47292fe279fdSBarry Smith Input Parameter: 4730f6dfbefdSBarry Smith . snes - the `SNES` object 47312a359c20SBarry Smith 4732f6dfbefdSBarry Smith Level: advanced 47332a359c20SBarry Smith 47341cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESConvergedReasonViewSet()`, `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, 4735f6dfbefdSBarry Smith `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()` 47362a359c20SBarry Smith @*/ 4737d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes) 4738d71ae5a4SJacob Faibussowitsch { 47392a359c20SBarry Smith static PetscBool incall = PETSC_FALSE; 47402a359c20SBarry Smith 47412a359c20SBarry Smith PetscFunctionBegin; 47423ba16761SJacob Faibussowitsch if (incall) PetscFunctionReturn(PETSC_SUCCESS); 47432a359c20SBarry Smith incall = PETSC_TRUE; 4744c4421ceaSFande Kong 4745c4421ceaSFande Kong /* All user-provided viewers are called first, if they exist. */ 474636d43d94SBarry Smith for (PetscInt i = 0; i < snes->numberreasonviews; i++) PetscCall((*snes->reasonview[i])(snes, snes->reasonviewcontext[i])); 4747c4421ceaSFande Kong 4748c4421ceaSFande Kong /* Call PETSc default routine if users ask for it */ 474936d43d94SBarry Smith if (snes->convergedreasonviewer) { 475036d43d94SBarry Smith PetscCall(PetscViewerPushFormat(snes->convergedreasonviewer, snes->convergedreasonformat)); 475136d43d94SBarry Smith PetscCall(SNESConvergedReasonView(snes, snes->convergedreasonviewer)); 475236d43d94SBarry Smith PetscCall(PetscViewerPopFormat(snes->convergedreasonviewer)); 47532a359c20SBarry Smith } 47542a359c20SBarry Smith incall = PETSC_FALSE; 47553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 47562a359c20SBarry Smith } 47572a359c20SBarry Smith 4758487a658cSBarry Smith /*@ 47590b4b7b1cSBarry Smith SNESSolve - Solves a nonlinear system $F(x) = b $ associated with a `SNES` object 47609b94acceSBarry Smith 4761c3339decSBarry Smith Collective 4762c7afd0dbSLois Curfman McInnes 4763b2002411SLois Curfman McInnes Input Parameters: 4764f6dfbefdSBarry Smith + snes - the `SNES` context 47650b4b7b1cSBarry Smith . b - the constant part of the equation $F(x) = b$, or `NULL` to use zero. 476685385478SLisandro Dalcin - x - the solution vector. 47679b94acceSBarry Smith 4768dc4c0fb0SBarry Smith Level: beginner 4769dc4c0fb0SBarry Smith 4770f6dfbefdSBarry Smith Note: 4771420bcc1bSBarry Smith The user should initialize the vector, `x`, with the initial guess 4772a9b45538SStefano Zampini for the nonlinear solve prior to calling `SNESSolve()` . 47738ddd3da0SLois Curfman McInnes 47741cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESSetFunction()`, `SNESSetJacobian()`, `SNESSetGridSequence()`, `SNESGetSolution()`, 4775db781477SPatrick Sanan `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRGetPreCheck()`, `SNESNewtonTRSetPostCheck()`, `SNESNewtonTRGetPostCheck()`, 4776a9b45538SStefano Zampini `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()` 47779b94acceSBarry Smith @*/ 4778d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSolve(SNES snes, Vec b, Vec x) 4779d71ae5a4SJacob Faibussowitsch { 4780ace3abfcSBarry Smith PetscBool flg; 4781efd51863SBarry Smith PetscInt grid; 47820298fd71SBarry Smith Vec xcreated = NULL; 4783caa4e7f2SJed Brown DM dm; 4784052efed2SBarry Smith 47853a40ed3dSBarry Smith PetscFunctionBegin; 47860700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4787a69afd8bSBarry Smith if (x) PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4788a69afd8bSBarry Smith if (x) PetscCheckSameComm(snes, 1, x, 3); 47890700a824SBarry Smith if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 479085385478SLisandro Dalcin if (b) PetscCheckSameComm(snes, 1, b, 2); 479185385478SLisandro Dalcin 479234b4d3a8SMatthew G. Knepley /* High level operations using the nonlinear solver */ 479306fc46c8SMatthew G. Knepley { 479406fc46c8SMatthew G. Knepley PetscViewer viewer; 479506fc46c8SMatthew G. Knepley PetscViewerFormat format; 47967c88af5aSMatthew G. Knepley PetscInt num; 479706fc46c8SMatthew G. Knepley PetscBool flg; 479806fc46c8SMatthew G. Knepley static PetscBool incall = PETSC_FALSE; 479906fc46c8SMatthew G. Knepley 480006fc46c8SMatthew G. Knepley if (!incall) { 480134b4d3a8SMatthew G. Knepley /* Estimate the convergence rate of the discretization */ 4802648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg)); 480306fc46c8SMatthew G. Knepley if (flg) { 480406fc46c8SMatthew G. Knepley PetscConvEst conv; 480546079b62SMatthew G. Knepley DM dm; 480646079b62SMatthew G. Knepley PetscReal *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */ 480746079b62SMatthew G. Knepley PetscInt Nf; 480806fc46c8SMatthew G. Knepley 480906fc46c8SMatthew G. Knepley incall = PETSC_TRUE; 48109566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 48119566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 48129566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(Nf, &alpha)); 48139566063dSJacob Faibussowitsch PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)snes), &conv)); 48149566063dSJacob Faibussowitsch PetscCall(PetscConvEstSetSolver(conv, (PetscObject)snes)); 48159566063dSJacob Faibussowitsch PetscCall(PetscConvEstSetFromOptions(conv)); 48169566063dSJacob Faibussowitsch PetscCall(PetscConvEstSetUp(conv)); 48179566063dSJacob Faibussowitsch PetscCall(PetscConvEstGetConvRate(conv, alpha)); 48189566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(viewer, format)); 48199566063dSJacob Faibussowitsch PetscCall(PetscConvEstRateView(conv, alpha, viewer)); 48209566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer)); 4821648c30bcSBarry Smith PetscCall(PetscViewerDestroy(&viewer)); 48229566063dSJacob Faibussowitsch PetscCall(PetscConvEstDestroy(&conv)); 48239566063dSJacob Faibussowitsch PetscCall(PetscFree(alpha)); 482406fc46c8SMatthew G. Knepley incall = PETSC_FALSE; 482506fc46c8SMatthew G. Knepley } 482634b4d3a8SMatthew G. Knepley /* Adaptively refine the initial grid */ 4827b2588ea6SMatthew G. Knepley num = 1; 48289566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_initial", &num, &flg)); 482934b4d3a8SMatthew G. Knepley if (flg) { 483034b4d3a8SMatthew G. Knepley DMAdaptor adaptor; 483134b4d3a8SMatthew G. Knepley 483234b4d3a8SMatthew G. Knepley incall = PETSC_TRUE; 48339566063dSJacob Faibussowitsch PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor)); 48349566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSolver(adaptor, snes)); 48359566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSequenceLength(adaptor, num)); 48369566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetFromOptions(adaptor)); 48379566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetUp(adaptor)); 48389566063dSJacob Faibussowitsch PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x)); 48399566063dSJacob Faibussowitsch PetscCall(DMAdaptorDestroy(&adaptor)); 484034b4d3a8SMatthew G. Knepley incall = PETSC_FALSE; 484134b4d3a8SMatthew G. Knepley } 48427c88af5aSMatthew G. Knepley /* Use grid sequencing to adapt */ 48437c88af5aSMatthew G. Knepley num = 0; 48449566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_sequence", &num, NULL)); 48457c88af5aSMatthew G. Knepley if (num) { 48467c88af5aSMatthew G. Knepley DMAdaptor adaptor; 4847e03fd340SMatthew G. Knepley const char *prefix; 48487c88af5aSMatthew G. Knepley 48497c88af5aSMatthew G. Knepley incall = PETSC_TRUE; 48509566063dSJacob Faibussowitsch PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor)); 4851e03fd340SMatthew G. Knepley PetscCall(SNESGetOptionsPrefix(snes, &prefix)); 4852e03fd340SMatthew G. Knepley PetscCall(DMAdaptorSetOptionsPrefix(adaptor, prefix)); 48539566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSolver(adaptor, snes)); 48549566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSequenceLength(adaptor, num)); 48559566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetFromOptions(adaptor)); 48569566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetUp(adaptor)); 4857e5148a0bSMatthew G. Knepley PetscCall(PetscObjectViewFromOptions((PetscObject)adaptor, NULL, "-snes_adapt_view")); 48589566063dSJacob Faibussowitsch PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x)); 48599566063dSJacob Faibussowitsch PetscCall(DMAdaptorDestroy(&adaptor)); 48607c88af5aSMatthew G. Knepley incall = PETSC_FALSE; 48617c88af5aSMatthew G. Knepley } 486206fc46c8SMatthew G. Knepley } 486306fc46c8SMatthew G. Knepley } 4864ad540459SPierre Jolivet if (!x) x = snes->vec_sol; 4865caa4e7f2SJed Brown if (!x) { 48669566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 48679566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dm, &xcreated)); 4868a69afd8bSBarry Smith x = xcreated; 4869a69afd8bSBarry Smith } 48709566063dSJacob Faibussowitsch PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view_pre")); 4871f05ece33SBarry Smith 48729566063dSJacob Faibussowitsch for (grid = 0; grid < snes->gridsequence; grid++) PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)))); 4873efd51863SBarry Smith for (grid = 0; grid < snes->gridsequence + 1; grid++) { 487485385478SLisandro Dalcin /* set solution vector */ 48759566063dSJacob Faibussowitsch if (!grid) PetscCall(PetscObjectReference((PetscObject)x)); 48769566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol)); 487785385478SLisandro Dalcin snes->vec_sol = x; 48789566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 4879caa4e7f2SJed Brown 4880caa4e7f2SJed Brown /* set affine vector if provided */ 48819566063dSJacob Faibussowitsch if (b) PetscCall(PetscObjectReference((PetscObject)b)); 48829566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_rhs)); 488385385478SLisandro Dalcin snes->vec_rhs = b; 488485385478SLisandro Dalcin 48855f80ce2aSJacob 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"); 48865f80ce2aSJacob Faibussowitsch PetscCheck(snes->vec_func != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be function vector"); 4887dd8e379bSPierre Jolivet PetscCheck(snes->vec_rhs != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be right-hand side vector"); 4888aa624791SPierre Jolivet if (!snes->vec_sol_update /* && snes->vec_sol */) PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_sol_update)); 48899566063dSJacob Faibussowitsch PetscCall(DMShellSetGlobalVector(dm, snes->vec_sol)); 48909566063dSJacob Faibussowitsch PetscCall(SNESSetUp(snes)); 48913f149594SLisandro Dalcin 48927eee914bSBarry Smith if (!grid) { 48939927e4dfSBarry Smith if (snes->ops->computeinitialguess) PetscCallBack("SNES callback compute initial guess", (*snes->ops->computeinitialguess)(snes, snes->vec_sol, snes->initialguessP)); 4894dd568438SSatish Balay } 4895d25893d9SBarry Smith 4896abc0a331SBarry Smith if (snes->conv_hist_reset) snes->conv_hist_len = 0; 489712b1dd1aSStefano Zampini PetscCall(SNESResetCounters(snes)); 48982d157150SStefano Zampini snes->reason = SNES_CONVERGED_ITERATING; 48999566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_Solve, snes, 0, 0, 0)); 4900dbbe0bcdSBarry Smith PetscUseTypeMethod(snes, solve); 49019566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_Solve, snes, 0, 0, 0)); 49022d157150SStefano Zampini PetscCheck(snes->reason, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error, solver %s returned without setting converged reason", ((PetscObject)snes)->type_name); 490376c63389SBarry Smith snes->functiondomainerror = PETSC_FALSE; /* clear the flag if it has been set */ 490476c63389SBarry Smith snes->objectivedomainerror = PETSC_FALSE; /* clear the flag if it has been set */ 490576c63389SBarry Smith snes->jacobiandomainerror = PETSC_FALSE; /* clear the flag if it has been set */ 49063f149594SLisandro Dalcin 490737ec4e1aSPeter Brune if (snes->lagjac_persist) snes->jac_iter += snes->iter; 490837ec4e1aSPeter Brune if (snes->lagpre_persist) snes->pre_iter += snes->iter; 490937ec4e1aSPeter Brune 4910648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_test_local_min", NULL, NULL, &flg)); 49119566063dSJacob Faibussowitsch if (flg && !PetscPreLoadingOn) PetscCall(SNESTestLocalMin(snes)); 4912c4421ceaSFande Kong /* Call converged reason views. This may involve user-provided viewers as well */ 49139566063dSJacob Faibussowitsch PetscCall(SNESConvergedReasonViewFromOptions(snes)); 49145968eb51SBarry Smith 49151b3000acSStefano Zampini if (snes->errorifnotconverged) { 49161b3000acSStefano Zampini if (snes->reason < 0) PetscCall(SNESMonitorCancel(snes)); 49171b3000acSStefano Zampini PetscCheck(snes->reason >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_NOT_CONVERGED, "SNESSolve has not converged"); 49181b3000acSStefano Zampini } 49199c8e83a9SBarry Smith if (snes->reason < 0) break; 4920efd51863SBarry Smith if (grid < snes->gridsequence) { 4921efd51863SBarry Smith DM fine; 4922efd51863SBarry Smith Vec xnew; 4923efd51863SBarry Smith Mat interp; 4924efd51863SBarry Smith 49259566063dSJacob Faibussowitsch PetscCall(DMRefine(snes->dm, PetscObjectComm((PetscObject)snes), &fine)); 49265f80ce2aSJacob Faibussowitsch PetscCheck(fine, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_INCOMP, "DMRefine() did not perform any refinement, cannot continue grid sequencing"); 49272eace19aSMatthew G. Knepley PetscCall(DMGetCoordinatesLocalSetUp(fine)); 49289566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(snes->dm, fine, &interp, NULL)); 49299566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(fine, &xnew)); 49309566063dSJacob Faibussowitsch PetscCall(MatInterpolate(interp, x, xnew)); 49319566063dSJacob Faibussowitsch PetscCall(DMInterpolate(snes->dm, interp, fine)); 49329566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interp)); 4933efd51863SBarry Smith x = xnew; 4934efd51863SBarry Smith 49359566063dSJacob Faibussowitsch PetscCall(SNESReset(snes)); 49369566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes, fine)); 49379566063dSJacob Faibussowitsch PetscCall(SNESResetFromOptions(snes)); 49389566063dSJacob Faibussowitsch PetscCall(DMDestroy(&fine)); 49399566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)))); 4940efd51863SBarry Smith } 4941efd51863SBarry Smith } 49429566063dSJacob Faibussowitsch PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view")); 49439566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(snes->vec_sol, (PetscObject)snes, "-snes_view_solution")); 49449566063dSJacob Faibussowitsch PetscCall(DMMonitor(snes->dm)); 49459566063dSJacob Faibussowitsch PetscCall(SNESMonitorPauseFinal_Internal(snes)); 49463f7e2da0SPeter Brune 49479566063dSJacob Faibussowitsch PetscCall(VecDestroy(&xcreated)); 49489566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsBlock((PetscObject)snes)); 49493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49509b94acceSBarry Smith } 49519b94acceSBarry Smith 49529b94acceSBarry Smith /* --------- Internal routines for SNES Package --------- */ 49539b94acceSBarry Smith 4954cc4c1da9SBarry Smith /*@ 49550b4b7b1cSBarry Smith SNESSetType - Sets the algorithm/method to be used to solve the nonlinear system with the given `SNES` 49569b94acceSBarry Smith 4957c3339decSBarry Smith Collective 4958fee21e36SBarry Smith 4959c7afd0dbSLois Curfman McInnes Input Parameters: 4960f6dfbefdSBarry Smith + snes - the `SNES` context 4961454a90a3SBarry Smith - type - a known method 4962c7afd0dbSLois Curfman McInnes 4963c7afd0dbSLois Curfman McInnes Options Database Key: 4964454a90a3SBarry Smith . -snes_type <type> - Sets the method; use -help for a list 496504d7464bSBarry Smith of available methods (for instance, newtonls or newtontr) 4966ae12b187SLois Curfman McInnes 4967dc4c0fb0SBarry Smith Level: intermediate 4968dc4c0fb0SBarry Smith 49699b94acceSBarry Smith Notes: 49700b4b7b1cSBarry Smith See `SNESType` for available methods (for instance) 4971f6dfbefdSBarry Smith + `SNESNEWTONLS` - Newton's method with line search 4972c7afd0dbSLois Curfman McInnes (systems of nonlinear equations) 49734a221d59SStefano Zampini - `SNESNEWTONTR` - Newton's method with trust region 4974c7afd0dbSLois Curfman McInnes (systems of nonlinear equations) 49759b94acceSBarry Smith 4976f6dfbefdSBarry Smith Normally, it is best to use the `SNESSetFromOptions()` command and then 4977f6dfbefdSBarry Smith set the `SNES` solver type from the options database rather than by using 4978ae12b187SLois Curfman McInnes this routine. Using the options database provides the user with 4979ae12b187SLois Curfman McInnes maximum flexibility in evaluating the many nonlinear solvers. 4980f6dfbefdSBarry Smith The `SNESSetType()` routine is provided for those situations where it 4981ae12b187SLois Curfman McInnes is necessary to set the nonlinear solver independently of the command 4982ae12b187SLois Curfman McInnes line or options database. This might be the case, for example, when 4983ae12b187SLois Curfman McInnes the choice of solver changes during the execution of the program, 4984ae12b187SLois Curfman McInnes and the user's application is taking responsibility for choosing the 4985b0a32e0cSBarry Smith appropriate method. 498636851e7fSLois Curfman McInnes 4987420bcc1bSBarry Smith Developer Note: 4988f6dfbefdSBarry Smith `SNESRegister()` adds a constructor for a new `SNESType` to `SNESList`, `SNESSetType()` locates 4989f6dfbefdSBarry Smith the constructor in that list and calls it to create the specific object. 49908f6c3df8SBarry Smith 49911cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESType`, `SNESCreate()`, `SNESDestroy()`, `SNESGetType()`, `SNESSetFromOptions()` 49929b94acceSBarry Smith @*/ 4993d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetType(SNES snes, SNESType type) 4994d71ae5a4SJacob Faibussowitsch { 4995ace3abfcSBarry Smith PetscBool match; 49965f80ce2aSJacob Faibussowitsch PetscErrorCode (*r)(SNES); 49973a40ed3dSBarry Smith 49983a40ed3dSBarry Smith PetscFunctionBegin; 49990700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 50004f572ea9SToby Isaac PetscAssertPointer(type, 2); 500182bf6240SBarry Smith 50029566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes, type, &match)); 50033ba16761SJacob Faibussowitsch if (match) PetscFunctionReturn(PETSC_SUCCESS); 500492ff6ae8SBarry Smith 50059566063dSJacob Faibussowitsch PetscCall(PetscFunctionListFind(SNESList, type, &r)); 50066adde796SStefano Zampini PetscCheck(r, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested SNES type %s", type); 500775396ef9SLisandro Dalcin /* Destroy the previous private SNES context */ 5008dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, destroy); 500943547594SStefano Zampini /* Reinitialize type-specific function pointers in SNESOps structure */ 501043547594SStefano Zampini snes->ops->reset = NULL; 50119e5d0892SLisandro Dalcin snes->ops->setup = NULL; 50129e5d0892SLisandro Dalcin snes->ops->solve = NULL; 50139e5d0892SLisandro Dalcin snes->ops->view = NULL; 50149e5d0892SLisandro Dalcin snes->ops->setfromoptions = NULL; 50159e5d0892SLisandro Dalcin snes->ops->destroy = NULL; 50167fe760d5SStefano Zampini 50177fe760d5SStefano Zampini /* It may happen the user has customized the line search before calling SNESSetType */ 50189566063dSJacob Faibussowitsch if (((PetscObject)snes)->type_name) PetscCall(SNESLineSearchDestroy(&snes->linesearch)); 50197fe760d5SStefano Zampini 502075396ef9SLisandro Dalcin /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */ 502175396ef9SLisandro Dalcin snes->setupcalled = PETSC_FALSE; 5022f5af7f23SKarl Rupp 50239566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)snes, type)); 50249566063dSJacob Faibussowitsch PetscCall((*r)(snes)); 50253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50269b94acceSBarry Smith } 50279b94acceSBarry Smith 5028cc4c1da9SBarry Smith /*@ 5029f6dfbefdSBarry Smith SNESGetType - Gets the `SNES` method type and name (as a string). 50309b94acceSBarry Smith 5031c7afd0dbSLois Curfman McInnes Not Collective 5032c7afd0dbSLois Curfman McInnes 50339b94acceSBarry Smith Input Parameter: 50344b0e389bSBarry Smith . snes - nonlinear solver context 50359b94acceSBarry Smith 50369b94acceSBarry Smith Output Parameter: 5037f6dfbefdSBarry Smith . type - `SNES` method (a character string) 50389b94acceSBarry Smith 503936851e7fSLois Curfman McInnes Level: intermediate 504036851e7fSLois Curfman McInnes 50411cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetType()`, `SNESType`, `SNESSetFromOptions()`, `SNES` 50429b94acceSBarry Smith @*/ 5043d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetType(SNES snes, SNESType *type) 5044d71ae5a4SJacob Faibussowitsch { 50453a40ed3dSBarry Smith PetscFunctionBegin; 50460700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 50474f572ea9SToby Isaac PetscAssertPointer(type, 2); 50487adad957SLisandro Dalcin *type = ((PetscObject)snes)->type_name; 50493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50509b94acceSBarry Smith } 50519b94acceSBarry Smith 50523cd8a7caSMatthew G. Knepley /*@ 5053f6dfbefdSBarry Smith SNESSetSolution - Sets the solution vector for use by the `SNES` routines. 50543cd8a7caSMatthew G. Knepley 5055c3339decSBarry Smith Logically Collective 50563cd8a7caSMatthew G. Knepley 50573cd8a7caSMatthew G. Knepley Input Parameters: 5058f6dfbefdSBarry Smith + snes - the `SNES` context obtained from `SNESCreate()` 50593cd8a7caSMatthew G. Knepley - u - the solution vector 50603cd8a7caSMatthew G. Knepley 50613cd8a7caSMatthew G. Knepley Level: beginner 50623cd8a7caSMatthew G. Knepley 50631cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetSolution()`, `Vec` 50643cd8a7caSMatthew G. Knepley @*/ 5065d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetSolution(SNES snes, Vec u) 5066d71ae5a4SJacob Faibussowitsch { 50673cd8a7caSMatthew G. Knepley DM dm; 50683cd8a7caSMatthew G. Knepley 50693cd8a7caSMatthew G. Knepley PetscFunctionBegin; 50703cd8a7caSMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 50713cd8a7caSMatthew G. Knepley PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 50729566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)u)); 50739566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol)); 50743cd8a7caSMatthew G. Knepley 50753cd8a7caSMatthew G. Knepley snes->vec_sol = u; 50763cd8a7caSMatthew G. Knepley 50779566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 50789566063dSJacob Faibussowitsch PetscCall(DMShellSetGlobalVector(dm, u)); 50793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50803cd8a7caSMatthew G. Knepley } 50813cd8a7caSMatthew G. Knepley 508252baeb72SSatish Balay /*@ 50839b94acceSBarry Smith SNESGetSolution - Returns the vector where the approximate solution is 5084f6dfbefdSBarry Smith stored. This is the fine grid solution when using `SNESSetGridSequence()`. 50859b94acceSBarry Smith 5086420bcc1bSBarry Smith Not Collective, but `x` is parallel if `snes` is parallel 5087c7afd0dbSLois Curfman McInnes 50889b94acceSBarry Smith Input Parameter: 5089f6dfbefdSBarry Smith . snes - the `SNES` context 50909b94acceSBarry Smith 50919b94acceSBarry Smith Output Parameter: 50929b94acceSBarry Smith . x - the solution 50939b94acceSBarry Smith 509470e92668SMatthew Knepley Level: intermediate 509536851e7fSLois Curfman McInnes 50961cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetSolution()`, `SNESSolve()`, `SNES`, `SNESGetSolutionUpdate()`, `SNESGetFunction()` 50979b94acceSBarry Smith @*/ 5098d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolution(SNES snes, Vec *x) 5099d71ae5a4SJacob Faibussowitsch { 51003a40ed3dSBarry Smith PetscFunctionBegin; 51010700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 51024f572ea9SToby Isaac PetscAssertPointer(x, 2); 510385385478SLisandro Dalcin *x = snes->vec_sol; 51043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 510570e92668SMatthew Knepley } 510670e92668SMatthew Knepley 510752baeb72SSatish Balay /*@ 51089b94acceSBarry Smith SNESGetSolutionUpdate - Returns the vector where the solution update is 51099b94acceSBarry Smith stored. 51109b94acceSBarry Smith 5111420bcc1bSBarry Smith Not Collective, but `x` is parallel if `snes` is parallel 5112c7afd0dbSLois Curfman McInnes 51139b94acceSBarry Smith Input Parameter: 5114f6dfbefdSBarry Smith . snes - the `SNES` context 51159b94acceSBarry Smith 51169b94acceSBarry Smith Output Parameter: 51179b94acceSBarry Smith . x - the solution update 51189b94acceSBarry Smith 511936851e7fSLois Curfman McInnes Level: advanced 512036851e7fSLois Curfman McInnes 51211cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()` 51229b94acceSBarry Smith @*/ 5123d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionUpdate(SNES snes, Vec *x) 5124d71ae5a4SJacob Faibussowitsch { 51253a40ed3dSBarry Smith PetscFunctionBegin; 51260700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 51274f572ea9SToby Isaac PetscAssertPointer(x, 2); 512885385478SLisandro Dalcin *x = snes->vec_sol_update; 51293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 51309b94acceSBarry Smith } 51319b94acceSBarry Smith 51329b94acceSBarry Smith /*@C 5133f6dfbefdSBarry Smith SNESGetFunction - Returns the function that defines the nonlinear system set with `SNESSetFunction()` 51349b94acceSBarry Smith 5135420bcc1bSBarry Smith Not Collective, but `r` is parallel if `snes` is parallel. Collective if `r` is requested, but has not been created yet. 5136c7afd0dbSLois Curfman McInnes 51379b94acceSBarry Smith Input Parameter: 5138f6dfbefdSBarry Smith . snes - the `SNES` context 51399b94acceSBarry Smith 5140d8d19677SJose E. Roman Output Parameters: 5141dc4c0fb0SBarry Smith + r - the vector that is used to store residuals (or `NULL` if you don't want it) 51428434afd1SBarry Smith . f - the function (or `NULL` if you don't want it); for calling sequence see `SNESFunctionFn` 5143dc4c0fb0SBarry Smith - ctx - the function context (or `NULL` if you don't want it) 51449b94acceSBarry Smith 514536851e7fSLois Curfman McInnes Level: advanced 514636851e7fSLois Curfman McInnes 5147f6dfbefdSBarry Smith Note: 5148dc4c0fb0SBarry Smith The vector `r` DOES NOT, in general, contain the current value of the `SNES` nonlinear function 514904edfde5SBarry Smith 51508434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetSolution()`, `SNESFunctionFn` 51519b94acceSBarry Smith @*/ 51522a8381b2SBarry Smith PetscErrorCode SNESGetFunction(SNES snes, Vec *r, SNESFunctionFn **f, PetscCtxRt ctx) 5153d71ae5a4SJacob Faibussowitsch { 51546cab3a1bSJed Brown DM dm; 5155a63bb30eSJed Brown 51563a40ed3dSBarry Smith PetscFunctionBegin; 51570700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5158a63bb30eSJed Brown if (r) { 5159a63bb30eSJed Brown if (!snes->vec_func) { 5160a63bb30eSJed Brown if (snes->vec_rhs) { 51619566063dSJacob Faibussowitsch PetscCall(VecDuplicate(snes->vec_rhs, &snes->vec_func)); 5162a63bb30eSJed Brown } else if (snes->vec_sol) { 51639566063dSJacob Faibussowitsch PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_func)); 5164a63bb30eSJed Brown } else if (snes->dm) { 51659566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(snes->dm, &snes->vec_func)); 5166a63bb30eSJed Brown } 5167a63bb30eSJed Brown } 5168a63bb30eSJed Brown *r = snes->vec_func; 5169a63bb30eSJed Brown } 51709566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 51719566063dSJacob Faibussowitsch PetscCall(DMSNESGetFunction(dm, f, ctx)); 51723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 51739b94acceSBarry Smith } 51749b94acceSBarry Smith 5175c79ef259SPeter Brune /*@C 517637fdd005SBarry Smith SNESGetNGS - Returns the function and context set with `SNESSetNGS()` 5177c79ef259SPeter Brune 5178c79ef259SPeter Brune Input Parameter: 5179f6dfbefdSBarry Smith . snes - the `SNES` context 5180c79ef259SPeter Brune 5181d8d19677SJose E. Roman Output Parameters: 51828434afd1SBarry Smith + f - the function (or `NULL`) see `SNESNGSFn` for calling sequence 5183dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`) 5184c79ef259SPeter Brune 5185c79ef259SPeter Brune Level: advanced 5186c79ef259SPeter Brune 51878434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetNGS()`, `SNESGetFunction()`, `SNESNGSFn` 5188c79ef259SPeter Brune @*/ 51892a8381b2SBarry Smith PetscErrorCode SNESGetNGS(SNES snes, SNESNGSFn **f, PetscCtxRt ctx) 5190d71ae5a4SJacob Faibussowitsch { 51916cab3a1bSJed Brown DM dm; 51926cab3a1bSJed Brown 5193646217ecSPeter Brune PetscFunctionBegin; 5194646217ecSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 51959566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 51969566063dSJacob Faibussowitsch PetscCall(DMSNESGetNGS(dm, f, ctx)); 51973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5198646217ecSPeter Brune } 5199646217ecSPeter Brune 5200cc4c1da9SBarry Smith /*@ 52013c7409f5SSatish Balay SNESSetOptionsPrefix - Sets the prefix used for searching for all 5202f6dfbefdSBarry Smith `SNES` options in the database. 52033c7409f5SSatish Balay 5204c3339decSBarry Smith Logically Collective 5205fee21e36SBarry Smith 5206d8d19677SJose E. Roman Input Parameters: 5207f6dfbefdSBarry Smith + snes - the `SNES` context 5208c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names 5209c7afd0dbSLois Curfman McInnes 5210dc4c0fb0SBarry Smith Level: advanced 5211dc4c0fb0SBarry Smith 5212f6dfbefdSBarry Smith Note: 5213a83b1b31SSatish Balay A hyphen (-) must NOT be given at the beginning of the prefix name. 5214c7afd0dbSLois Curfman McInnes The first character of all runtime options is AUTOMATICALLY the hyphen. 5215d850072dSLois Curfman McInnes 52161cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESAppendOptionsPrefix()` 52173c7409f5SSatish Balay @*/ 5218d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetOptionsPrefix(SNES snes, const char prefix[]) 5219d71ae5a4SJacob Faibussowitsch { 52203a40ed3dSBarry Smith PetscFunctionBegin; 52210700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 52229566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes, prefix)); 52239566063dSJacob Faibussowitsch if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 522435f5d045SPeter Brune if (snes->linesearch) { 52259566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 52269566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch, prefix)); 522735f5d045SPeter Brune } 52289566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(snes->ksp, prefix)); 52293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 52303c7409f5SSatish Balay } 52313c7409f5SSatish Balay 5232cc4c1da9SBarry Smith /*@ 5233f525115eSLois Curfman McInnes SNESAppendOptionsPrefix - Appends to the prefix used for searching for all 5234f6dfbefdSBarry Smith `SNES` options in the database. 52353c7409f5SSatish Balay 5236c3339decSBarry Smith Logically Collective 5237fee21e36SBarry Smith 5238c7afd0dbSLois Curfman McInnes Input Parameters: 5239f6dfbefdSBarry Smith + snes - the `SNES` context 5240c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names 5241c7afd0dbSLois Curfman McInnes 5242dc4c0fb0SBarry Smith Level: advanced 5243dc4c0fb0SBarry Smith 5244f6dfbefdSBarry Smith Note: 5245a83b1b31SSatish Balay A hyphen (-) must NOT be given at the beginning of the prefix name. 5246c7afd0dbSLois Curfman McInnes The first character of all runtime options is AUTOMATICALLY the hyphen. 5247d850072dSLois Curfman McInnes 52481cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetOptionsPrefix()`, `SNESSetOptionsPrefix()` 52493c7409f5SSatish Balay @*/ 5250d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESAppendOptionsPrefix(SNES snes, const char prefix[]) 5251d71ae5a4SJacob Faibussowitsch { 52523a40ed3dSBarry Smith PetscFunctionBegin; 52530700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 52549566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes, prefix)); 52559566063dSJacob Faibussowitsch if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 525635f5d045SPeter Brune if (snes->linesearch) { 52579566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 52589566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch, prefix)); 525935f5d045SPeter Brune } 52609566063dSJacob Faibussowitsch PetscCall(KSPAppendOptionsPrefix(snes->ksp, prefix)); 52613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 52623c7409f5SSatish Balay } 52633c7409f5SSatish Balay 5264cc4c1da9SBarry Smith /*@ 5265f6dfbefdSBarry Smith SNESGetOptionsPrefix - Gets the prefix used for searching for all 5266f6dfbefdSBarry Smith `SNES` options in the database. 52673c7409f5SSatish Balay 5268c7afd0dbSLois Curfman McInnes Not Collective 5269c7afd0dbSLois Curfman McInnes 52703c7409f5SSatish Balay Input Parameter: 5271f6dfbefdSBarry Smith . snes - the `SNES` context 52723c7409f5SSatish Balay 52733c7409f5SSatish Balay Output Parameter: 52743c7409f5SSatish Balay . prefix - pointer to the prefix string used 52753c7409f5SSatish Balay 527636851e7fSLois Curfman McInnes Level: advanced 527736851e7fSLois Curfman McInnes 52781cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetOptionsPrefix()`, `SNESAppendOptionsPrefix()` 52793c7409f5SSatish Balay @*/ 5280d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetOptionsPrefix(SNES snes, const char *prefix[]) 5281d71ae5a4SJacob Faibussowitsch { 52823a40ed3dSBarry Smith PetscFunctionBegin; 52830700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 52849566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)snes, prefix)); 52853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 52863c7409f5SSatish Balay } 52873c7409f5SSatish Balay 52883cea93caSBarry Smith /*@C 52891c84c290SBarry Smith SNESRegister - Adds a method to the nonlinear solver package. 52901c84c290SBarry Smith 529120f4b53cSBarry Smith Not Collective 52921c84c290SBarry Smith 52931c84c290SBarry Smith Input Parameters: 529420f4b53cSBarry Smith + sname - name of a new user-defined solver 529520f4b53cSBarry Smith - function - routine to create method context 52961c84c290SBarry Smith 5297dc4c0fb0SBarry Smith Level: advanced 5298dc4c0fb0SBarry Smith 5299f6dfbefdSBarry Smith Note: 5300f6dfbefdSBarry Smith `SNESRegister()` may be called multiple times to add several user-defined solvers. 53011c84c290SBarry Smith 5302e4094ef1SJacob Faibussowitsch Example Usage: 53031c84c290SBarry Smith .vb 5304bdf89e91SBarry Smith SNESRegister("my_solver", MySolverCreate); 53051c84c290SBarry Smith .ve 53061c84c290SBarry Smith 53071c84c290SBarry Smith Then, your solver can be chosen with the procedural interface via 5308b44f4de4SBarry Smith .vb 5309b44f4de4SBarry Smith SNESSetType(snes, "my_solver") 5310b44f4de4SBarry Smith .ve 53111c84c290SBarry Smith or at runtime via the option 5312b44f4de4SBarry Smith .vb 5313b44f4de4SBarry Smith -snes_type my_solver 5314b44f4de4SBarry Smith .ve 53151c84c290SBarry Smith 53161cc06b55SBarry Smith .seealso: [](ch_snes), `SNESRegisterAll()`, `SNESRegisterDestroy()` 53173cea93caSBarry Smith @*/ 5318d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESRegister(const char sname[], PetscErrorCode (*function)(SNES)) 5319d71ae5a4SJacob Faibussowitsch { 5320b2002411SLois Curfman McInnes PetscFunctionBegin; 53219566063dSJacob Faibussowitsch PetscCall(SNESInitializePackage()); 53229566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&SNESList, sname, function)); 53233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5324b2002411SLois Curfman McInnes } 5325da9b6338SBarry Smith 5326d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestLocalMin(SNES snes) 5327d71ae5a4SJacob Faibussowitsch { 532877431f27SBarry Smith PetscInt N, i, j; 5329da9b6338SBarry Smith Vec u, uh, fh; 5330da9b6338SBarry Smith PetscScalar value; 5331da9b6338SBarry Smith PetscReal norm; 5332da9b6338SBarry Smith 5333da9b6338SBarry Smith PetscFunctionBegin; 53349566063dSJacob Faibussowitsch PetscCall(SNESGetSolution(snes, &u)); 53359566063dSJacob Faibussowitsch PetscCall(VecDuplicate(u, &uh)); 53369566063dSJacob Faibussowitsch PetscCall(VecDuplicate(u, &fh)); 5337da9b6338SBarry Smith 5338da9b6338SBarry Smith /* currently only works for sequential */ 53399566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Testing FormFunction() for local min\n")); 53409566063dSJacob Faibussowitsch PetscCall(VecGetSize(u, &N)); 5341da9b6338SBarry Smith for (i = 0; i < N; i++) { 53429566063dSJacob Faibussowitsch PetscCall(VecCopy(u, uh)); 534363a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "i = %" PetscInt_FMT "\n", i)); 5344da9b6338SBarry Smith for (j = -10; j < 11; j++) { 53458b49ba18SBarry Smith value = PetscSign(j) * PetscExpReal(PetscAbs(j) - 10.0); 53469566063dSJacob Faibussowitsch PetscCall(VecSetValue(uh, i, value, ADD_VALUES)); 53479566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, uh, fh)); 534876c63389SBarry Smith PetscCall(VecNorm(fh, NORM_2, &norm)); /* does not handle use of SNESSetFunctionDomainError() correctly */ 534963a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), " j norm %" PetscInt_FMT " %18.16e\n", j, (double)norm)); 5350da9b6338SBarry Smith value = -value; 53519566063dSJacob Faibussowitsch PetscCall(VecSetValue(uh, i, value, ADD_VALUES)); 5352da9b6338SBarry Smith } 5353da9b6338SBarry Smith } 53549566063dSJacob Faibussowitsch PetscCall(VecDestroy(&uh)); 53559566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fh)); 53563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5357da9b6338SBarry Smith } 535871f87433Sdalcinl 535971f87433Sdalcinl /*@ 536076c63389SBarry Smith SNESGetLineSearch - Returns the line search associated with the `SNES`. 536176c63389SBarry Smith 536276c63389SBarry Smith Not Collective 536376c63389SBarry Smith 536476c63389SBarry Smith Input Parameter: 536576c63389SBarry Smith . snes - iterative context obtained from `SNESCreate()` 536676c63389SBarry Smith 536776c63389SBarry Smith Output Parameter: 536876c63389SBarry Smith . linesearch - linesearch context 536976c63389SBarry Smith 537076c63389SBarry Smith Level: beginner 537176c63389SBarry Smith 537276c63389SBarry Smith Notes: 537376c63389SBarry Smith It creates a default line search instance which can be configured as needed in case it has not been already set with `SNESSetLineSearch()`. 537476c63389SBarry Smith 537576c63389SBarry Smith You can also use the options database keys `-snes_linesearch_*` to configure the line search. See `SNESLineSearchSetFromOptions()` for the possible options. 537676c63389SBarry Smith 537776c63389SBarry Smith .seealso: [](ch_snes), `SNESLineSearch`, `SNESSetLineSearch()`, `SNESLineSearchCreate()`, `SNESLineSearchSetFromOptions()` 537876c63389SBarry Smith @*/ 537976c63389SBarry Smith PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch) 538076c63389SBarry Smith { 538176c63389SBarry Smith const char *optionsprefix; 538276c63389SBarry Smith 538376c63389SBarry Smith PetscFunctionBegin; 538476c63389SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 538576c63389SBarry Smith PetscAssertPointer(linesearch, 2); 538676c63389SBarry Smith if (!snes->linesearch) { 538776c63389SBarry Smith PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 538876c63389SBarry Smith PetscCall(SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch)); 538976c63389SBarry Smith PetscCall(SNESLineSearchSetSNES(snes->linesearch, snes)); 539076c63389SBarry Smith PetscCall(SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix)); 539176c63389SBarry Smith PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->linesearch, (PetscObject)snes, 1)); 539276c63389SBarry Smith } 539376c63389SBarry Smith *linesearch = snes->linesearch; 539476c63389SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 539576c63389SBarry Smith } 539676c63389SBarry Smith 539776c63389SBarry Smith /*@ 5398f6dfbefdSBarry Smith SNESKSPSetUseEW - Sets `SNES` to the use Eisenstat-Walker method for 539971f87433Sdalcinl computing relative tolerance for linear solvers within an inexact 540071f87433Sdalcinl Newton method. 540171f87433Sdalcinl 5402c3339decSBarry Smith Logically Collective 540371f87433Sdalcinl 540471f87433Sdalcinl Input Parameters: 5405f6dfbefdSBarry Smith + snes - `SNES` context 5406f6dfbefdSBarry Smith - flag - `PETSC_TRUE` or `PETSC_FALSE` 540771f87433Sdalcinl 5408f6dfbefdSBarry Smith Options Database Keys: 540964ba62caSBarry Smith + -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence 541064ba62caSBarry Smith . -snes_ksp_ew_version ver - version of Eisenstat-Walker method 541164ba62caSBarry Smith . -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0 541264ba62caSBarry Smith . -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax 541364ba62caSBarry Smith . -snes_ksp_ew_gamma <gamma> - Sets gamma 541464ba62caSBarry Smith . -snes_ksp_ew_alpha <alpha> - Sets alpha 541564ba62caSBarry Smith . -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2 541664ba62caSBarry Smith - -snes_ksp_ew_threshold <threshold> - Sets threshold 541764ba62caSBarry Smith 5418dc4c0fb0SBarry Smith Level: advanced 5419dc4c0fb0SBarry Smith 5420f6dfbefdSBarry Smith Note: 5421f6dfbefdSBarry Smith The default is to use a constant relative tolerance for 542271f87433Sdalcinl the inner linear solvers. Alternatively, one can use the 54231d27aa22SBarry Smith Eisenstat-Walker method {cite}`ew96`, where the relative convergence tolerance 542471f87433Sdalcinl is reset at each Newton iteration according progress of the nonlinear 542571f87433Sdalcinl solver. 542671f87433Sdalcinl 54271cc06b55SBarry Smith .seealso: [](ch_snes), `KSP`, `SNES`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()` 542871f87433Sdalcinl @*/ 5429d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetUseEW(SNES snes, PetscBool flag) 5430d71ae5a4SJacob Faibussowitsch { 543171f87433Sdalcinl PetscFunctionBegin; 54320700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5433acfcf0e5SJed Brown PetscValidLogicalCollectiveBool(snes, flag, 2); 543471f87433Sdalcinl snes->ksp_ewconv = flag; 54353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 543671f87433Sdalcinl } 543771f87433Sdalcinl 543871f87433Sdalcinl /*@ 5439f6dfbefdSBarry Smith SNESKSPGetUseEW - Gets if `SNES` is using Eisenstat-Walker method 544071f87433Sdalcinl for computing relative tolerance for linear solvers within an 544171f87433Sdalcinl inexact Newton method. 544271f87433Sdalcinl 544371f87433Sdalcinl Not Collective 544471f87433Sdalcinl 544571f87433Sdalcinl Input Parameter: 5446f6dfbefdSBarry Smith . snes - `SNES` context 544771f87433Sdalcinl 544871f87433Sdalcinl Output Parameter: 5449f6dfbefdSBarry Smith . flag - `PETSC_TRUE` or `PETSC_FALSE` 545071f87433Sdalcinl 545171f87433Sdalcinl Level: advanced 545271f87433Sdalcinl 54531cc06b55SBarry Smith .seealso: [](ch_snes), `SNESKSPSetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()` 545471f87433Sdalcinl @*/ 5455d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag) 5456d71ae5a4SJacob Faibussowitsch { 545771f87433Sdalcinl PetscFunctionBegin; 54580700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 54594f572ea9SToby Isaac PetscAssertPointer(flag, 2); 546071f87433Sdalcinl *flag = snes->ksp_ewconv; 54613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 546271f87433Sdalcinl } 546371f87433Sdalcinl 546471f87433Sdalcinl /*@ 5465fa9f3622SBarry Smith SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker 546671f87433Sdalcinl convergence criteria for the linear solvers within an inexact 546771f87433Sdalcinl Newton method. 546871f87433Sdalcinl 5469c3339decSBarry Smith Logically Collective 547071f87433Sdalcinl 547171f87433Sdalcinl Input Parameters: 5472f6dfbefdSBarry Smith + snes - `SNES` context 54730f0abf79SStefano Zampini . version - version 1, 2 (default is 2), 3 or 4 547471f87433Sdalcinl . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 547571f87433Sdalcinl . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 547671f87433Sdalcinl . gamma - multiplicative factor for version 2 rtol computation 547771f87433Sdalcinl (0 <= gamma2 <= 1) 547871f87433Sdalcinl . alpha - power for version 2 rtol computation (1 < alpha <= 2) 547971f87433Sdalcinl . alpha2 - power for safeguard 548071f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1) 548171f87433Sdalcinl 5482dc4c0fb0SBarry Smith Level: advanced 5483dc4c0fb0SBarry Smith 5484f6dfbefdSBarry Smith Notes: 548571f87433Sdalcinl Version 3 was contributed by Luis Chacon, June 2006. 548671f87433Sdalcinl 548777e5a1f9SBarry Smith Use `PETSC_CURRENT` to retain the default for any of the parameters. 548871f87433Sdalcinl 54891cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()` 549071f87433Sdalcinl @*/ 5491d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetParametersEW(SNES snes, PetscInt version, PetscReal rtol_0, PetscReal rtol_max, PetscReal gamma, PetscReal alpha, PetscReal alpha2, PetscReal threshold) 5492d71ae5a4SJacob Faibussowitsch { 5493fa9f3622SBarry Smith SNESKSPEW *kctx; 54945fd66863SKarl Rupp 549571f87433Sdalcinl PetscFunctionBegin; 54960700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5497fa9f3622SBarry Smith kctx = (SNESKSPEW *)snes->kspconvctx; 54985f80ce2aSJacob Faibussowitsch PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing"); 5499c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, version, 2); 5500c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, rtol_0, 3); 5501c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, rtol_max, 4); 5502c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, gamma, 5); 5503c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, alpha, 6); 5504c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, alpha2, 7); 5505c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, threshold, 8); 550671f87433Sdalcinl 550777e5a1f9SBarry Smith if (version != PETSC_CURRENT) kctx->version = version; 550877e5a1f9SBarry Smith if (rtol_0 != (PetscReal)PETSC_CURRENT) kctx->rtol_0 = rtol_0; 550977e5a1f9SBarry Smith if (rtol_max != (PetscReal)PETSC_CURRENT) kctx->rtol_max = rtol_max; 551077e5a1f9SBarry Smith if (gamma != (PetscReal)PETSC_CURRENT) kctx->gamma = gamma; 551177e5a1f9SBarry Smith if (alpha != (PetscReal)PETSC_CURRENT) kctx->alpha = alpha; 551277e5a1f9SBarry Smith if (alpha2 != (PetscReal)PETSC_CURRENT) kctx->alpha2 = alpha2; 551377e5a1f9SBarry Smith if (threshold != (PetscReal)PETSC_CURRENT) kctx->threshold = threshold; 551471f87433Sdalcinl 55150f0abf79SStefano 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); 55160b121fc5SBarry 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); 55170b121fc5SBarry 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); 55180b121fc5SBarry 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); 55190b121fc5SBarry 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); 55200b121fc5SBarry 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); 55213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 552271f87433Sdalcinl } 552371f87433Sdalcinl 552471f87433Sdalcinl /*@ 5525fa9f3622SBarry Smith SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker 552671f87433Sdalcinl convergence criteria for the linear solvers within an inexact 552771f87433Sdalcinl Newton method. 552871f87433Sdalcinl 552971f87433Sdalcinl Not Collective 553071f87433Sdalcinl 553197bb3fdcSJose E. Roman Input Parameter: 5532f6dfbefdSBarry Smith . snes - `SNES` context 553371f87433Sdalcinl 553471f87433Sdalcinl Output Parameters: 55350f0abf79SStefano Zampini + version - version 1, 2 (default is 2), 3 or 4 553671f87433Sdalcinl . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 553771f87433Sdalcinl . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 5538bf388a1fSBarry Smith . gamma - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1) 553971f87433Sdalcinl . alpha - power for version 2 rtol computation (1 < alpha <= 2) 554071f87433Sdalcinl . alpha2 - power for safeguard 554171f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1) 554271f87433Sdalcinl 554371f87433Sdalcinl Level: advanced 554471f87433Sdalcinl 55451cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPSetParametersEW()` 554671f87433Sdalcinl @*/ 5547d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetParametersEW(SNES snes, PetscInt *version, PetscReal *rtol_0, PetscReal *rtol_max, PetscReal *gamma, PetscReal *alpha, PetscReal *alpha2, PetscReal *threshold) 5548d71ae5a4SJacob Faibussowitsch { 5549fa9f3622SBarry Smith SNESKSPEW *kctx; 55505fd66863SKarl Rupp 555171f87433Sdalcinl PetscFunctionBegin; 55520700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5553fa9f3622SBarry Smith kctx = (SNESKSPEW *)snes->kspconvctx; 55545f80ce2aSJacob Faibussowitsch PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing"); 555571f87433Sdalcinl if (version) *version = kctx->version; 555671f87433Sdalcinl if (rtol_0) *rtol_0 = kctx->rtol_0; 555771f87433Sdalcinl if (rtol_max) *rtol_max = kctx->rtol_max; 555871f87433Sdalcinl if (gamma) *gamma = kctx->gamma; 555971f87433Sdalcinl if (alpha) *alpha = kctx->alpha; 556071f87433Sdalcinl if (alpha2) *alpha2 = kctx->alpha2; 556171f87433Sdalcinl if (threshold) *threshold = kctx->threshold; 55623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 556371f87433Sdalcinl } 556471f87433Sdalcinl 55652a8381b2SBarry Smith PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, PetscCtx ctx) 5566d71ae5a4SJacob Faibussowitsch { 55675c0db29aSPierre Jolivet SNES snes = (SNES)ctx; 5568fa9f3622SBarry Smith SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx; 556977e5a1f9SBarry Smith PetscReal rtol = PETSC_CURRENT, stol; 557071f87433Sdalcinl 557171f87433Sdalcinl PetscFunctionBegin; 55723ba16761SJacob Faibussowitsch if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS); 557330058271SDmitry Karpeev if (!snes->iter) { 557430058271SDmitry Karpeev rtol = kctx->rtol_0; /* first time in, so use the original user rtol */ 55759566063dSJacob Faibussowitsch PetscCall(VecNorm(snes->vec_func, NORM_2, &kctx->norm_first)); 55760f0abf79SStefano Zampini } else { 55770fdf79fbSJacob 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); 557871f87433Sdalcinl if (kctx->version == 1) { 55790f0abf79SStefano Zampini rtol = PetscAbsReal(snes->norm - kctx->lresid_last) / kctx->norm_last; 558085ec1a3cSBarry Smith stol = PetscPowReal(kctx->rtol_last, kctx->alpha2); 558171f87433Sdalcinl if (stol > kctx->threshold) rtol = PetscMax(rtol, stol); 558271f87433Sdalcinl } else if (kctx->version == 2) { 558385ec1a3cSBarry Smith rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha); 558485ec1a3cSBarry Smith stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha); 558571f87433Sdalcinl if (stol > kctx->threshold) rtol = PetscMax(rtol, stol); 558671f87433Sdalcinl } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */ 558785ec1a3cSBarry Smith rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha); 558871f87433Sdalcinl /* safeguard: avoid sharp decrease of rtol */ 558985ec1a3cSBarry Smith stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha); 559071f87433Sdalcinl stol = PetscMax(rtol, stol); 559171f87433Sdalcinl rtol = PetscMin(kctx->rtol_0, stol); 559271f87433Sdalcinl /* safeguard: avoid oversolving */ 559330058271SDmitry Karpeev stol = kctx->gamma * (kctx->norm_first * snes->rtol) / snes->norm; 559471f87433Sdalcinl stol = PetscMax(rtol, stol); 559571f87433Sdalcinl rtol = PetscMin(kctx->rtol_0, stol); 55960fdf79fbSJacob Faibussowitsch } else /* if (kctx->version == 4) */ { 55970fdf79fbSJacob Faibussowitsch /* H.-B. An et al. Journal of Computational and Applied Mathematics 200 (2007) 47-60 */ 55980f0abf79SStefano Zampini PetscReal ared = PetscAbsReal(kctx->norm_last - snes->norm); 55990f0abf79SStefano Zampini PetscReal pred = PetscAbsReal(kctx->norm_last - kctx->lresid_last); 56000f0abf79SStefano Zampini PetscReal rk = ared / pred; 56010f0abf79SStefano Zampini if (rk < kctx->v4_p1) rtol = 1. - 2. * kctx->v4_p1; 56020f0abf79SStefano Zampini else if (rk < kctx->v4_p2) rtol = kctx->rtol_last; 56030f0abf79SStefano Zampini else if (rk < kctx->v4_p3) rtol = kctx->v4_m1 * kctx->rtol_last; 56040f0abf79SStefano Zampini else rtol = kctx->v4_m2 * kctx->rtol_last; 56050f0abf79SStefano Zampini 5606a4598233SStefano 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; 56070f0abf79SStefano Zampini kctx->rtol_last_2 = kctx->rtol_last; 56080f0abf79SStefano Zampini kctx->rk_last_2 = kctx->rk_last; 56090f0abf79SStefano Zampini kctx->rk_last = rk; 56100fdf79fbSJacob Faibussowitsch } 56110f0abf79SStefano Zampini } 56120f0abf79SStefano Zampini /* safeguard: avoid rtol greater than rtol_max */ 561371f87433Sdalcinl rtol = PetscMin(rtol, kctx->rtol_max); 561477e5a1f9SBarry Smith PetscCall(KSPSetTolerances(ksp, rtol, PETSC_CURRENT, PETSC_CURRENT, PETSC_CURRENT)); 561563a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "iter %" PetscInt_FMT ", Eisenstat-Walker (version %" PetscInt_FMT ") KSP rtol=%g\n", snes->iter, kctx->version, (double)rtol)); 56163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 561771f87433Sdalcinl } 561871f87433Sdalcinl 56192a8381b2SBarry Smith PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, PetscCtx ctx) 5620d71ae5a4SJacob Faibussowitsch { 56215c0db29aSPierre Jolivet SNES snes = (SNES)ctx; 5622fa9f3622SBarry Smith SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx; 562371f87433Sdalcinl PCSide pcside; 562471f87433Sdalcinl Vec lres; 562571f87433Sdalcinl 562671f87433Sdalcinl PetscFunctionBegin; 56273ba16761SJacob Faibussowitsch if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS); 56289566063dSJacob Faibussowitsch PetscCall(KSPGetTolerances(ksp, &kctx->rtol_last, NULL, NULL, NULL)); 562971dbe336SPeter Brune kctx->norm_last = snes->norm; 56300f0abf79SStefano Zampini if (kctx->version == 1 || kctx->version == 4) { 56314f00ce20SMatthew G. Knepley PC pc; 56320f0abf79SStefano Zampini PetscBool getRes; 56334f00ce20SMatthew G. Knepley 56349566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksp, &pc)); 56350f0abf79SStefano Zampini PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &getRes)); 56360f0abf79SStefano Zampini if (!getRes) { 56370f0abf79SStefano Zampini KSPNormType normtype; 56380f0abf79SStefano Zampini 56390f0abf79SStefano Zampini PetscCall(KSPGetNormType(ksp, &normtype)); 56400f0abf79SStefano Zampini getRes = (PetscBool)(normtype == KSP_NORM_UNPRECONDITIONED); 56410f0abf79SStefano Zampini } 56429566063dSJacob Faibussowitsch PetscCall(KSPGetPCSide(ksp, &pcside)); 56430f0abf79SStefano Zampini if (pcside == PC_RIGHT || getRes) { /* KSP residual is true linear residual */ 56449566063dSJacob Faibussowitsch PetscCall(KSPGetResidualNorm(ksp, &kctx->lresid_last)); 564571f87433Sdalcinl } else { 564671f87433Sdalcinl /* KSP residual is preconditioned residual */ 564771f87433Sdalcinl /* compute true linear residual norm */ 56480f0abf79SStefano Zampini Mat J; 56490f0abf79SStefano Zampini PetscCall(KSPGetOperators(ksp, &J, NULL)); 56509566063dSJacob Faibussowitsch PetscCall(VecDuplicate(b, &lres)); 56510f0abf79SStefano Zampini PetscCall(MatMult(J, x, lres)); 56529566063dSJacob Faibussowitsch PetscCall(VecAYPX(lres, -1.0, b)); 56539566063dSJacob Faibussowitsch PetscCall(VecNorm(lres, NORM_2, &kctx->lresid_last)); 56549566063dSJacob Faibussowitsch PetscCall(VecDestroy(&lres)); 565571f87433Sdalcinl } 565671f87433Sdalcinl } 56573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 565871f87433Sdalcinl } 565971f87433Sdalcinl 5660d4211eb9SBarry Smith /*@ 5661f6dfbefdSBarry Smith SNESGetKSP - Returns the `KSP` context for a `SNES` solver. 5662d4211eb9SBarry Smith 5663420bcc1bSBarry Smith Not Collective, but if `snes` is parallel, then `ksp` is parallel 5664d4211eb9SBarry Smith 5665d4211eb9SBarry Smith Input Parameter: 5666f6dfbefdSBarry Smith . snes - the `SNES` context 5667d4211eb9SBarry Smith 5668d4211eb9SBarry Smith Output Parameter: 5669f6dfbefdSBarry Smith . ksp - the `KSP` context 5670d4211eb9SBarry Smith 5671dc4c0fb0SBarry Smith Level: beginner 5672dc4c0fb0SBarry Smith 5673d4211eb9SBarry Smith Notes: 5674f6dfbefdSBarry Smith The user can then directly manipulate the `KSP` context to set various 5675d4211eb9SBarry Smith options, etc. Likewise, the user can then extract and manipulate the 5676f6dfbefdSBarry Smith `PC` contexts as well. 5677f6dfbefdSBarry Smith 56780b4b7b1cSBarry 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. 5679d4211eb9SBarry Smith 56801cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSP`, `PC`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()` 5681d4211eb9SBarry Smith @*/ 5682d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetKSP(SNES snes, KSP *ksp) 5683d71ae5a4SJacob Faibussowitsch { 568471f87433Sdalcinl PetscFunctionBegin; 5685d4211eb9SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 56864f572ea9SToby Isaac PetscAssertPointer(ksp, 2); 5687d4211eb9SBarry Smith 5688d4211eb9SBarry Smith if (!snes->ksp) { 56899566063dSJacob Faibussowitsch PetscCall(KSPCreate(PetscObjectComm((PetscObject)snes), &snes->ksp)); 56909566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->ksp, (PetscObject)snes, 1)); 5691d4211eb9SBarry Smith 56925c0db29aSPierre Jolivet PetscCall(KSPSetPreSolve(snes->ksp, KSPPreSolve_SNESEW, snes)); 56935c0db29aSPierre Jolivet PetscCall(KSPSetPostSolve(snes->ksp, KSPPostSolve_SNESEW, snes)); 5694a5c2985bSBarry Smith 56959566063dSJacob Faibussowitsch PetscCall(KSPMonitorSetFromOptions(snes->ksp, "-snes_monitor_ksp", "snes_preconditioned_residual", snes)); 56969566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptions((PetscObject)snes->ksp, ((PetscObject)snes)->options)); 5697d4211eb9SBarry Smith } 5698d4211eb9SBarry Smith *ksp = snes->ksp; 56993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 570071f87433Sdalcinl } 57016c699258SBarry Smith 5702af0996ceSBarry Smith #include <petsc/private/dmimpl.h> 57036c699258SBarry Smith /*@ 57040b4b7b1cSBarry Smith SNESSetDM - Sets the `DM` that may be used by some `SNES` nonlinear solvers or their underlying preconditioners 57056c699258SBarry Smith 5706c3339decSBarry Smith Logically Collective 57076c699258SBarry Smith 57086c699258SBarry Smith Input Parameters: 57092a808120SBarry Smith + snes - the nonlinear solver context 5710420bcc1bSBarry Smith - dm - the `DM`, cannot be `NULL` 5711dc4c0fb0SBarry Smith 5712dc4c0fb0SBarry Smith Level: intermediate 57136c699258SBarry Smith 5714f6dfbefdSBarry Smith Note: 5715f6dfbefdSBarry Smith A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`, 5716f6dfbefdSBarry Smith even when not using interfaces like `DMSNESSetFunction()`. Use `DMClone()` to get a distinct `DM` when solving different 5717e03a659cSJed Brown problems using the same function space. 5718e03a659cSJed Brown 5719420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()` 57206c699258SBarry Smith @*/ 5721d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDM(SNES snes, DM dm) 5722d71ae5a4SJacob Faibussowitsch { 5723345fed2cSBarry Smith KSP ksp; 5724942e3340SBarry Smith DMSNES sdm; 57256c699258SBarry Smith 57266c699258SBarry Smith PetscFunctionBegin; 57270700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 57282a808120SBarry Smith PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 57299566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 5730942e3340SBarry Smith if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */ 573151f4b3c7SToby Isaac if (snes->dm->dmsnes && !dm->dmsnes) { 57329566063dSJacob Faibussowitsch PetscCall(DMCopyDMSNES(snes->dm, dm)); 57339566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(snes->dm, &sdm)); 5734f5af7f23SKarl Rupp if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */ 57356cab3a1bSJed Brown } 57369566063dSJacob Faibussowitsch PetscCall(DMCoarsenHookRemove(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes)); 57379566063dSJacob Faibussowitsch PetscCall(DMDestroy(&snes->dm)); 57386cab3a1bSJed Brown } 57396c699258SBarry Smith snes->dm = dm; 5740116d1032SJed Brown snes->dmAuto = PETSC_FALSE; 5741f5af7f23SKarl Rupp 57429566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 57439566063dSJacob Faibussowitsch PetscCall(KSPSetDM(ksp, dm)); 5744*bf0c7fc2SBarry Smith PetscCall(KSPSetDMActive(ksp, KSP_DMACTIVE_ALL, PETSC_FALSE)); 5745efd4aadfSBarry Smith if (snes->npc) { 57469566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes->npc, snes->dm)); 57479566063dSJacob Faibussowitsch PetscCall(SNESSetNPCSide(snes, snes->npcside)); 57482c155ee1SBarry Smith } 57493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 57506c699258SBarry Smith } 57516c699258SBarry Smith 57526c699258SBarry Smith /*@ 57530b4b7b1cSBarry Smith SNESGetDM - Gets the `DM` that may be used by some `SNES` nonlinear solvers/preconditioners 57546c699258SBarry Smith 57550b4b7b1cSBarry Smith Not Collective but `dm` obtained is parallel on `snes` 57566c699258SBarry Smith 57576c699258SBarry Smith Input Parameter: 5758420bcc1bSBarry Smith . snes - the `SNES` context 57596c699258SBarry Smith 57606c699258SBarry Smith Output Parameter: 5761420bcc1bSBarry Smith . dm - the `DM` 57626c699258SBarry Smith 57636c699258SBarry Smith Level: intermediate 57646c699258SBarry Smith 5765420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESSetDM()`, `KSPSetDM()`, `KSPGetDM()` 57666c699258SBarry Smith @*/ 5767d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDM(SNES snes, DM *dm) 5768d71ae5a4SJacob Faibussowitsch { 57696c699258SBarry Smith PetscFunctionBegin; 57700700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 57716cab3a1bSJed Brown if (!snes->dm) { 57729566063dSJacob Faibussowitsch PetscCall(DMShellCreate(PetscObjectComm((PetscObject)snes), &snes->dm)); 5773116d1032SJed Brown snes->dmAuto = PETSC_TRUE; 57746cab3a1bSJed Brown } 57756c699258SBarry Smith *dm = snes->dm; 57763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 57776c699258SBarry Smith } 57780807856dSBarry Smith 577931823bd8SMatthew G Knepley /*@ 5780be95d8f1SBarry Smith SNESSetNPC - Sets the nonlinear preconditioner to be used. 578131823bd8SMatthew G Knepley 5782c3339decSBarry Smith Collective 578331823bd8SMatthew G Knepley 578431823bd8SMatthew G Knepley Input Parameters: 5785f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 578662842358SBarry Smith - npc - the `SNES` nonlinear preconditioner object 578762842358SBarry Smith 578862842358SBarry Smith Options Database Key: 578962842358SBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner 579031823bd8SMatthew G Knepley 5791dc4c0fb0SBarry Smith Level: developer 5792dc4c0fb0SBarry Smith 579331823bd8SMatthew G Knepley Notes: 579462842358SBarry Smith This is rarely used, rather use `SNESGetNPC()` to retrieve the preconditioner and configure it using the API. 579531823bd8SMatthew G Knepley 5796f6dfbefdSBarry Smith Only some `SNESType` can use a nonlinear preconditioner 5797f6dfbefdSBarry Smith 5798420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNGS`, `SNESFAS`, `SNESGetNPC()`, `SNESHasNPC()` 579931823bd8SMatthew G Knepley @*/ 5800d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPC(SNES snes, SNES npc) 5801d71ae5a4SJacob Faibussowitsch { 580231823bd8SMatthew G Knepley PetscFunctionBegin; 580331823bd8SMatthew G Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5804f6dfbefdSBarry Smith PetscValidHeaderSpecific(npc, SNES_CLASSID, 2); 5805f6dfbefdSBarry Smith PetscCheckSameComm(snes, 1, npc, 2); 5806f6dfbefdSBarry Smith PetscCall(PetscObjectReference((PetscObject)npc)); 58079566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&snes->npc)); 5808f6dfbefdSBarry Smith snes->npc = npc; 58093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 581031823bd8SMatthew G Knepley } 581131823bd8SMatthew G Knepley 581231823bd8SMatthew G Knepley /*@ 5813f6dfbefdSBarry Smith SNESGetNPC - Gets a nonlinear preconditioning solver SNES` to be used to precondition the original nonlinear solver. 581431823bd8SMatthew G Knepley 58150b4b7b1cSBarry Smith Not Collective; but any changes to the obtained the `pc` object must be applied collectively 581631823bd8SMatthew G Knepley 581731823bd8SMatthew G Knepley Input Parameter: 5818f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 581931823bd8SMatthew G Knepley 582031823bd8SMatthew G Knepley Output Parameter: 582162842358SBarry Smith . pc - the `SNES` preconditioner context 582231823bd8SMatthew G Knepley 5823f6dfbefdSBarry Smith Options Database Key: 5824f6dfbefdSBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner 5825b5badacbSBarry Smith 58260b4b7b1cSBarry Smith Level: advanced 5827dc4c0fb0SBarry Smith 582895452b02SPatrick Sanan Notes: 58290b4b7b1cSBarry Smith If a `SNES` was previously set with `SNESSetNPC()` then that value is returned, otherwise a new `SNES` object is created that will 58300b4b7b1cSBarry Smith be used as the nonlinear preconditioner for the current `SNES`. 5831be95d8f1SBarry Smith 5832f6dfbefdSBarry Smith The (preconditioner) `SNES` returned automatically inherits the same nonlinear function and Jacobian supplied to the original 583362842358SBarry Smith `SNES`. These may be overwritten if needed. 583462842358SBarry Smith 583562842358SBarry Smith Use the options database prefixes `-npc_snes`, `-npc_ksp`, etc., to control the configuration of the nonlinear preconditioner 5836951fe5abSBarry Smith 58371cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESHasNPC()`, `SNES`, `SNESCreate()` 583831823bd8SMatthew G Knepley @*/ 5839d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPC(SNES snes, SNES *pc) 5840d71ae5a4SJacob Faibussowitsch { 5841a64e098fSPeter Brune const char *optionsprefix; 584231823bd8SMatthew G Knepley 584331823bd8SMatthew G Knepley PetscFunctionBegin; 584431823bd8SMatthew G Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 58454f572ea9SToby Isaac PetscAssertPointer(pc, 2); 5846efd4aadfSBarry Smith if (!snes->npc) { 58472a8381b2SBarry Smith PetscCtx ctx; 5848ec785e5bSStefano Zampini 58499566063dSJacob Faibussowitsch PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &snes->npc)); 58509566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->npc, (PetscObject)snes, 1)); 58519566063dSJacob Faibussowitsch PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 58529566063dSJacob Faibussowitsch PetscCall(SNESSetOptionsPrefix(snes->npc, optionsprefix)); 58539566063dSJacob Faibussowitsch PetscCall(SNESAppendOptionsPrefix(snes->npc, "npc_")); 58542a8381b2SBarry Smith if (snes->ops->ctxcompute) { 58552a8381b2SBarry Smith PetscCall(SNESSetComputeApplicationContext(snes, snes->ops->ctxcompute, snes->ops->ctxdestroy)); 5856fb87a551SStefano Zampini } else { 5857ec785e5bSStefano Zampini PetscCall(SNESGetApplicationContext(snes, &ctx)); 5858ec785e5bSStefano Zampini PetscCall(SNESSetApplicationContext(snes->npc, ctx)); 5859fb87a551SStefano Zampini } 58609566063dSJacob Faibussowitsch PetscCall(SNESSetCountersReset(snes->npc, PETSC_FALSE)); 586131823bd8SMatthew G Knepley } 5862efd4aadfSBarry Smith *pc = snes->npc; 58633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 586431823bd8SMatthew G Knepley } 586531823bd8SMatthew G Knepley 58663ad1a0b9SPatrick Farrell /*@ 58670b4b7b1cSBarry Smith SNESHasNPC - Returns whether a nonlinear preconditioner is associated with the given `SNES` 58683ad1a0b9SPatrick Farrell 58693ad1a0b9SPatrick Farrell Not Collective 58703ad1a0b9SPatrick Farrell 58713ad1a0b9SPatrick Farrell Input Parameter: 5872f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 58733ad1a0b9SPatrick Farrell 58743ad1a0b9SPatrick Farrell Output Parameter: 5875420bcc1bSBarry Smith . has_npc - whether the `SNES` has a nonlinear preconditioner or not 58763ad1a0b9SPatrick Farrell 58773ad1a0b9SPatrick Farrell Level: developer 58783ad1a0b9SPatrick Farrell 58791cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESGetNPC()` 58803ad1a0b9SPatrick Farrell @*/ 5881d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc) 5882d71ae5a4SJacob Faibussowitsch { 58833ad1a0b9SPatrick Farrell PetscFunctionBegin; 58843ad1a0b9SPatrick Farrell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5885835f2295SStefano Zampini PetscAssertPointer(has_npc, 2); 5886835f2295SStefano Zampini *has_npc = snes->npc ? PETSC_TRUE : PETSC_FALSE; 58873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 58883ad1a0b9SPatrick Farrell } 58893ad1a0b9SPatrick Farrell 5890c40d0f55SPeter Brune /*@ 589162842358SBarry Smith SNESSetNPCSide - Sets the nonlinear preconditioning side used by the nonlinear preconditioner inside `SNES`. 5892c40d0f55SPeter Brune 5893c3339decSBarry Smith Logically Collective 5894c40d0f55SPeter Brune 5895c40d0f55SPeter Brune Input Parameter: 5896f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 5897c40d0f55SPeter Brune 5898c40d0f55SPeter Brune Output Parameter: 5899c40d0f55SPeter Brune . side - the preconditioning side, where side is one of 5900c40d0f55SPeter Brune .vb 59012d547940SBarry Smith PC_LEFT - left preconditioning 59022d547940SBarry Smith PC_RIGHT - right preconditioning (default for most nonlinear solvers) 5903c40d0f55SPeter Brune .ve 5904c40d0f55SPeter Brune 5905f6dfbefdSBarry Smith Options Database Key: 590667b8a455SSatish Balay . -snes_npc_side <right,left> - nonlinear preconditioner side 5907c40d0f55SPeter Brune 5908dc4c0fb0SBarry Smith Level: intermediate 5909dc4c0fb0SBarry Smith 5910f6dfbefdSBarry Smith Note: 5911f6dfbefdSBarry Smith `SNESNRICHARDSON` and `SNESNCG` only support left preconditioning. 59122d547940SBarry Smith 591362842358SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNPC()`, `SNESNRICHARDSON`, `SNESNCG`, `SNESType`, `SNESGetNPCSide()`, `KSPSetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide` 5914c40d0f55SPeter Brune @*/ 5915d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPCSide(SNES snes, PCSide side) 5916d71ae5a4SJacob Faibussowitsch { 5917c40d0f55SPeter Brune PetscFunctionBegin; 5918c40d0f55SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5919c40d0f55SPeter Brune PetscValidLogicalCollectiveEnum(snes, side, 2); 5920b552625fSStefano Zampini if (side == PC_SIDE_DEFAULT) side = PC_RIGHT; 592154c59aa7SJacob Faibussowitsch PetscCheck((side == PC_LEFT) || (side == PC_RIGHT), PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Only PC_LEFT and PC_RIGHT are supported"); 5922efd4aadfSBarry Smith snes->npcside = side; 59233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5924c40d0f55SPeter Brune } 5925c40d0f55SPeter Brune 5926c40d0f55SPeter Brune /*@ 592762842358SBarry Smith SNESGetNPCSide - Gets the preconditioning side used by the nonlinear preconditioner inside `SNES`. 5928c40d0f55SPeter Brune 5929c40d0f55SPeter Brune Not Collective 5930c40d0f55SPeter Brune 5931c40d0f55SPeter Brune Input Parameter: 5932f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 5933c40d0f55SPeter Brune 5934c40d0f55SPeter Brune Output Parameter: 5935c40d0f55SPeter Brune . side - the preconditioning side, where side is one of 5936c40d0f55SPeter Brune .vb 5937f6dfbefdSBarry Smith `PC_LEFT` - left preconditioning 5938f6dfbefdSBarry Smith `PC_RIGHT` - right preconditioning (default for most nonlinear solvers) 5939c40d0f55SPeter Brune .ve 5940c40d0f55SPeter Brune 5941c40d0f55SPeter Brune Level: intermediate 5942c40d0f55SPeter Brune 594362842358SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNPC()`, `SNESSetNPCSide()`, `KSPGetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide` 5944c40d0f55SPeter Brune @*/ 5945d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPCSide(SNES snes, PCSide *side) 5946d71ae5a4SJacob Faibussowitsch { 5947c40d0f55SPeter Brune PetscFunctionBegin; 5948c40d0f55SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 59494f572ea9SToby Isaac PetscAssertPointer(side, 2); 5950efd4aadfSBarry Smith *side = snes->npcside; 59513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5952c40d0f55SPeter Brune } 5953c40d0f55SPeter Brune 59549e764e56SPeter Brune /*@ 59550b4b7b1cSBarry Smith SNESSetLineSearch - Sets the `SNESLineSearch` to be used for a given `SNES` 59569e764e56SPeter Brune 5957c3339decSBarry Smith Collective 59589e764e56SPeter Brune 59599e764e56SPeter Brune Input Parameters: 5960f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 59619e764e56SPeter Brune - linesearch - the linesearch object 59629e764e56SPeter Brune 5963dc4c0fb0SBarry Smith Level: developer 5964dc4c0fb0SBarry Smith 5965f6dfbefdSBarry Smith Note: 5966420bcc1bSBarry Smith This is almost never used, rather one uses `SNESGetLineSearch()` to retrieve the line search and set options on it 59679e764e56SPeter Brune to configure it using the API). 59689e764e56SPeter Brune 5969420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()` 59709e764e56SPeter Brune @*/ 5971d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch) 5972d71ae5a4SJacob Faibussowitsch { 59739e764e56SPeter Brune PetscFunctionBegin; 59749e764e56SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5975f1c6b773SPeter Brune PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 2); 59769e764e56SPeter Brune PetscCheckSameComm(snes, 1, linesearch, 2); 59779566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)linesearch)); 59789566063dSJacob Faibussowitsch PetscCall(SNESLineSearchDestroy(&snes->linesearch)); 5979f5af7f23SKarl Rupp 59809e764e56SPeter Brune snes->linesearch = linesearch; 59813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 59829e764e56SPeter Brune } 5983