1af0996ceSBarry Smith #include <petsc/private/snesimpl.h> /*I "petscsnes.h" I*/ 207475bc1SBarry Smith #include <petscdmshell.h> 3d96771aaSLisandro Dalcin #include <petscdraw.h> 4a01aa210SMatthew G. Knepley #include <petscds.h> 534b4d3a8SMatthew G. Knepley #include <petscdmadaptor.h> 606fc46c8SMatthew G. Knepley #include <petscconvest.h> 79b94acceSBarry Smith 8ace3abfcSBarry Smith PetscBool SNESRegisterAllCalled = PETSC_FALSE; 90298fd71SBarry Smith PetscFunctionList SNESList = NULL; 108ba1e511SMatthew Knepley 118ba1e511SMatthew Knepley /* Logging support */ 1222c6f798SBarry Smith PetscClassId SNES_CLASSID, DMSNES_CLASSID; 1397276fddSZach Atkins PetscLogEvent SNES_Solve, SNES_SetUp, SNES_FunctionEval, SNES_JacobianEval, SNES_NGSEval, SNES_NGSFuncEval, SNES_NewtonALEval, SNES_NPCSolve, SNES_ObjectiveEval; 14a09944afSBarry Smith 15e113a28aSBarry Smith /*@ 16dc4c0fb0SBarry Smith SNESSetErrorIfNotConverged - Causes `SNESSolve()` to generate an error immediately if the solver has not converged. 17e113a28aSBarry Smith 18c3339decSBarry Smith Logically Collective 19e113a28aSBarry Smith 20e113a28aSBarry Smith Input Parameters: 21f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 22f6dfbefdSBarry Smith - flg - `PETSC_TRUE` indicates you want the error generated 23e113a28aSBarry Smith 2420f4b53cSBarry Smith Options Database Key: 2567b8a455SSatish Balay . -snes_error_if_not_converged <true,false> - cause an immediate error condition and stop the program if the solver does not converge 26e113a28aSBarry Smith 27e113a28aSBarry Smith Level: intermediate 28e113a28aSBarry Smith 29f6dfbefdSBarry Smith Note: 30f6dfbefdSBarry Smith Normally PETSc continues if a solver fails to converge, you can call `SNESGetConvergedReason()` after a `SNESSolve()` 31f6dfbefdSBarry Smith to determine if it has converged. Otherwise the solution may be inaccurate or wrong 32e113a28aSBarry Smith 331cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetErrorIfNotConverged()`, `KSPGetErrorIfNotConverged()`, `KSPSetErrorIfNotConverged()` 34e113a28aSBarry Smith @*/ 35d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetErrorIfNotConverged(SNES snes, PetscBool flg) 36d71ae5a4SJacob Faibussowitsch { 37e113a28aSBarry Smith PetscFunctionBegin; 38e113a28aSBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 39acfcf0e5SJed Brown PetscValidLogicalCollectiveBool(snes, flg, 2); 40e113a28aSBarry Smith snes->errorifnotconverged = flg; 413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 42e113a28aSBarry Smith } 43e113a28aSBarry Smith 44e113a28aSBarry Smith /*@ 45f6dfbefdSBarry Smith SNESGetErrorIfNotConverged - Indicates if `SNESSolve()` will generate an error if the solver does not converge? 46e113a28aSBarry Smith 47e113a28aSBarry Smith Not Collective 48e113a28aSBarry Smith 49e113a28aSBarry Smith Input Parameter: 50f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 51e113a28aSBarry Smith 52e113a28aSBarry Smith Output Parameter: 53f6dfbefdSBarry Smith . flag - `PETSC_TRUE` if it will generate an error, else `PETSC_FALSE` 54e113a28aSBarry Smith 55e113a28aSBarry Smith Level: intermediate 56e113a28aSBarry Smith 571cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetErrorIfNotConverged()`, `KSPGetErrorIfNotConverged()`, `KSPSetErrorIfNotConverged()` 58e113a28aSBarry Smith @*/ 59d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetErrorIfNotConverged(SNES snes, PetscBool *flag) 60d71ae5a4SJacob Faibussowitsch { 61e113a28aSBarry Smith PetscFunctionBegin; 62e113a28aSBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 634f572ea9SToby Isaac PetscAssertPointer(flag, 2); 64e113a28aSBarry Smith *flag = snes->errorifnotconverged; 653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 66e113a28aSBarry Smith } 67e113a28aSBarry Smith 684fc747eaSLawrence Mitchell /*@ 69dc4c0fb0SBarry Smith SNESSetAlwaysComputesFinalResidual - tells the `SNES` to always compute the residual (nonlinear function value) at the final solution 704fc747eaSLawrence Mitchell 71c3339decSBarry Smith Logically Collective 724fc747eaSLawrence Mitchell 734fc747eaSLawrence Mitchell Input Parameters: 74f6dfbefdSBarry Smith + snes - the shell `SNES` 75f6dfbefdSBarry Smith - flg - `PETSC_TRUE` to always compute the residual 764fc747eaSLawrence Mitchell 774fc747eaSLawrence Mitchell Level: advanced 784fc747eaSLawrence Mitchell 79f6dfbefdSBarry Smith Note: 80f6dfbefdSBarry Smith Some solvers (such as smoothers in a `SNESFAS`) do not need the residual computed at the final solution so skip computing it 81f6dfbefdSBarry Smith to save time. 82f6dfbefdSBarry Smith 83420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSolve()`, `SNESGetAlwaysComputesFinalResidual()` 844fc747eaSLawrence Mitchell @*/ 85d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetAlwaysComputesFinalResidual(SNES snes, PetscBool flg) 86d71ae5a4SJacob Faibussowitsch { 874fc747eaSLawrence Mitchell PetscFunctionBegin; 884fc747eaSLawrence Mitchell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 894fc747eaSLawrence Mitchell snes->alwayscomputesfinalresidual = flg; 903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 914fc747eaSLawrence Mitchell } 924fc747eaSLawrence Mitchell 934fc747eaSLawrence Mitchell /*@ 94f6dfbefdSBarry Smith SNESGetAlwaysComputesFinalResidual - checks if the `SNES` always computes the residual at the final solution 954fc747eaSLawrence Mitchell 96c3339decSBarry Smith Logically Collective 974fc747eaSLawrence Mitchell 984fc747eaSLawrence Mitchell Input Parameter: 99f6dfbefdSBarry Smith . snes - the `SNES` context 1004fc747eaSLawrence Mitchell 1014fc747eaSLawrence Mitchell Output Parameter: 102f6dfbefdSBarry Smith . flg - `PETSC_TRUE` if the residual is computed 1034fc747eaSLawrence Mitchell 1044fc747eaSLawrence Mitchell Level: advanced 1054fc747eaSLawrence Mitchell 106420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSolve()`, `SNESSetAlwaysComputesFinalResidual()` 1074fc747eaSLawrence Mitchell @*/ 108d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetAlwaysComputesFinalResidual(SNES snes, PetscBool *flg) 109d71ae5a4SJacob Faibussowitsch { 1104fc747eaSLawrence Mitchell PetscFunctionBegin; 1114fc747eaSLawrence Mitchell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1124fc747eaSLawrence Mitchell *flg = snes->alwayscomputesfinalresidual; 1133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1144fc747eaSLawrence Mitchell } 1154fc747eaSLawrence Mitchell 116e725d27bSBarry Smith /*@ 117f6dfbefdSBarry Smith SNESSetFunctionDomainError - tells `SNES` that the input vector, a proposed new solution, to your function you provided to `SNESSetFunction()` is not 118f0b84518SBarry Smith in the functions domain. For example, a step with negative pressure. 1194936397dSBarry Smith 1206b1535e8SBarry Smith Not Collective 1214936397dSBarry Smith 1222fe279fdSBarry Smith Input Parameter: 123f6dfbefdSBarry Smith . snes - the `SNES` context 1244936397dSBarry Smith 12528529972SSatish Balay Level: advanced 1264936397dSBarry Smith 127ced0f3aeSBarry Smith Notes: 1286b1535e8SBarry Smith This does not need to be called by all processes in the `SNES` MPI communicator. 1296b1535e8SBarry Smith 130ced0f3aeSBarry Smith If this is called the `SNESSolve()` stops iterating and returns with a `SNESConvergedReason` of `SNES_DIVERGED_FUNCTION_DOMAIN` 131ced0f3aeSBarry Smith 132ced0f3aeSBarry Smith You should always call `SNESGetConvergedReason()` after each `SNESSolve()` and verify if the iteration converged (positive result) or diverged (negative result). 133ced0f3aeSBarry Smith 134f0b84518SBarry Smith You can direct `SNES` to avoid certain steps by using `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()` or 135f0b84518SBarry Smith `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()` 136f0b84518SBarry Smith 1376b1535e8SBarry Smith You can call `SNESSetJacobianDomainError()` during a Jacobian computation to indicate the proposed solution is not in the domain. 1386b1535e8SBarry Smith 1396b1535e8SBarry Smith Developer Note: 1406b1535e8SBarry Smith This value is used by `SNESCheckFunctionNorm()` to determine if the `SNESConvergedReason` is set to `SNES_DIVERGED_FUNCTION_DOMAIN` 1416b1535e8SBarry Smith 1428434afd1SBarry Smith .seealso: [](ch_snes), `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetJacobianDomainError()`, `SNESVISetVariableBounds()`, 1436b1535e8SBarry Smith `SNESVISetComputeVariableBounds()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, 1446b1535e8SBarry Smith `SNES_DIVERGED_FUNCTION_DOMAIN` 1454936397dSBarry Smith @*/ 146d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionDomainError(SNES snes) 147d71ae5a4SJacob Faibussowitsch { 1484936397dSBarry Smith PetscFunctionBegin; 1490700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1504936397dSBarry Smith snes->domainerror = PETSC_TRUE; 1513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1524936397dSBarry Smith } 1534936397dSBarry Smith 1546a388c36SPeter Brune /*@ 155f6dfbefdSBarry Smith SNESSetJacobianDomainError - tells `SNES` that the function you provided to `SNESSetJacobian()` at the proposed step. For example there is a negative element transformation. 15607b62357SFande Kong 157c3339decSBarry Smith Logically Collective 15807b62357SFande Kong 1592fe279fdSBarry Smith Input Parameter: 160f6dfbefdSBarry Smith . snes - the `SNES` context 16107b62357SFande Kong 16207b62357SFande Kong Level: advanced 16307b62357SFande Kong 164ced0f3aeSBarry Smith Notes: 165ced0f3aeSBarry Smith If this is called the `SNESSolve()` stops iterating and returns with a `SNESConvergedReason` of `SNES_DIVERGED_FUNCTION_DOMAIN` 166ced0f3aeSBarry Smith 167ced0f3aeSBarry Smith You should always call `SNESGetConvergedReason()` after each `SNESSolve()` and verify if the iteration converged (positive result) or diverged (negative result). 168ced0f3aeSBarry Smith 169f0b84518SBarry Smith You can direct `SNES` to avoid certain steps by using `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()` or 170f0b84518SBarry Smith `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()` 171f0b84518SBarry Smith 1728434afd1SBarry Smith .seealso: [](ch_snes), `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetFunctionDomainError()`, `SNESVISetVariableBounds()`, 173ced0f3aeSBarry Smith `SNESVISetComputeVariableBounds()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESConvergedReason`, `SNESGetConvergedReason()` 17407b62357SFande Kong @*/ 175d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetJacobianDomainError(SNES snes) 176d71ae5a4SJacob Faibussowitsch { 17707b62357SFande Kong PetscFunctionBegin; 17807b62357SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1795f80ce2aSJacob Faibussowitsch PetscCheck(!snes->errorifnotconverged, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "User code indicates computeJacobian does not make sense"); 18007b62357SFande Kong snes->jacobiandomainerror = PETSC_TRUE; 1813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18207b62357SFande Kong } 18307b62357SFande Kong 18407b62357SFande Kong /*@ 185f6dfbefdSBarry Smith SNESSetCheckJacobianDomainError - tells `SNESSolve()` whether to check if the user called `SNESSetJacobianDomainError()` Jacobian domain error after 186420bcc1bSBarry Smith each Jacobian evaluation. By default, it checks for the Jacobian domain error in the debug mode, and does not check it in the optimized mode. 187b351a90bSFande Kong 188c3339decSBarry Smith Logically Collective 189b351a90bSFande Kong 190b351a90bSFande Kong Input Parameters: 19120f4b53cSBarry Smith + snes - the `SNES` context 192f6dfbefdSBarry Smith - flg - indicates if or not to check Jacobian domain error after each Jacobian evaluation 193b351a90bSFande Kong 194b351a90bSFande Kong Level: advanced 195b351a90bSFande Kong 196f6dfbefdSBarry Smith Note: 197f6dfbefdSBarry Smith Checks require one extra parallel synchronization for each Jacobian evaluation 198f6dfbefdSBarry Smith 1998434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetFunctionDomainError()`, `SNESGetCheckJacobianDomainError()` 200b351a90bSFande Kong @*/ 201d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCheckJacobianDomainError(SNES snes, PetscBool flg) 202d71ae5a4SJacob Faibussowitsch { 203b351a90bSFande Kong PetscFunctionBegin; 204b351a90bSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 205b351a90bSFande Kong snes->checkjacdomainerror = flg; 2063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 207b351a90bSFande Kong } 208b351a90bSFande Kong 209b351a90bSFande Kong /*@ 210420bcc1bSBarry Smith SNESGetCheckJacobianDomainError - Get an indicator whether or not `SNES` is checking Jacobian domain errors after each Jacobian evaluation. 2118383d7d7SFande Kong 212c3339decSBarry Smith Logically Collective 2138383d7d7SFande Kong 2142fe279fdSBarry Smith Input Parameter: 215f6dfbefdSBarry Smith . snes - the `SNES` context 2168383d7d7SFande Kong 2172fe279fdSBarry Smith Output Parameter: 218420bcc1bSBarry Smith . flg - `PETSC_FALSE` indicates that it is not checking Jacobian domain errors after each Jacobian evaluation 2198383d7d7SFande Kong 2208383d7d7SFande Kong Level: advanced 2218383d7d7SFande Kong 2228434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetFunctionDomainError()`, `SNESSetCheckJacobianDomainError()` 2238383d7d7SFande Kong @*/ 224d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetCheckJacobianDomainError(SNES snes, PetscBool *flg) 225d71ae5a4SJacob Faibussowitsch { 2268383d7d7SFande Kong PetscFunctionBegin; 2278383d7d7SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2284f572ea9SToby Isaac PetscAssertPointer(flg, 2); 2298383d7d7SFande Kong *flg = snes->checkjacdomainerror; 2303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2318383d7d7SFande Kong } 2328383d7d7SFande Kong 2338383d7d7SFande Kong /*@ 234420bcc1bSBarry Smith SNESGetFunctionDomainError - Gets the status of the domain error after a call to `SNESComputeFunction()` 2356a388c36SPeter Brune 2366b1535e8SBarry Smith Not Collective, different MPI processes may return different values 2376a388c36SPeter Brune 2382fe279fdSBarry Smith Input Parameter: 239f6dfbefdSBarry Smith . snes - the `SNES` context 2406a388c36SPeter Brune 2412fe279fdSBarry Smith Output Parameter: 242f6dfbefdSBarry Smith . domainerror - Set to `PETSC_TRUE` if there's a domain error; `PETSC_FALSE` otherwise. 2436a388c36SPeter Brune 244f6dfbefdSBarry Smith Level: developer 2456a388c36SPeter Brune 2466b1535e8SBarry Smith Notes: 2476b1535e8SBarry Smith The value will only be true on those MPI processes that called `SNESSetFunctionDomainError()` 2486b1535e8SBarry Smith 2496b1535e8SBarry Smith The value is reset to `PETSC_FALSE` when `SNESCheckFunctionNorm()` is called. 2506b1535e8SBarry Smith 2511cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunctionDomainError()`, `SNESComputeFunction()` 2526a388c36SPeter Brune @*/ 253d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionDomainError(SNES snes, PetscBool *domainerror) 254d71ae5a4SJacob Faibussowitsch { 2556a388c36SPeter Brune PetscFunctionBegin; 2566a388c36SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2574f572ea9SToby Isaac PetscAssertPointer(domainerror, 2); 2586a388c36SPeter Brune *domainerror = snes->domainerror; 2593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2606a388c36SPeter Brune } 2616a388c36SPeter Brune 26207b62357SFande Kong /*@ 263420bcc1bSBarry Smith SNESGetJacobianDomainError - Gets the status of the Jacobian domain error after a call to `SNESComputeJacobian()` 26407b62357SFande Kong 2656b1535e8SBarry Smith Not Collective, different MPI processes may return different values 26607b62357SFande Kong 2672fe279fdSBarry Smith Input Parameter: 268f6dfbefdSBarry Smith . snes - the `SNES` context 26907b62357SFande Kong 2702fe279fdSBarry Smith Output Parameter: 271f6dfbefdSBarry Smith . domainerror - Set to `PETSC_TRUE` if there's a Jacobian domain error; `PETSC_FALSE` otherwise. 27207b62357SFande Kong 27307b62357SFande Kong Level: advanced 27407b62357SFande Kong 2756b1535e8SBarry Smith Notes: 2766b1535e8SBarry Smith The value will only be true on those MPI processes that called `SNESSetJacobianDomainError()` 2776b1535e8SBarry Smith 2786b1535e8SBarry Smith The value is reset to `PETSC_FALSE` when `SNESCheckJacobianDomainerror()` is called but only `SNESSetCheckJacobianDomainError()` was called 2796b1535e8SBarry Smith 2801cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunctionDomainError()`, `SNESComputeFunction()`, `SNESGetFunctionDomainError()` 28107b62357SFande Kong @*/ 282d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetJacobianDomainError(SNES snes, PetscBool *domainerror) 283d71ae5a4SJacob Faibussowitsch { 28407b62357SFande Kong PetscFunctionBegin; 28507b62357SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2864f572ea9SToby Isaac PetscAssertPointer(domainerror, 2); 28707b62357SFande Kong *domainerror = snes->jacobiandomainerror; 2883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 28907b62357SFande Kong } 29007b62357SFande Kong 291ffeef943SBarry Smith /*@ 292f6dfbefdSBarry Smith SNESLoad - Loads a `SNES` that has been stored in `PETSCVIEWERBINARY` with `SNESView()`. 29355849f57SBarry Smith 294c3339decSBarry Smith Collective 29555849f57SBarry Smith 29655849f57SBarry Smith Input Parameters: 297e4094ef1SJacob Faibussowitsch + snes - the newly loaded `SNES`, this needs to have been created with `SNESCreate()` or 298f6dfbefdSBarry Smith some related function before a call to `SNESLoad()`. 299f6dfbefdSBarry Smith - viewer - binary file viewer, obtained from `PetscViewerBinaryOpen()` 30055849f57SBarry Smith 30155849f57SBarry Smith Level: intermediate 30255849f57SBarry Smith 303f6dfbefdSBarry Smith Note: 304420bcc1bSBarry Smith The `SNESType` is determined by the data in the file, any type set into the `SNES` before this call is ignored. 30555849f57SBarry Smith 3061cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `PetscViewer`, `SNESCreate()`, `SNESType`, `PetscViewerBinaryOpen()`, `SNESView()`, `MatLoad()`, `VecLoad()` 30755849f57SBarry Smith @*/ 308d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESLoad(SNES snes, PetscViewer viewer) 309d71ae5a4SJacob Faibussowitsch { 31055849f57SBarry Smith PetscBool isbinary; 311060da220SMatthew G. Knepley PetscInt classid; 31255849f57SBarry Smith char type[256]; 31355849f57SBarry Smith KSP ksp; 3142d53ad75SBarry Smith DM dm; 3152d53ad75SBarry Smith DMSNES dmsnes; 31655849f57SBarry Smith 31755849f57SBarry Smith PetscFunctionBegin; 3182d53ad75SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 31955849f57SBarry Smith PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 3209566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 3215f80ce2aSJacob Faibussowitsch PetscCheck(isbinary, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerBinaryOpen()"); 32255849f57SBarry Smith 3239566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer, &classid, 1, NULL, PETSC_INT)); 3245f80ce2aSJacob Faibussowitsch PetscCheck(classid == SNES_FILE_CLASSID, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Not SNES next in file"); 3259566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer, type, 256, NULL, PETSC_CHAR)); 3269566063dSJacob Faibussowitsch PetscCall(SNESSetType(snes, type)); 327dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, load, viewer); 3289566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 3299566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &dmsnes)); 3309566063dSJacob Faibussowitsch PetscCall(DMSNESLoad(dmsnes, viewer)); 3319566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 3329566063dSJacob Faibussowitsch PetscCall(KSPLoad(ksp, viewer)); 3333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 33455849f57SBarry Smith } 3356a388c36SPeter Brune 3369804daf3SBarry Smith #include <petscdraw.h> 337e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS) 338e04113cfSBarry Smith #include <petscviewersaws.h> 339bfb97211SBarry Smith #endif 3408404b7f3SBarry Smith 341ffeef943SBarry Smith /*@ 342dc4c0fb0SBarry Smith SNESViewFromOptions - View a `SNES` based on values in the options database 343fe2efc57SMark 344c3339decSBarry Smith Collective 345fe2efc57SMark 346fe2efc57SMark Input Parameters: 347f6dfbefdSBarry Smith + A - the `SNES` context 348dc4c0fb0SBarry Smith . obj - Optional object that provides the options prefix for the checks 349736c3998SJose E. Roman - name - command line option 350fe2efc57SMark 351fe2efc57SMark Level: intermediate 352f6dfbefdSBarry Smith 3531cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESView`, `PetscObjectViewFromOptions()`, `SNESCreate()` 354fe2efc57SMark @*/ 355d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESViewFromOptions(SNES A, PetscObject obj, const char name[]) 356d71ae5a4SJacob Faibussowitsch { 357fe2efc57SMark PetscFunctionBegin; 358fe2efc57SMark PetscValidHeaderSpecific(A, SNES_CLASSID, 1); 3599566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 3603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 361fe2efc57SMark } 362fe2efc57SMark 363789d8953SBarry Smith PETSC_EXTERN PetscErrorCode SNESComputeJacobian_DMDA(SNES, Vec, Mat, Mat, void *); 364789d8953SBarry Smith 365ffeef943SBarry Smith /*@ 366dc4c0fb0SBarry Smith SNESView - Prints or visualizes the `SNES` data structure. 3679b94acceSBarry Smith 368c3339decSBarry Smith Collective 369fee21e36SBarry Smith 370c7afd0dbSLois Curfman McInnes Input Parameters: 371f6dfbefdSBarry Smith + snes - the `SNES` context 372f6dfbefdSBarry Smith - viewer - the `PetscViewer` 373c7afd0dbSLois Curfman McInnes 3749b94acceSBarry Smith Options Database Key: 375f6dfbefdSBarry Smith . -snes_view - Calls `SNESView()` at end of `SNESSolve()` 3769b94acceSBarry Smith 377dc4c0fb0SBarry Smith Level: beginner 378dc4c0fb0SBarry Smith 3799b94acceSBarry Smith Notes: 3809b94acceSBarry Smith The available visualization contexts include 381f6dfbefdSBarry Smith + `PETSC_VIEWER_STDOUT_SELF` - standard output (default) 382f6dfbefdSBarry Smith - `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard 383c8a8ba5cSLois Curfman McInnes output where only the first processor opens 384c8a8ba5cSLois Curfman McInnes the file. All other processors send their 385c8a8ba5cSLois Curfman McInnes data to the first processor to print. 3869b94acceSBarry Smith 387052bf0daSPierre Jolivet The available formats include 388f6dfbefdSBarry Smith + `PETSC_VIEWER_DEFAULT` - standard output (default) 389f6dfbefdSBarry Smith - `PETSC_VIEWER_ASCII_INFO_DETAIL` - more verbose output for `SNESNASM` 390052bf0daSPierre Jolivet 3913e081fefSLois Curfman McInnes The user can open an alternative visualization context with 392f6dfbefdSBarry Smith `PetscViewerASCIIOpen()` - output to a specified file. 3939b94acceSBarry Smith 394f6dfbefdSBarry Smith In the debugger you can do "call `SNESView`(snes,0)" to display the `SNES` solver. (The same holds for any PETSc object viewer). 395595c91d4SBarry Smith 3961cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESLoad()`, `SNESCreate()`, `PetscViewerASCIIOpen()` 3979b94acceSBarry Smith @*/ 398d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESView(SNES snes, PetscViewer viewer) 399d71ae5a4SJacob Faibussowitsch { 400fa9f3622SBarry Smith SNESKSPEW *kctx; 40194b7f48cSBarry Smith KSP ksp; 4027f1410a3SPeter Brune SNESLineSearch linesearch; 4039f196a02SMartin Diehl PetscBool isascii, isstring, isbinary, isdraw; 4042d53ad75SBarry Smith DMSNES dmsnes; 405e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS) 406536b137fSBarry Smith PetscBool issaws; 407bfb97211SBarry Smith #endif 4089b94acceSBarry Smith 4093a40ed3dSBarry Smith PetscFunctionBegin; 4100700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 41148a46eb9SPierre Jolivet if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &viewer)); 4120700a824SBarry Smith PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 413c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, viewer, 2); 41474679c65SBarry Smith 4159f196a02SMartin Diehl PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 4169566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 4179566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 4189566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 419e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS) 4209566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 421bfb97211SBarry Smith #endif 4229f196a02SMartin Diehl if (isascii) { 423dc0571f2SMatthew G. Knepley SNESNormSchedule normschedule; 4248404b7f3SBarry Smith DM dm; 4258434afd1SBarry Smith SNESJacobianFn *cJ; 4268404b7f3SBarry Smith void *ctx; 427789d8953SBarry Smith const char *pre = ""; 428dc0571f2SMatthew G. Knepley 4299566063dSJacob Faibussowitsch PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)snes, viewer)); 43048a46eb9SPierre Jolivet if (!snes->setupcalled) PetscCall(PetscViewerASCIIPrintf(viewer, " SNES has not been set up so information may be incomplete\n")); 431e7788613SBarry Smith if (snes->ops->view) { 4329566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 433dbbe0bcdSBarry Smith PetscUseTypeMethod(snes, view, viewer); 4349566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 4350ef38995SBarry Smith } 43677e5a1f9SBarry Smith if (snes->max_funcs == PETSC_UNLIMITED) { 43777e5a1f9SBarry Smith PetscCall(PetscViewerASCIIPrintf(viewer, " maximum iterations=%" PetscInt_FMT ", maximum function evaluations=unlimited\n", snes->max_its)); 43877e5a1f9SBarry Smith } else { 43963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " maximum iterations=%" PetscInt_FMT ", maximum function evaluations=%" PetscInt_FMT "\n", snes->max_its, snes->max_funcs)); 44077e5a1f9SBarry Smith } 4419566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " tolerances: relative=%g, absolute=%g, solution=%g\n", (double)snes->rtol, (double)snes->abstol, (double)snes->stol)); 44248a46eb9SPierre Jolivet if (snes->usesksp) PetscCall(PetscViewerASCIIPrintf(viewer, " total number of linear solver iterations=%" PetscInt_FMT "\n", snes->linear_its)); 44363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " total number of function evaluations=%" PetscInt_FMT "\n", snes->nfuncs)); 4449566063dSJacob Faibussowitsch PetscCall(SNESGetNormSchedule(snes, &normschedule)); 4459566063dSJacob Faibussowitsch if (normschedule > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " norm schedule %s\n", SNESNormSchedules[normschedule])); 44648a46eb9SPierre Jolivet if (snes->gridsequence) PetscCall(PetscViewerASCIIPrintf(viewer, " total number of grid sequence refinements=%" PetscInt_FMT "\n", snes->gridsequence)); 4479b94acceSBarry Smith if (snes->ksp_ewconv) { 448fa9f3622SBarry Smith kctx = (SNESKSPEW *)snes->kspconvctx; 4499b94acceSBarry Smith if (kctx) { 45063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Eisenstat-Walker computation of KSP relative tolerance (version %" PetscInt_FMT ")\n", kctx->version)); 4519566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " rtol_0=%g, rtol_max=%g, threshold=%g\n", (double)kctx->rtol_0, (double)kctx->rtol_max, (double)kctx->threshold)); 4529566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " gamma=%g, alpha=%g, alpha2=%g\n", (double)kctx->gamma, (double)kctx->alpha, (double)kctx->alpha2)); 4539b94acceSBarry Smith } 4549b94acceSBarry Smith } 455eb1f6c34SBarry Smith if (snes->lagpreconditioner == -1) { 4569566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Preconditioned is never rebuilt\n")); 457eb1f6c34SBarry Smith } else if (snes->lagpreconditioner > 1) { 45863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Preconditioned is rebuilt every %" PetscInt_FMT " new Jacobians\n", snes->lagpreconditioner)); 459eb1f6c34SBarry Smith } 460eb1f6c34SBarry Smith if (snes->lagjacobian == -1) { 4619566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Jacobian is never rebuilt\n")); 462eb1f6c34SBarry Smith } else if (snes->lagjacobian > 1) { 46363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Jacobian is rebuilt every %" PetscInt_FMT " SNES iterations\n", snes->lagjacobian)); 464eb1f6c34SBarry Smith } 4659566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 4669566063dSJacob Faibussowitsch PetscCall(DMSNESGetJacobian(dm, &cJ, &ctx)); 467789d8953SBarry Smith if (snes->mf_operator) { 4689566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Jacobian is applied matrix-free with differencing\n")); 469789d8953SBarry Smith pre = "Preconditioning "; 470789d8953SBarry Smith } 4718404b7f3SBarry Smith if (cJ == SNESComputeJacobianDefault) { 4729566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %sJacobian is built using finite differences one column at a time\n", pre)); 4738404b7f3SBarry Smith } else if (cJ == SNESComputeJacobianDefaultColor) { 4749566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %sJacobian is built using finite differences with coloring\n", pre)); 475789d8953SBarry Smith /* it slightly breaks data encapsulation for access the DMDA information directly */ 476789d8953SBarry Smith } else if (cJ == SNESComputeJacobian_DMDA) { 477789d8953SBarry Smith MatFDColoring fdcoloring; 4789566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)dm, "DMDASNES_FDCOLORING", (PetscObject *)&fdcoloring)); 479789d8953SBarry Smith if (fdcoloring) { 4809566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %sJacobian is built using colored finite differences on a DMDA\n", pre)); 481789d8953SBarry Smith } else { 4829566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %sJacobian is built using a DMDA local Jacobian\n", pre)); 483789d8953SBarry Smith } 484996e1cbcSBarry Smith } else if (snes->mf && !snes->mf_operator) { 4859566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Jacobian is applied matrix-free with differencing, no explicit Jacobian\n")); 4868404b7f3SBarry Smith } 4870f5bd95cSBarry Smith } else if (isstring) { 488317d6ea6SBarry Smith const char *type; 4899566063dSJacob Faibussowitsch PetscCall(SNESGetType(snes, &type)); 4909566063dSJacob Faibussowitsch PetscCall(PetscViewerStringSPrintf(viewer, " SNESType: %-7.7s", type)); 491dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, view, viewer); 49255849f57SBarry Smith } else if (isbinary) { 49355849f57SBarry Smith PetscInt classid = SNES_FILE_CLASSID; 49455849f57SBarry Smith MPI_Comm comm; 49555849f57SBarry Smith PetscMPIInt rank; 49655849f57SBarry Smith char type[256]; 49755849f57SBarry Smith 4989566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 4999566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 500dd400576SPatrick Sanan if (rank == 0) { 5019566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryWrite(viewer, &classid, 1, PETSC_INT)); 5029566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(type, ((PetscObject)snes)->type_name, sizeof(type))); 5039566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryWrite(viewer, type, sizeof(type), PETSC_CHAR)); 50455849f57SBarry Smith } 505dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, view, viewer); 50672a02f06SBarry Smith } else if (isdraw) { 50772a02f06SBarry Smith PetscDraw draw; 50872a02f06SBarry Smith char str[36]; 50989fd9fafSBarry Smith PetscReal x, y, bottom, h; 51072a02f06SBarry Smith 5119566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 5129566063dSJacob Faibussowitsch PetscCall(PetscDrawGetCurrentPoint(draw, &x, &y)); 5139566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(str, "SNES: ", sizeof(str))); 5149566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(str, ((PetscObject)snes)->type_name, sizeof(str))); 5159566063dSJacob Faibussowitsch PetscCall(PetscDrawStringBoxed(draw, x, y, PETSC_DRAW_BLUE, PETSC_DRAW_BLACK, str, NULL, &h)); 51689fd9fafSBarry Smith bottom = y - h; 5179566063dSJacob Faibussowitsch PetscCall(PetscDrawPushCurrentPoint(draw, x, bottom)); 518dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, view, viewer); 519e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS) 520536b137fSBarry Smith } else if (issaws) { 521d45a07a7SBarry Smith PetscMPIInt rank; 5222657e9d9SBarry Smith const char *name; 523d45a07a7SBarry Smith 5249566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)snes, &name)); 5259566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 526dd400576SPatrick Sanan if (!((PetscObject)snes)->amsmem && rank == 0) { 527d45a07a7SBarry Smith char dir[1024]; 528d45a07a7SBarry Smith 5299566063dSJacob Faibussowitsch PetscCall(PetscObjectViewSAWs((PetscObject)snes, viewer)); 5309566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/its", name)); 531792fecdfSBarry Smith PetscCallSAWs(SAWs_Register, (dir, &snes->iter, 1, SAWs_READ, SAWs_INT)); 53248a46eb9SPierre Jolivet if (!snes->conv_hist) PetscCall(SNESSetConvergenceHistory(snes, NULL, NULL, PETSC_DECIDE, PETSC_TRUE)); 5339566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/conv_hist", name)); 534792fecdfSBarry Smith PetscCallSAWs(SAWs_Register, (dir, snes->conv_hist, 10, SAWs_READ, SAWs_DOUBLE)); 535f05ece33SBarry Smith } 536bfb97211SBarry Smith #endif 53772a02f06SBarry Smith } 53872a02f06SBarry Smith if (snes->linesearch) { 5399566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &linesearch)); 5409566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 5419566063dSJacob Faibussowitsch PetscCall(SNESLineSearchView(linesearch, viewer)); 5429566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 54319bcc07fSBarry Smith } 544efd4aadfSBarry Smith if (snes->npc && snes->usesnpc) { 5459566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 5469566063dSJacob Faibussowitsch PetscCall(SNESView(snes->npc, viewer)); 5479566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 5484a0c5b0cSMatthew G Knepley } 5499566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 5509566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(snes->dm, &dmsnes)); 5519566063dSJacob Faibussowitsch PetscCall(DMSNESView(dmsnes, viewer)); 5529566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 5532c155ee1SBarry Smith if (snes->usesksp) { 5549566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 5559566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 5569566063dSJacob Faibussowitsch PetscCall(KSPView(ksp, viewer)); 5579566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 5582c155ee1SBarry Smith } 55972a02f06SBarry Smith if (isdraw) { 56072a02f06SBarry Smith PetscDraw draw; 5619566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 5629566063dSJacob Faibussowitsch PetscCall(PetscDrawPopCurrentPoint(draw)); 5637f1410a3SPeter Brune } 5643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5659b94acceSBarry Smith } 5669b94acceSBarry Smith 56776b2cf59SMatthew Knepley /* 56876b2cf59SMatthew Knepley We retain a list of functions that also take SNES command 56976b2cf59SMatthew Knepley line options. These are called at the end SNESSetFromOptions() 57076b2cf59SMatthew Knepley */ 57176b2cf59SMatthew Knepley #define MAXSETFROMOPTIONS 5 572a7cc72afSBarry Smith static PetscInt numberofsetfromoptions; 5736849ba73SBarry Smith static PetscErrorCode (*othersetfromoptions[MAXSETFROMOPTIONS])(SNES); 57476b2cf59SMatthew Knepley 575ac226902SBarry Smith /*@C 576f6dfbefdSBarry Smith SNESAddOptionsChecker - Adds an additional function to check for `SNES` options. 57776b2cf59SMatthew Knepley 57876b2cf59SMatthew Knepley Not Collective 57976b2cf59SMatthew Knepley 58076b2cf59SMatthew Knepley Input Parameter: 58176b2cf59SMatthew Knepley . snescheck - function that checks for options 58276b2cf59SMatthew Knepley 583420bcc1bSBarry Smith Calling sequence of `snescheck`: 584420bcc1bSBarry Smith . snes - the `SNES` object for which it is checking options 585420bcc1bSBarry Smith 58676b2cf59SMatthew Knepley Level: developer 58776b2cf59SMatthew Knepley 5881cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()` 58976b2cf59SMatthew Knepley @*/ 590420bcc1bSBarry Smith PetscErrorCode SNESAddOptionsChecker(PetscErrorCode (*snescheck)(SNES snes)) 591d71ae5a4SJacob Faibussowitsch { 59276b2cf59SMatthew Knepley PetscFunctionBegin; 59363a3b9bcSJacob Faibussowitsch PetscCheck(numberofsetfromoptions < MAXSETFROMOPTIONS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many options checkers, only %d allowed", MAXSETFROMOPTIONS); 59476b2cf59SMatthew Knepley othersetfromoptions[numberofsetfromoptions++] = snescheck; 5953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 59676b2cf59SMatthew Knepley } 59776b2cf59SMatthew Knepley 598d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetUpMatrixFree_Private(SNES snes, PetscBool hasOperator, PetscInt version) 599d71ae5a4SJacob Faibussowitsch { 600aa3661deSLisandro Dalcin Mat J; 601895c21f2SBarry Smith MatNullSpace nullsp; 602aa3661deSLisandro Dalcin 603aa3661deSLisandro Dalcin PetscFunctionBegin; 6040700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 605aa3661deSLisandro Dalcin 60698613b67SLisandro Dalcin if (!snes->vec_func && (snes->jacobian || snes->jacobian_pre)) { 60798613b67SLisandro Dalcin Mat A = snes->jacobian, B = snes->jacobian_pre; 6089566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A ? A : B, NULL, &snes->vec_func)); 60998613b67SLisandro Dalcin } 61098613b67SLisandro Dalcin 6110fdf79fbSJacob Faibussowitsch PetscCheck(version == 1 || version == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "matrix-free operator routines, only version 1 and 2"); 612aa3661deSLisandro Dalcin if (version == 1) { 6139566063dSJacob Faibussowitsch PetscCall(MatCreateSNESMF(snes, &J)); 6149566063dSJacob Faibussowitsch PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix)); 6159566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(J)); 6161e2ae407SBarry Smith /* TODO: the version 2 code should be merged into the MatCreateSNESMF() and MatCreateMFFD() infrastructure and then removed */ 6170fdf79fbSJacob Faibussowitsch } else /* if (version == 2) */ { 6185f80ce2aSJacob Faibussowitsch PetscCheck(snes->vec_func, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "SNESSetFunction() must be called first"); 619570b7f6dSBarry Smith #if !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_REAL_SINGLE) && !defined(PETSC_USE_REAL___FLOAT128) && !defined(PETSC_USE_REAL___FP16) 620f6dfbefdSBarry Smith PetscCall(MatCreateSNESMFMore(snes, snes->vec_func, &J)); 621aa3661deSLisandro Dalcin #else 6222479783cSJose E. Roman SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "matrix-free operator routines (version 2)"); 623aa3661deSLisandro Dalcin #endif 6240fdf79fbSJacob Faibussowitsch } 625aa3661deSLisandro Dalcin 62601c1178eSBarry Smith /* attach any user provided null space that was on Amat to the newly created matrix-free matrix */ 627895c21f2SBarry Smith if (snes->jacobian) { 6289566063dSJacob Faibussowitsch PetscCall(MatGetNullSpace(snes->jacobian, &nullsp)); 6291baa6e33SBarry Smith if (nullsp) PetscCall(MatSetNullSpace(J, nullsp)); 630895c21f2SBarry Smith } 631895c21f2SBarry Smith 63263a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Setting default matrix-free operator routines (version %" PetscInt_FMT ")\n", version)); 633d3462f78SMatthew Knepley if (hasOperator) { 634aa3661deSLisandro Dalcin /* This version replaces the user provided Jacobian matrix with a 6357addb90fSBarry Smith matrix-free version but still employs the user-provided matrix used for computing the preconditioner. */ 6369566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL)); 637aa3661deSLisandro Dalcin } else { 638aa3661deSLisandro Dalcin /* This version replaces both the user-provided Jacobian and the user- 63901c1178eSBarry Smith provided preconditioner Jacobian with the default matrix-free version. */ 640b552625fSStefano Zampini if (snes->npcside == PC_LEFT && snes->npc) { 6419566063dSJacob Faibussowitsch if (!snes->jacobian) PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL)); 642172a4300SPeter Brune } else { 643789d8953SBarry Smith KSP ksp; 644789d8953SBarry Smith PC pc; 645789d8953SBarry Smith PetscBool match; 646789d8953SBarry Smith 6479566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J, J, MatMFFDComputeJacobian, NULL)); 648aa3661deSLisandro Dalcin /* Force no preconditioner */ 6499566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 6509566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksp, &pc)); 6512698c518SLisandro Dalcin PetscCall(PetscObjectTypeCompareAny((PetscObject)pc, &match, PCSHELL, PCH2OPUS, "")); 652aa3661deSLisandro Dalcin if (!match) { 6539566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Setting default matrix-free preconditioner routines\nThat is no preconditioner is being used\n")); 6549566063dSJacob Faibussowitsch PetscCall(PCSetType(pc, PCNONE)); 655aa3661deSLisandro Dalcin } 656aa3661deSLisandro Dalcin } 657789d8953SBarry Smith } 6589566063dSJacob Faibussowitsch PetscCall(MatDestroy(&J)); 6593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 660aa3661deSLisandro Dalcin } 661aa3661deSLisandro Dalcin 662d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMRestrictHook_SNESVecSol(DM dmfine, Mat Restrict, Vec Rscale, Mat Inject, DM dmcoarse, void *ctx) 663d71ae5a4SJacob Faibussowitsch { 664dfe15315SJed Brown SNES snes = (SNES)ctx; 6650298fd71SBarry Smith Vec Xfine, Xfine_named = NULL, Xcoarse; 666dfe15315SJed Brown 667dfe15315SJed Brown PetscFunctionBegin; 66816ebb321SJed Brown if (PetscLogPrintInfo) { 66916ebb321SJed Brown PetscInt finelevel, coarselevel, fineclevel, coarseclevel; 6709566063dSJacob Faibussowitsch PetscCall(DMGetRefineLevel(dmfine, &finelevel)); 6719566063dSJacob Faibussowitsch PetscCall(DMGetCoarsenLevel(dmfine, &fineclevel)); 6729566063dSJacob Faibussowitsch PetscCall(DMGetRefineLevel(dmcoarse, &coarselevel)); 6739566063dSJacob Faibussowitsch PetscCall(DMGetCoarsenLevel(dmcoarse, &coarseclevel)); 67463a3b9bcSJacob 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)); 67516ebb321SJed Brown } 676dfe15315SJed Brown if (dmfine == snes->dm) Xfine = snes->vec_sol; 677dfe15315SJed Brown else { 6789566063dSJacob Faibussowitsch PetscCall(DMGetNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named)); 679dfe15315SJed Brown Xfine = Xfine_named; 680dfe15315SJed Brown } 6819566063dSJacob Faibussowitsch PetscCall(DMGetNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse)); 682907f5c5aSLawrence Mitchell if (Inject) { 6839566063dSJacob Faibussowitsch PetscCall(MatRestrict(Inject, Xfine, Xcoarse)); 684907f5c5aSLawrence Mitchell } else { 6859566063dSJacob Faibussowitsch PetscCall(MatRestrict(Restrict, Xfine, Xcoarse)); 6869566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(Xcoarse, Xcoarse, Rscale)); 687907f5c5aSLawrence Mitchell } 6889566063dSJacob Faibussowitsch PetscCall(DMRestoreNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse)); 6899566063dSJacob Faibussowitsch if (Xfine_named) PetscCall(DMRestoreNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named)); 6903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 691dfe15315SJed Brown } 692dfe15315SJed Brown 693d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCoarsenHook_SNESVecSol(DM dm, DM dmc, void *ctx) 694d71ae5a4SJacob Faibussowitsch { 69516ebb321SJed Brown PetscFunctionBegin; 6969566063dSJacob Faibussowitsch PetscCall(DMCoarsenHookAdd(dmc, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, ctx)); 6973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 69816ebb321SJed Brown } 69916ebb321SJed Brown 700a6950cb2SJed Brown /* This may be called to rediscretize the operator on levels of linear multigrid. The DM shuffle is so the user can 701a6950cb2SJed Brown * safely call SNESGetDM() in their residual evaluation routine. */ 702d71ae5a4SJacob Faibussowitsch static PetscErrorCode KSPComputeOperators_SNES(KSP ksp, Mat A, Mat B, void *ctx) 703d71ae5a4SJacob Faibussowitsch { 704caa4e7f2SJed Brown SNES snes = (SNES)ctx; 70597d931d1SStefano Zampini DMSNES sdm; 7060298fd71SBarry Smith Vec X, Xnamed = NULL; 707dfe15315SJed Brown DM dmsave; 7084e269d77SPeter Brune void *ctxsave; 7098434afd1SBarry Smith SNESJacobianFn *jac = NULL; 710caa4e7f2SJed Brown 711caa4e7f2SJed Brown PetscFunctionBegin; 712dfe15315SJed Brown dmsave = snes->dm; 7139566063dSJacob Faibussowitsch PetscCall(KSPGetDM(ksp, &snes->dm)); 714dfe15315SJed Brown if (dmsave == snes->dm) X = snes->vec_sol; /* We are on the finest level */ 71597d931d1SStefano Zampini else { 716309d62e6SStefano Zampini PetscBool has; 717309d62e6SStefano Zampini 71897d931d1SStefano Zampini /* We are on a coarser level, this vec was initialized using a DM restrict hook */ 719309d62e6SStefano Zampini PetscCall(DMHasNamedGlobalVector(snes->dm, "SNESVecSol", &has)); 720309d62e6SStefano Zampini PetscCheck(has, PetscObjectComm((PetscObject)snes->dm), PETSC_ERR_PLIB, "Missing SNESVecSol"); 72197d931d1SStefano Zampini PetscCall(DMGetNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed)); 722dfe15315SJed Brown X = Xnamed; 7239566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, NULL, NULL, &jac, &ctxsave)); 7244e269d77SPeter Brune /* If the DM's don't match up, the MatFDColoring context needed for the jacobian won't match up either -- fixit. */ 72548a46eb9SPierre Jolivet if (jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, SNESComputeJacobianDefaultColor, NULL)); 7264e269d77SPeter Brune } 7274e269d77SPeter Brune 7282b93b426SMatthew G. Knepley /* Compute the operators */ 72997d931d1SStefano Zampini PetscCall(DMGetDMSNES(snes->dm, &sdm)); 73097d931d1SStefano Zampini if (Xnamed && sdm->ops->computefunction) { 73197d931d1SStefano Zampini /* The SNES contract with the user is that ComputeFunction is always called before ComputeJacobian. 73297d931d1SStefano Zampini We make sure of this here. Disable affine shift since it is for the finest level */ 73397d931d1SStefano Zampini Vec F, saverhs = snes->vec_rhs; 73497d931d1SStefano Zampini 73597d931d1SStefano Zampini snes->vec_rhs = NULL; 73697d931d1SStefano Zampini PetscCall(DMGetGlobalVector(snes->dm, &F)); 73797d931d1SStefano Zampini PetscCall(SNESComputeFunction(snes, X, F)); 73897d931d1SStefano Zampini PetscCall(DMRestoreGlobalVector(snes->dm, &F)); 73997d931d1SStefano Zampini snes->vec_rhs = saverhs; 74097d931d1SStefano Zampini snes->nfuncs--; /* Do not log coarser level evaluations */ 74197d931d1SStefano Zampini } 74297d931d1SStefano Zampini /* Make sure KSP DM has the Jacobian computation routine */ 74397d931d1SStefano Zampini if (!sdm->ops->computejacobian) PetscCall(DMCopyDMSNES(dmsave, snes->dm)); 7449566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobian(snes, X, A, B)); 74597d931d1SStefano Zampini 7462b93b426SMatthew G. Knepley /* Put the previous context back */ 74748a46eb9SPierre Jolivet if (snes->dm != dmsave && jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, jac, ctxsave)); 7484e269d77SPeter Brune 7499566063dSJacob Faibussowitsch if (Xnamed) PetscCall(DMRestoreNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed)); 750dfe15315SJed Brown snes->dm = dmsave; 7513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 752caa4e7f2SJed Brown } 753caa4e7f2SJed Brown 7546cab3a1bSJed Brown /*@ 755dc4c0fb0SBarry Smith SNESSetUpMatrices - ensures that matrices are available for `SNES` Newton-like methods, this is called by `SNESSetUp_XXX()` 7566cab3a1bSJed Brown 7576cab3a1bSJed Brown Collective 7586cab3a1bSJed Brown 7594165533cSJose E. Roman Input Parameter: 76020f4b53cSBarry Smith . snes - `SNES` object to configure 7616cab3a1bSJed Brown 7626cab3a1bSJed Brown Level: developer 7636cab3a1bSJed Brown 764dc4c0fb0SBarry Smith Note: 765dc4c0fb0SBarry 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` 766dc4c0fb0SBarry Smith 76773a84a35SBarry Smith Developer Note: 76873a84a35SBarry Smith The functionality of this routine overlaps in a confusing way with the functionality of `SNESSetUpMatrixFree_Private()` which is called by 76973a84a35SBarry Smith `SNESSetUp()` but sometimes `SNESSetUpMatrices()` is called without `SNESSetUp()` being called. A refactorization to simplify the 77073a84a35SBarry Smith logic that handles the matrix-free case is desirable. 77173a84a35SBarry Smith 7721cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUp()` 7736cab3a1bSJed Brown @*/ 774d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUpMatrices(SNES snes) 775d71ae5a4SJacob Faibussowitsch { 7766cab3a1bSJed Brown DM dm; 777942e3340SBarry Smith DMSNES sdm; 7786cab3a1bSJed Brown 7796cab3a1bSJed Brown PetscFunctionBegin; 7809566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 7819566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 78273a84a35SBarry Smith if (!snes->jacobian && snes->mf && !snes->mf_operator && !snes->jacobian_pre) { 7836cab3a1bSJed Brown Mat J; 7846cab3a1bSJed Brown void *functx; 7859566063dSJacob Faibussowitsch PetscCall(MatCreateSNESMF(snes, &J)); 7869566063dSJacob Faibussowitsch PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix)); 7879566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(J)); 7889566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, NULL, &functx)); 7899566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J, J, NULL, NULL)); 7909566063dSJacob Faibussowitsch PetscCall(MatDestroy(&J)); 791caa4e7f2SJed Brown } else if (snes->mf_operator && !snes->jacobian_pre && !snes->jacobian) { 7926cab3a1bSJed Brown Mat J, B; 7939566063dSJacob Faibussowitsch PetscCall(MatCreateSNESMF(snes, &J)); 7949566063dSJacob Faibussowitsch PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix)); 7959566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(J)); 7969566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(snes->dm, &B)); 79706f20277SJed Brown /* sdm->computejacobian was already set to reach here */ 7989566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J, B, NULL, NULL)); 7999566063dSJacob Faibussowitsch PetscCall(MatDestroy(&J)); 8009566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 801caa4e7f2SJed Brown } else if (!snes->jacobian_pre) { 8021ba9b98eSMatthew G. Knepley PetscDS prob; 8036cab3a1bSJed Brown Mat J, B; 8041ba9b98eSMatthew G. Knepley PetscBool hasPrec = PETSC_FALSE; 8051ba9b98eSMatthew G. Knepley 8066cab3a1bSJed Brown J = snes->jacobian; 8079566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob)); 8089566063dSJacob Faibussowitsch if (prob) PetscCall(PetscDSHasJacobianPreconditioner(prob, &hasPrec)); 8099566063dSJacob Faibussowitsch if (J) PetscCall(PetscObjectReference((PetscObject)J)); 8109566063dSJacob Faibussowitsch else if (hasPrec) PetscCall(DMCreateMatrix(snes->dm, &J)); 8119566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(snes->dm, &B)); 8129566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J ? J : B, B, NULL, NULL)); 8139566063dSJacob Faibussowitsch PetscCall(MatDestroy(&J)); 8149566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 8156cab3a1bSJed Brown } 816caa4e7f2SJed Brown { 817caa4e7f2SJed Brown KSP ksp; 8189566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 8199566063dSJacob Faibussowitsch PetscCall(KSPSetComputeOperators(ksp, KSPComputeOperators_SNES, snes)); 8209566063dSJacob Faibussowitsch PetscCall(DMCoarsenHookAdd(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes)); 821caa4e7f2SJed Brown } 8223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8236cab3a1bSJed Brown } 8246cab3a1bSJed Brown 825d6acfc2dSPierre Jolivet PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode PetscMonitorPauseFinal_Internal(PetscInt, void *); 826ce78bad3SBarry Smith 827d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESMonitorPauseFinal_Internal(SNES snes) 828d71ae5a4SJacob Faibussowitsch { 8295e7c47f3SMatthew G. Knepley PetscFunctionBegin; 8303ba16761SJacob Faibussowitsch if (!snes->pauseFinal) PetscFunctionReturn(PETSC_SUCCESS); 831ce78bad3SBarry Smith PetscCall(PetscMonitorPauseFinal_Internal(snes->numbermonitors, snes->monitorcontext)); 8323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8335e7c47f3SMatthew G. Knepley } 8345e7c47f3SMatthew G. Knepley 835fde5950dSBarry Smith /*@C 836fde5950dSBarry Smith SNESMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user 837fde5950dSBarry Smith 838c3339decSBarry Smith Collective 839fde5950dSBarry Smith 840fde5950dSBarry Smith Input Parameters: 841dc4c0fb0SBarry Smith + snes - `SNES` object you wish to monitor 842fde5950dSBarry Smith . name - the monitor type one is seeking 843fde5950dSBarry Smith . help - message indicating what monitoring is done 844fde5950dSBarry Smith . manual - manual page for the monitor 84549abdd8aSBarry Smith . monitor - the monitor function, this must use a `PetscViewerFormat` as its context 846f6dfbefdSBarry 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 847fde5950dSBarry Smith 848420bcc1bSBarry Smith Calling sequence of `monitor`: 849420bcc1bSBarry Smith + snes - the nonlinear solver context 850420bcc1bSBarry Smith . it - the current iteration 851420bcc1bSBarry Smith . r - the current function norm 852420bcc1bSBarry Smith - vf - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use 853420bcc1bSBarry Smith 854420bcc1bSBarry Smith Calling sequence of `monitorsetup`: 855420bcc1bSBarry Smith + snes - the nonlinear solver context 856420bcc1bSBarry Smith - vf - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use 857420bcc1bSBarry Smith 858f6dfbefdSBarry Smith Options Database Key: 859f6dfbefdSBarry Smith . -name - trigger the use of this monitor in `SNESSetFromOptions()` 860f6dfbefdSBarry Smith 861f6dfbefdSBarry Smith Level: advanced 862fde5950dSBarry Smith 863648c30bcSBarry Smith .seealso: [](ch_snes), `PetscOptionsCreateViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, 864db781477SPatrick Sanan `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()` 865e4094ef1SJacob Faibussowitsch `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, 866db781477SPatrick Sanan `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`, 867c2e3fba1SPatrick Sanan `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`, 868db781477SPatrick Sanan `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`, 869db781477SPatrick Sanan `PetscOptionsFList()`, `PetscOptionsEList()` 870fde5950dSBarry Smith @*/ 871420bcc1bSBarry 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)) 872d71ae5a4SJacob Faibussowitsch { 873fde5950dSBarry Smith PetscViewer viewer; 874fde5950dSBarry Smith PetscViewerFormat format; 875fde5950dSBarry Smith PetscBool flg; 876fde5950dSBarry Smith 877fde5950dSBarry Smith PetscFunctionBegin; 878648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, name, &viewer, &format, &flg)); 879fde5950dSBarry Smith if (flg) { 880d43b4f6eSBarry Smith PetscViewerAndFormat *vf; 8819566063dSJacob Faibussowitsch PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf)); 882648c30bcSBarry Smith PetscCall(PetscViewerDestroy(&viewer)); 8831baa6e33SBarry Smith if (monitorsetup) PetscCall((*monitorsetup)(snes, vf)); 88449abdd8aSBarry Smith PetscCall(SNESMonitorSet(snes, (PetscErrorCode (*)(SNES, PetscInt, PetscReal, void *))monitor, vf, (PetscCtxDestroyFn *)PetscViewerAndFormatDestroy)); 885fde5950dSBarry Smith } 8863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 887fde5950dSBarry Smith } 888fde5950dSBarry Smith 889a4598233SStefano Zampini PetscErrorCode SNESEWSetFromOptions_Private(SNESKSPEW *kctx, PetscBool print_api, MPI_Comm comm, const char *prefix) 890d71ae5a4SJacob Faibussowitsch { 891a4598233SStefano Zampini const char *api = print_api ? "SNESKSPSetParametersEW" : NULL; 892a4598233SStefano Zampini 8930f0abf79SStefano Zampini PetscFunctionBegin; 8940f0abf79SStefano Zampini PetscOptionsBegin(comm, prefix, "Eisenstat and Walker type forcing options", "KSP"); 895a4598233SStefano Zampini PetscCall(PetscOptionsInt("-ksp_ew_version", "Version 1, 2 or 3", api, kctx->version, &kctx->version, NULL)); 896a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_rtol0", "0 <= rtol0 < 1", api, kctx->rtol_0, &kctx->rtol_0, NULL)); 897a4598233SStefano Zampini kctx->rtol_max = PetscMax(kctx->rtol_0, kctx->rtol_max); 898a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_rtolmax", "0 <= rtolmax < 1", api, kctx->rtol_max, &kctx->rtol_max, NULL)); 899a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_gamma", "0 <= gamma <= 1", api, kctx->gamma, &kctx->gamma, NULL)); 900a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_alpha", "1 < alpha <= 2", api, kctx->alpha, &kctx->alpha, NULL)); 9010f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_alpha2", "alpha2", NULL, kctx->alpha2, &kctx->alpha2, NULL)); 902a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_threshold", "0 < threshold < 1", api, kctx->threshold, &kctx->threshold, NULL)); 9030f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_p1", "p1", NULL, kctx->v4_p1, &kctx->v4_p1, NULL)); 9040f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_p2", "p2", NULL, kctx->v4_p2, &kctx->v4_p2, NULL)); 9050f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_p3", "p3", NULL, kctx->v4_p3, &kctx->v4_p3, NULL)); 9060f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_m1", "Scaling when rk-1 in [p2,p3)", NULL, kctx->v4_m1, &kctx->v4_m1, NULL)); 9070f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_m2", "Scaling when rk-1 in [p3,+infty)", NULL, kctx->v4_m2, &kctx->v4_m2, NULL)); 9080f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_m3", "Threshold for successive rtol (0.1 in Eq.7)", NULL, kctx->v4_m3, &kctx->v4_m3, NULL)); 9090f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_m4", "Adaptation scaling (0.5 in Eq.7)", NULL, kctx->v4_m4, &kctx->v4_m4, NULL)); 9100f0abf79SStefano Zampini PetscOptionsEnd(); 9113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9120f0abf79SStefano Zampini } 9130f0abf79SStefano Zampini 9149b94acceSBarry Smith /*@ 915f6dfbefdSBarry Smith SNESSetFromOptions - Sets various `SNES` and `KSP` parameters from user options. 9169b94acceSBarry Smith 917c3339decSBarry Smith Collective 918c7afd0dbSLois Curfman McInnes 9199b94acceSBarry Smith Input Parameter: 920f6dfbefdSBarry Smith . snes - the `SNES` context 9219b94acceSBarry Smith 92236851e7fSLois Curfman McInnes Options Database Keys: 923f6dfbefdSBarry Smith + -snes_type <type> - newtonls, newtontr, ngmres, ncg, nrichardson, qn, vi, fas, `SNESType` for complete list 924b39c3a46SLois Curfman McInnes . -snes_rtol <rtol> - relative decrease in tolerance norm from initial 92577e5a1f9SBarry Smith . -snes_atol <abstol> - absolute tolerance of residual norm 92677e5a1f9SBarry Smith . -snes_stol <stol> - convergence tolerance in terms of the norm of the change in the solution between steps 927e4d06f11SPatrick Farrell . -snes_divergence_tolerance <divtol> - if the residual goes above divtol*rnorm0, exit with divergence 928b39c3a46SLois Curfman McInnes . -snes_max_it <max_it> - maximum number of iterations 929b39c3a46SLois Curfman McInnes . -snes_max_funcs <max_funcs> - maximum number of function evaluations 93077e5a1f9SBarry Smith . -snes_force_iteration <force> - force `SNESSolve()` to take at least one iteration 9314839bfe8SBarry Smith . -snes_max_fail <max_fail> - maximum number of line search failures allowed before stopping, default is none 932ddf469c8SBarry Smith . -snes_max_linear_solve_fail - number of linear solver failures before SNESSolve() stops 933a8054027SBarry Smith . -snes_lag_preconditioner <lag> - how often preconditioner is rebuilt (use -1 to never rebuild) 9343d5a8a6aSBarry Smith . -snes_lag_preconditioner_persists <true,false> - retains the -snes_lag_preconditioner information across multiple SNESSolve() 935e35cf81dSBarry Smith . -snes_lag_jacobian <lag> - how often Jacobian is rebuilt (use -1 to never rebuild) 9363d5a8a6aSBarry Smith . -snes_lag_jacobian_persists <true,false> - retains the -snes_lag_jacobian information across multiple SNESSolve() 937ceaaa498SBarry 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. 938fde5950dSBarry Smith . -snes_monitor [ascii][:filename][:viewer format] - prints residual norm at each iteration. if no filename given prints to stdout 939fde5950dSBarry Smith . -snes_monitor_solution [ascii binary draw][:filename][:viewer format] - plots solution at each iteration 940fde5950dSBarry Smith . -snes_monitor_residual [ascii binary draw][:filename][:viewer format] - plots residual (not its norm) at each iteration 941fde5950dSBarry Smith . -snes_monitor_solution_update [ascii binary draw][:filename][:viewer format] - plots update to solution at each iteration 9424619e776SBarry Smith . -snes_monitor_lg_residualnorm - plots residual norm at each iteration 943459f5d12SBarry Smith . -snes_monitor_lg_range - plots residual norm at each iteration 9445e7c47f3SMatthew G. Knepley . -snes_monitor_pause_final - Pauses all monitor drawing after the solver ends 945e24b481bSBarry Smith . -snes_fd - use finite differences to compute Jacobian; very slow, only for testing 946e2e60de9SPeter Brune . -snes_fd_color - use finite differences with coloring to compute Jacobian 947ceaaa498SBarry Smith . -snes_mf_ksp_monitor - if using matrix-free multiply then print h at each `KSP` iteration 948b5badacbSBarry Smith . -snes_converged_reason - print the reason for convergence/divergence after each solve 949ceaaa498SBarry Smith . -npc_snes_type <type> - the `SNES` type to use as a nonlinear preconditioner 950e62ac41dSBarry 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. 951e62ac41dSBarry 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. 95282738288SBarry Smith 953f6dfbefdSBarry Smith Options Database Keys for Eisenstat-Walker method: 954fa9f3622SBarry Smith + -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence 9554b27c08aSLois Curfman McInnes . -snes_ksp_ew_version ver - version of Eisenstat-Walker method 95636851e7fSLois Curfman McInnes . -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0 95736851e7fSLois Curfman McInnes . -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax 95836851e7fSLois Curfman McInnes . -snes_ksp_ew_gamma <gamma> - Sets gamma 95936851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha <alpha> - Sets alpha 96036851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2 96136851e7fSLois Curfman McInnes - -snes_ksp_ew_threshold <threshold> - Sets threshold 96282738288SBarry Smith 963dc4c0fb0SBarry Smith Level: beginner 964dc4c0fb0SBarry Smith 96511ca99fdSLois Curfman McInnes Notes: 966ec5066bdSBarry Smith To see all options, run your program with the -help option or consult the users manual 967ec5066bdSBarry Smith 968420bcc1bSBarry Smith `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`, 969420bcc1bSBarry Smith and computing explicitly with 970f6dfbefdSBarry Smith finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object. 97183e2fdc7SBarry Smith 972420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESType`, `SNESSetOptionsPrefix()`, `SNESResetFromOptions()`, `SNES`, `SNESCreate()`, `MatCreateSNESMF()`, `MatFDColoring` 9739b94acceSBarry Smith @*/ 974d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFromOptions(SNES snes) 975d71ae5a4SJacob Faibussowitsch { 9768afaa268SBarry Smith PetscBool flg, pcset, persist, set; 97777e5a1f9SBarry Smith PetscInt i, indx, lag, grids, max_its, max_funcs; 97804d7464bSBarry Smith const char *deft = SNESNEWTONLS; 979649ef022SMatthew Knepley const char *convtests[] = {"default", "skip", "correct_pressure"}; 98085385478SLisandro Dalcin SNESKSPEW *kctx = NULL; 9810f0abf79SStefano Zampini char type[256], monfilename[PETSC_MAX_PATH_LEN], ewprefix[256]; 982c40d0f55SPeter Brune PCSide pcside; 983a64e098fSPeter Brune const char *optionsprefix; 98477e5a1f9SBarry Smith PetscReal rtol, abstol, stol; 9859b94acceSBarry Smith 9863a40ed3dSBarry Smith PetscFunctionBegin; 9870700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 9889566063dSJacob Faibussowitsch PetscCall(SNESRegisterAll()); 989d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)snes); 990639ff905SBarry Smith if (((PetscObject)snes)->type_name) deft = ((PetscObject)snes)->type_name; 9919566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-snes_type", "Nonlinear solver method", "SNESSetType", SNESList, deft, type, 256, &flg)); 992d64ed03dSBarry Smith if (flg) { 9939566063dSJacob Faibussowitsch PetscCall(SNESSetType(snes, type)); 9947adad957SLisandro Dalcin } else if (!((PetscObject)snes)->type_name) { 9959566063dSJacob Faibussowitsch PetscCall(SNESSetType(snes, deft)); 996d64ed03dSBarry Smith } 997186905e3SBarry Smith 99877e5a1f9SBarry Smith abstol = snes->abstol; 99977e5a1f9SBarry Smith rtol = snes->rtol; 100077e5a1f9SBarry Smith stol = snes->stol; 100177e5a1f9SBarry Smith max_its = snes->max_its; 100277e5a1f9SBarry Smith max_funcs = snes->max_funcs; 100377e5a1f9SBarry Smith PetscCall(PetscOptionsReal("-snes_rtol", "Stop if decrease in function norm less than", "SNESSetTolerances", snes->rtol, &rtol, NULL)); 100477e5a1f9SBarry Smith PetscCall(PetscOptionsReal("-snes_atol", "Stop if function norm less than", "SNESSetTolerances", snes->abstol, &abstol, NULL)); 100577e5a1f9SBarry Smith PetscCall(PetscOptionsReal("-snes_stol", "Stop if step length less than", "SNESSetTolerances", snes->stol, &stol, NULL)); 100677e5a1f9SBarry Smith PetscCall(PetscOptionsInt("-snes_max_it", "Maximum iterations", "SNESSetTolerances", snes->max_its, &max_its, NULL)); 100777e5a1f9SBarry Smith PetscCall(PetscOptionsInt("-snes_max_funcs", "Maximum function evaluations", "SNESSetTolerances", snes->max_funcs, &max_funcs, NULL)); 100877e5a1f9SBarry Smith PetscCall(SNESSetTolerances(snes, abstol, rtol, stol, max_its, max_funcs)); 100977e5a1f9SBarry Smith 101077e5a1f9SBarry Smith PetscCall(PetscOptionsReal("-snes_divergence_tolerance", "Stop if residual norm increases by this factor", "SNESSetDivergenceTolerance", snes->divtol, &snes->divtol, &flg)); 101177e5a1f9SBarry Smith if (flg) PetscCall(SNESSetDivergenceTolerance(snes, snes->divtol)); 101277e5a1f9SBarry Smith 101377e5a1f9SBarry Smith PetscCall(PetscOptionsInt("-snes_max_fail", "Maximum nonlinear step failures", "SNESSetMaxNonlinearStepFailures", snes->maxFailures, &snes->maxFailures, &flg)); 101477e5a1f9SBarry Smith if (flg) PetscCall(SNESSetMaxNonlinearStepFailures(snes, snes->maxFailures)); 101577e5a1f9SBarry Smith 101677e5a1f9SBarry Smith PetscCall(PetscOptionsInt("-snes_max_linear_solve_fail", "Maximum failures in linear solves allowed", "SNESSetMaxLinearSolveFailures", snes->maxLinearSolveFailures, &snes->maxLinearSolveFailures, &flg)); 101777e5a1f9SBarry Smith if (flg) PetscCall(SNESSetMaxLinearSolveFailures(snes, snes->maxLinearSolveFailures)); 101877e5a1f9SBarry Smith 10199566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_error_if_not_converged", "Generate error if solver does not converge", "SNESSetErrorIfNotConverged", snes->errorifnotconverged, &snes->errorifnotconverged, NULL)); 10209566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_force_iteration", "Force SNESSolve() to take at least one iteration", "SNESSetForceIteration", snes->forceiteration, &snes->forceiteration, NULL)); 10219566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_check_jacobian_domain_error", "Check Jacobian domain error after Jacobian evaluation", "SNESCheckJacobianDomainError", snes->checkjacdomainerror, &snes->checkjacdomainerror, NULL)); 102285385478SLisandro Dalcin 10239566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_lag_preconditioner", "How often to rebuild preconditioner", "SNESSetLagPreconditioner", snes->lagpreconditioner, &lag, &flg)); 1024a8054027SBarry Smith if (flg) { 10255f80ce2aSJacob 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"); 10269566063dSJacob Faibussowitsch PetscCall(SNESSetLagPreconditioner(snes, lag)); 1027a8054027SBarry Smith } 10289566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_lag_preconditioner_persists", "Preconditioner lagging through multiple SNES solves", "SNESSetLagPreconditionerPersists", snes->lagjac_persist, &persist, &flg)); 10291baa6e33SBarry Smith if (flg) PetscCall(SNESSetLagPreconditionerPersists(snes, persist)); 10309566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_lag_jacobian", "How often to rebuild Jacobian", "SNESSetLagJacobian", snes->lagjacobian, &lag, &flg)); 1031e35cf81dSBarry Smith if (flg) { 10325f80ce2aSJacob 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"); 10339566063dSJacob Faibussowitsch PetscCall(SNESSetLagJacobian(snes, lag)); 1034e35cf81dSBarry Smith } 10359566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_lag_jacobian_persists", "Jacobian lagging through multiple SNES solves", "SNESSetLagJacobianPersists", snes->lagjac_persist, &persist, &flg)); 10361baa6e33SBarry Smith if (flg) PetscCall(SNESSetLagJacobianPersists(snes, persist)); 103737ec4e1aSPeter Brune 10389566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_grid_sequence", "Use grid sequencing to generate initial guess", "SNESSetGridSequence", snes->gridsequence, &grids, &flg)); 10391baa6e33SBarry Smith if (flg) PetscCall(SNESSetGridSequence(snes, grids)); 1040a8054027SBarry Smith 1041400f6f02SBarry Smith PetscCall(PetscOptionsEList("-snes_convergence_test", "Convergence test", "SNESSetConvergenceTest", convtests, PETSC_STATIC_ARRAY_LENGTH(convtests), "default", &indx, &flg)); 104285385478SLisandro Dalcin if (flg) { 104385385478SLisandro Dalcin switch (indx) { 1044d71ae5a4SJacob Faibussowitsch case 0: 1045d71ae5a4SJacob Faibussowitsch PetscCall(SNESSetConvergenceTest(snes, SNESConvergedDefault, NULL, NULL)); 1046d71ae5a4SJacob Faibussowitsch break; 1047d71ae5a4SJacob Faibussowitsch case 1: 1048d71ae5a4SJacob Faibussowitsch PetscCall(SNESSetConvergenceTest(snes, SNESConvergedSkip, NULL, NULL)); 1049d71ae5a4SJacob Faibussowitsch break; 1050d71ae5a4SJacob Faibussowitsch case 2: 1051d71ae5a4SJacob Faibussowitsch PetscCall(SNESSetConvergenceTest(snes, SNESConvergedCorrectPressure, NULL, NULL)); 1052d71ae5a4SJacob Faibussowitsch break; 105385385478SLisandro Dalcin } 105485385478SLisandro Dalcin } 105585385478SLisandro Dalcin 10569566063dSJacob Faibussowitsch PetscCall(PetscOptionsEList("-snes_norm_schedule", "SNES Norm schedule", "SNESSetNormSchedule", SNESNormSchedules, 5, "function", &indx, &flg)); 10579566063dSJacob Faibussowitsch if (flg) PetscCall(SNESSetNormSchedule(snes, (SNESNormSchedule)indx)); 1058fdacfa88SPeter Brune 10599566063dSJacob Faibussowitsch PetscCall(PetscOptionsEList("-snes_function_type", "SNES Norm schedule", "SNESSetFunctionType", SNESFunctionTypes, 2, "unpreconditioned", &indx, &flg)); 10609566063dSJacob Faibussowitsch if (flg) PetscCall(SNESSetFunctionType(snes, (SNESFunctionType)indx)); 1061186905e3SBarry Smith 106285385478SLisandro Dalcin kctx = (SNESKSPEW *)snes->kspconvctx; 106385385478SLisandro Dalcin 10649566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_ksp_ew", "Use Eisentat-Walker linear system convergence test", "SNESKSPSetUseEW", snes->ksp_ewconv, &snes->ksp_ewconv, NULL)); 1065186905e3SBarry Smith 10660f0abf79SStefano Zampini PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 10670f0abf79SStefano Zampini PetscCall(PetscSNPrintf(ewprefix, sizeof(ewprefix), "%s%s", optionsprefix ? optionsprefix : "", "snes_")); 1068a4598233SStefano Zampini PetscCall(SNESEWSetFromOptions_Private(kctx, PETSC_TRUE, PetscObjectComm((PetscObject)snes), ewprefix)); 1069186905e3SBarry Smith 107090d69ab7SBarry Smith flg = PETSC_FALSE; 10719566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_monitor_cancel", "Remove all monitors", "SNESMonitorCancel", flg, &flg, &set)); 10729566063dSJacob Faibussowitsch if (set && flg) PetscCall(SNESMonitorCancel(snes)); 1073eabae89aSBarry Smith 10749566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor", "Monitor norm of function", "SNESMonitorDefault", SNESMonitorDefault, SNESMonitorDefaultSetUp)); 10759566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_short", "Monitor norm of function with fewer digits", "SNESMonitorDefaultShort", SNESMonitorDefaultShort, NULL)); 10769566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_range", "Monitor range of elements of function", "SNESMonitorRange", SNESMonitorRange, NULL)); 1077eabae89aSBarry Smith 10789566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_ratio", "Monitor ratios of the norm of function for consecutive steps", "SNESMonitorRatio", SNESMonitorRatio, SNESMonitorRatioSetUp)); 10799566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_field", "Monitor norm of function (split into fields)", "SNESMonitorDefaultField", SNESMonitorDefaultField, NULL)); 10809566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution", "View solution at each iteration", "SNESMonitorSolution", SNESMonitorSolution, NULL)); 10819566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution_update", "View correction at each iteration", "SNESMonitorSolutionUpdate", SNESMonitorSolutionUpdate, NULL)); 10829566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_residual", "View residual at each iteration", "SNESMonitorResidual", SNESMonitorResidual, NULL)); 10839566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_jacupdate_spectrum", "Print the change in the spectrum of the Jacobian", "SNESMonitorJacUpdateSpectrum", SNESMonitorJacUpdateSpectrum, NULL)); 10849566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_fields", "Monitor norm of function per field", "SNESMonitorSet", SNESMonitorFields, NULL)); 10859566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_monitor_pause_final", "Pauses all draw monitors at the final iterate", "SNESMonitorPauseFinal_Internal", PETSC_FALSE, &snes->pauseFinal, NULL)); 10862db13446SMatthew G. Knepley 10879566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-snes_monitor_python", "Use Python function", "SNESMonitorSet", NULL, monfilename, sizeof(monfilename), &flg)); 10889566063dSJacob Faibussowitsch if (flg) PetscCall(PetscPythonMonitorSet((PetscObject)snes, monfilename)); 10895180491cSLisandro Dalcin 109090d69ab7SBarry Smith flg = PETSC_FALSE; 10919566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_monitor_lg_range", "Plot function range at each iteration", "SNESMonitorLGRange", flg, &flg, NULL)); 1092459f5d12SBarry Smith if (flg) { 1093459f5d12SBarry Smith PetscViewer ctx; 1094e24b481bSBarry Smith 10959566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &ctx)); 109649abdd8aSBarry Smith PetscCall(SNESMonitorSet(snes, SNESMonitorLGRange, ctx, (PetscCtxDestroyFn *)PetscViewerDestroy)); 1097459f5d12SBarry Smith } 10982e7541e6SPeter Brune 1099648c30bcSBarry Smith PetscCall(PetscViewerDestroy(&snes->convergedreasonviewer)); 1100648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_converged_reason", &snes->convergedreasonviewer, &snes->convergedreasonformat, NULL)); 110190d69ab7SBarry Smith flg = PETSC_FALSE; 11029566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_converged_reason_view_cancel", "Remove all converged reason viewers", "SNESConvergedReasonViewCancel", flg, &flg, &set)); 11039566063dSJacob Faibussowitsch if (set && flg) PetscCall(SNESConvergedReasonViewCancel(snes)); 1104c4421ceaSFande Kong 1105c4421ceaSFande Kong flg = PETSC_FALSE; 11069566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_fd", "Use finite differences (slow) to compute Jacobian", "SNESComputeJacobianDefault", flg, &flg, NULL)); 11074b27c08aSLois Curfman McInnes if (flg) { 11086cab3a1bSJed Brown void *functx; 1109b1f624c7SBarry Smith DM dm; 11109566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 1111800f99ffSJeremy L Thompson PetscCall(DMSNESUnsetJacobianContext_Internal(dm)); 11129566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, NULL, &functx)); 11139566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefault, functx)); 11149566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Setting default finite difference Jacobian matrix\n")); 11159b94acceSBarry Smith } 1116639f9d9dSBarry Smith 111744848bc4SPeter Brune flg = PETSC_FALSE; 11189566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_fd_function", "Use finite differences (slow) to compute function from user objective", "SNESObjectiveComputeFunctionDefaultFD", flg, &flg, NULL)); 11191baa6e33SBarry Smith if (flg) PetscCall(SNESSetFunction(snes, NULL, SNESObjectiveComputeFunctionDefaultFD, NULL)); 112097584545SPeter Brune 112197584545SPeter Brune flg = PETSC_FALSE; 11229566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_fd_color", "Use finite differences with coloring to compute Jacobian", "SNESComputeJacobianDefaultColor", flg, &flg, NULL)); 112344848bc4SPeter Brune if (flg) { 1124c52e227fSPeter Brune DM dm; 11259566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 1126800f99ffSJeremy L Thompson PetscCall(DMSNESUnsetJacobianContext_Internal(dm)); 11279566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefaultColor, NULL)); 11289566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Setting default finite difference coloring Jacobian matrix\n")); 112944848bc4SPeter Brune } 113044848bc4SPeter Brune 1131aa3661deSLisandro Dalcin flg = PETSC_FALSE; 11327addb90fSBarry 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)); 1133d8f46077SPeter Brune if (flg && snes->mf_operator) { 1134a8248277SBarry Smith snes->mf_operator = PETSC_TRUE; 1135d8f46077SPeter Brune snes->mf = PETSC_TRUE; 1136a8248277SBarry Smith } 1137aa3661deSLisandro Dalcin flg = PETSC_FALSE; 11387addb90fSBarry Smith PetscCall(PetscOptionsBool("-snes_mf", "Use a Matrix-Free Jacobian with no matrix for computing the preconditioner", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf, &flg)); 1139d8f46077SPeter Brune if (!flg && snes->mf_operator) snes->mf = PETSC_TRUE; 11409566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_mf_version", "Matrix-Free routines version 1 or 2", "None", snes->mf_version, &snes->mf_version, NULL)); 1141d28543b3SPeter Brune 11421dfd7622SMatthew Knepley PetscCall(PetscOptionsName("-snes_test_function", "Compare hand-coded and finite difference functions", "None", &snes->testFunc)); 11431dfd7622SMatthew Knepley PetscCall(PetscOptionsName("-snes_test_jacobian", "Compare hand-coded and finite difference Jacobians", "None", &snes->testJac)); 11441dfd7622SMatthew Knepley 1145c40d0f55SPeter Brune flg = PETSC_FALSE; 11469566063dSJacob Faibussowitsch PetscCall(SNESGetNPCSide(snes, &pcside)); 11479566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-snes_npc_side", "SNES nonlinear preconditioner side", "SNESSetNPCSide", PCSides, (PetscEnum)pcside, (PetscEnum *)&pcside, &flg)); 11489566063dSJacob Faibussowitsch if (flg) PetscCall(SNESSetNPCSide(snes, pcside)); 1149c40d0f55SPeter Brune 1150e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS) 11518a70d858SHong Zhang /* 11528a70d858SHong Zhang Publish convergence information using SAWs 11538a70d858SHong Zhang */ 11548a70d858SHong Zhang flg = PETSC_FALSE; 11559566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_monitor_saws", "Publish SNES progress using SAWs", "SNESMonitorSet", flg, &flg, NULL)); 11568a70d858SHong Zhang if (flg) { 11578a70d858SHong Zhang void *ctx; 11589566063dSJacob Faibussowitsch PetscCall(SNESMonitorSAWsCreate(snes, &ctx)); 11599566063dSJacob Faibussowitsch PetscCall(SNESMonitorSet(snes, SNESMonitorSAWs, ctx, SNESMonitorSAWsDestroy)); 11608a70d858SHong Zhang } 11618a70d858SHong Zhang #endif 11628a70d858SHong Zhang #if defined(PETSC_HAVE_SAWS) 1163b90c6cbeSBarry Smith { 1164b90c6cbeSBarry Smith PetscBool set; 1165b90c6cbeSBarry Smith flg = PETSC_FALSE; 11669566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_saws_block", "Block for SAWs at end of SNESSolve", "PetscObjectSAWsBlock", ((PetscObject)snes)->amspublishblock, &flg, &set)); 11671baa6e33SBarry Smith if (set) PetscCall(PetscObjectSAWsSetBlock((PetscObject)snes, flg)); 1168b90c6cbeSBarry Smith } 1169b90c6cbeSBarry Smith #endif 1170b90c6cbeSBarry Smith 117148a46eb9SPierre Jolivet for (i = 0; i < numberofsetfromoptions; i++) PetscCall((*othersetfromoptions[i])(snes)); 117276b2cf59SMatthew Knepley 1173dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, setfromoptions, PetscOptionsObject); 11745d973c19SBarry Smith 11755d973c19SBarry Smith /* process any options handlers added with PetscObjectAddOptionsHandler() */ 1176dbbe0bcdSBarry Smith PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)snes, PetscOptionsObject)); 1177d0609cedSBarry Smith PetscOptionsEnd(); 11784bbc92c1SBarry Smith 1179d8d34be6SBarry Smith if (snes->linesearch) { 11809566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 11819566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetFromOptions(snes->linesearch)); 1182d8d34be6SBarry Smith } 11839e764e56SPeter Brune 11846aa5e7e9SBarry Smith if (snes->usesksp) { 11859566063dSJacob Faibussowitsch if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 11869566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(snes->ksp, snes->jacobian, snes->jacobian_pre)); 11879566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(snes->ksp)); 11886aa5e7e9SBarry Smith } 11896991f827SBarry Smith 1190b5badacbSBarry Smith /* if user has set the SNES NPC type via options database, create it. */ 11919566063dSJacob Faibussowitsch PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 11929566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)snes)->options, optionsprefix, "-npc_snes_type", &pcset)); 119348a46eb9SPierre Jolivet if (pcset && (!snes->npc)) PetscCall(SNESGetNPC(snes, &snes->npc)); 11941baa6e33SBarry Smith if (snes->npc) PetscCall(SNESSetFromOptions(snes->npc)); 1195b3cd9a81SMatthew G. Knepley snes->setfromoptionscalled++; 11963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1197b3cd9a81SMatthew G. Knepley } 1198b3cd9a81SMatthew G. Knepley 1199b3cd9a81SMatthew G. Knepley /*@ 1200420bcc1bSBarry Smith SNESResetFromOptions - Sets various `SNES` and `KSP` parameters from user options ONLY if the `SNESSetFromOptions()` was previously called 1201b3cd9a81SMatthew G. Knepley 1202c3339decSBarry Smith Collective 1203b3cd9a81SMatthew G. Knepley 1204b3cd9a81SMatthew G. Knepley Input Parameter: 1205f6dfbefdSBarry Smith . snes - the `SNES` context 1206b3cd9a81SMatthew G. Knepley 1207420bcc1bSBarry Smith Level: advanced 1208b3cd9a81SMatthew G. Knepley 12091cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESSetOptionsPrefix()` 1210b3cd9a81SMatthew G. Knepley @*/ 1211d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESResetFromOptions(SNES snes) 1212d71ae5a4SJacob Faibussowitsch { 1213b3cd9a81SMatthew G. Knepley PetscFunctionBegin; 12149566063dSJacob Faibussowitsch if (snes->setfromoptionscalled) PetscCall(SNESSetFromOptions(snes)); 12153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12169b94acceSBarry Smith } 12179b94acceSBarry Smith 1218bb9467b5SJed Brown /*@C 1219d25893d9SBarry Smith SNESSetComputeApplicationContext - Sets an optional function to compute a user-defined context for 1220d25893d9SBarry Smith the nonlinear solvers. 1221d25893d9SBarry Smith 1222dc4c0fb0SBarry Smith Logically Collective; No Fortran Support 1223d25893d9SBarry Smith 1224d25893d9SBarry Smith Input Parameters: 1225f6dfbefdSBarry Smith + snes - the `SNES` context 1226d25893d9SBarry Smith . compute - function to compute the context 122749abdd8aSBarry Smith - destroy - function to destroy the context, see `PetscCtxDestroyFn` for the calling sequence 1228d25893d9SBarry Smith 1229420bcc1bSBarry Smith Calling sequence of `compute`: 1230420bcc1bSBarry Smith + snes - the `SNES` context 1231420bcc1bSBarry Smith - ctx - context to be computed 1232420bcc1bSBarry Smith 1233d25893d9SBarry Smith Level: intermediate 1234d25893d9SBarry Smith 1235f6dfbefdSBarry Smith Note: 1236f6dfbefdSBarry Smith This routine is useful if you are performing grid sequencing or using `SNESFAS` and need the appropriate context generated for each level. 1237f6dfbefdSBarry Smith 1238f6dfbefdSBarry Smith Use `SNESSetApplicationContext()` to see the context immediately 1239f6dfbefdSBarry Smith 124049abdd8aSBarry Smith .seealso: [](ch_snes), `SNESGetApplicationContext()`, `SNESSetApplicationContext()`, `PetscCtxDestroyFn` 1241d25893d9SBarry Smith @*/ 124249abdd8aSBarry Smith PetscErrorCode SNESSetComputeApplicationContext(SNES snes, PetscErrorCode (*compute)(SNES snes, void **ctx), PetscCtxDestroyFn *destroy) 1243d71ae5a4SJacob Faibussowitsch { 1244d25893d9SBarry Smith PetscFunctionBegin; 1245d25893d9SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1246d25893d9SBarry Smith snes->ops->usercompute = compute; 124749abdd8aSBarry Smith snes->ops->ctxdestroy = destroy; 12483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1249d25893d9SBarry Smith } 1250a847f771SSatish Balay 1251b07ff414SBarry Smith /*@ 1252f6dfbefdSBarry Smith SNESSetApplicationContext - Sets the optional user-defined context for the nonlinear solvers. 12539b94acceSBarry Smith 1254c3339decSBarry Smith Logically Collective 1255fee21e36SBarry Smith 1256c7afd0dbSLois Curfman McInnes Input Parameters: 1257f6dfbefdSBarry Smith + snes - the `SNES` context 1258ce78bad3SBarry Smith - ctx - the user context 1259c7afd0dbSLois Curfman McInnes 126036851e7fSLois Curfman McInnes Level: intermediate 126136851e7fSLois Curfman McInnes 1262f6dfbefdSBarry Smith Notes: 1263ce78bad3SBarry Smith Users can provide a context when constructing the `SNES` options and then access it inside their function, Jacobian computation, or other evaluation function 1264f6dfbefdSBarry Smith with `SNESGetApplicationContext()` 1265f6dfbefdSBarry Smith 1266f6dfbefdSBarry Smith To provide a function that computes the context for you use `SNESSetComputeApplicationContext()` 1267f6dfbefdSBarry Smith 1268420bcc1bSBarry Smith Fortran Note: 1269ce78bad3SBarry 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 1270ce78bad3SBarry Smith function that tells the Fortran compiler the derived data type that is passed in as the `ctx` argument. See `SNESGetApplicationContext()` for 1271ce78bad3SBarry Smith an example. 1272daf670e6SBarry Smith 12731cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetComputeApplicationContext()`, `SNESGetApplicationContext()` 12749b94acceSBarry Smith @*/ 127549abdd8aSBarry Smith PetscErrorCode SNESSetApplicationContext(SNES snes, void *ctx) 1276d71ae5a4SJacob Faibussowitsch { 1277b07ff414SBarry Smith KSP ksp; 12781b2093e4SBarry Smith 12793a40ed3dSBarry Smith PetscFunctionBegin; 12800700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 12819566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 128249abdd8aSBarry Smith PetscCall(KSPSetApplicationContext(ksp, ctx)); 128349abdd8aSBarry Smith snes->ctx = ctx; 12843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12859b94acceSBarry Smith } 128674679c65SBarry Smith 1287b07ff414SBarry Smith /*@ 12889b94acceSBarry Smith SNESGetApplicationContext - Gets the user-defined context for the 1289420bcc1bSBarry Smith nonlinear solvers set with `SNESGetApplicationContext()` or `SNESSetComputeApplicationContext()` 12909b94acceSBarry Smith 1291c7afd0dbSLois Curfman McInnes Not Collective 1292c7afd0dbSLois Curfman McInnes 12939b94acceSBarry Smith Input Parameter: 1294f6dfbefdSBarry Smith . snes - `SNES` context 12959b94acceSBarry Smith 12969b94acceSBarry Smith Output Parameter: 129749abdd8aSBarry Smith . ctx - user context 12989b94acceSBarry Smith 129936851e7fSLois Curfman McInnes Level: intermediate 130036851e7fSLois Curfman McInnes 1301ce78bad3SBarry Smith Fortran Notes: 1302ce78bad3SBarry Smith This only works when the context is a Fortran derived type (it cannot be a `PetscObject`) and you **must** write a Fortran interface definition for this 1303ce78bad3SBarry Smith function that tells the Fortran compiler the derived data type that is returned as the `ctx` argument. For example, 1304ce78bad3SBarry Smith .vb 1305ce78bad3SBarry Smith Interface SNESGetApplicationContext 1306ce78bad3SBarry Smith Subroutine SNESGetApplicationContext(snes,ctx,ierr) 1307ce78bad3SBarry Smith #include <petsc/finclude/petscsnes.h> 1308ce78bad3SBarry Smith use petscsnes 1309ce78bad3SBarry Smith SNES snes 1310ce78bad3SBarry Smith type(tUsertype), pointer :: ctx 1311ce78bad3SBarry Smith PetscErrorCode ierr 1312ce78bad3SBarry Smith End Subroutine 1313ce78bad3SBarry Smith End Interface SNESGetApplicationContext 1314ce78bad3SBarry Smith .ve 1315ce78bad3SBarry Smith 1316bfe80ac4SPierre Jolivet The prototype for `ctx` must be 1317ce78bad3SBarry Smith .vb 1318ce78bad3SBarry Smith type(tUsertype), pointer :: ctx 1319ce78bad3SBarry Smith .ve 1320dc4c0fb0SBarry Smith 1321420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESSetApplicationContext()`, `SNESSetComputeApplicationContext()` 13229b94acceSBarry Smith @*/ 1323ce78bad3SBarry Smith PetscErrorCode SNESGetApplicationContext(SNES snes, PeCtx ctx) 1324d71ae5a4SJacob Faibussowitsch { 13253a40ed3dSBarry Smith PetscFunctionBegin; 13260700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 132749abdd8aSBarry Smith *(void **)ctx = snes->ctx; 13283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13299b94acceSBarry Smith } 133074679c65SBarry Smith 13319b94acceSBarry Smith /*@ 1332420bcc1bSBarry Smith SNESSetUseMatrixFree - indicates that `SNES` should use matrix-free finite difference matrix-vector products to apply the Jacobian. 13333565c898SBarry Smith 1334dc4c0fb0SBarry Smith Logically Collective 13353565c898SBarry Smith 13363565c898SBarry Smith Input Parameters: 1337f6dfbefdSBarry Smith + snes - `SNES` context 1338f6dfbefdSBarry Smith . mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used 1339f6dfbefdSBarry 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 1340420bcc1bSBarry Smith this option no matrix-element based preconditioners can be used in the linear solve since the matrix won't be explicitly available 13413565c898SBarry Smith 1342f6dfbefdSBarry Smith Options Database Keys: 134301c1178eSBarry Smith + -snes_mf_operator - use matrix-free only for the mat operator 1344f6dfbefdSBarry Smith . -snes_mf - use matrix-free for both the mat and pmat operator 1345ec5066bdSBarry Smith . -snes_fd_color - compute the Jacobian via coloring and finite differences. 1346ec5066bdSBarry Smith - -snes_fd - compute the Jacobian via finite differences (slow) 13473565c898SBarry Smith 13483565c898SBarry Smith Level: intermediate 13493565c898SBarry Smith 1350f6dfbefdSBarry Smith Note: 1351420bcc1bSBarry Smith `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`, 1352420bcc1bSBarry Smith and computing explicitly with 1353f6dfbefdSBarry Smith finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object. 1354ec5066bdSBarry Smith 1355420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetUseMatrixFree()`, `MatCreateSNESMF()`, `SNESComputeJacobianDefaultColor()`, `MatFDColoring` 13563565c898SBarry Smith @*/ 1357d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUseMatrixFree(SNES snes, PetscBool mf_operator, PetscBool mf) 1358d71ae5a4SJacob Faibussowitsch { 13593565c898SBarry Smith PetscFunctionBegin; 13603565c898SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 136188b4c220SStefano Zampini PetscValidLogicalCollectiveBool(snes, mf_operator, 2); 136288b4c220SStefano Zampini PetscValidLogicalCollectiveBool(snes, mf, 3); 13634ddffce6SLisandro Dalcin snes->mf = mf_operator ? PETSC_TRUE : mf; 13643565c898SBarry Smith snes->mf_operator = mf_operator; 13653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13663565c898SBarry Smith } 13673565c898SBarry Smith 13683565c898SBarry Smith /*@ 1369dc4c0fb0SBarry Smith SNESGetUseMatrixFree - indicates if the `SNES` uses matrix-free finite difference matrix vector products to apply the Jacobian. 13703565c898SBarry Smith 1371420bcc1bSBarry Smith Not Collective, but the resulting flags will be the same on all MPI processes 13723565c898SBarry Smith 13733565c898SBarry Smith Input Parameter: 1374f6dfbefdSBarry Smith . snes - `SNES` context 13753565c898SBarry Smith 13763565c898SBarry Smith Output Parameters: 1377f6dfbefdSBarry Smith + mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used 1378f6dfbefdSBarry 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 13793565c898SBarry Smith 13803565c898SBarry Smith Level: intermediate 13813565c898SBarry Smith 13821cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUseMatrixFree()`, `MatCreateSNESMF()` 13833565c898SBarry Smith @*/ 1384d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUseMatrixFree(SNES snes, PetscBool *mf_operator, PetscBool *mf) 1385d71ae5a4SJacob Faibussowitsch { 13863565c898SBarry Smith PetscFunctionBegin; 13873565c898SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 13883565c898SBarry Smith if (mf) *mf = snes->mf; 13893565c898SBarry Smith if (mf_operator) *mf_operator = snes->mf_operator; 13903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13913565c898SBarry Smith } 13923565c898SBarry Smith 13933565c898SBarry Smith /*@ 1394420bcc1bSBarry Smith SNESGetIterationNumber - Gets the number of nonlinear iterations completed in the current or most recent `SNESSolve()` 13959b94acceSBarry Smith 1396c7afd0dbSLois Curfman McInnes Not Collective 1397c7afd0dbSLois Curfman McInnes 13989b94acceSBarry Smith Input Parameter: 1399f6dfbefdSBarry Smith . snes - `SNES` context 14009b94acceSBarry Smith 14019b94acceSBarry Smith Output Parameter: 14029b94acceSBarry Smith . iter - iteration number 14039b94acceSBarry Smith 1404dc4c0fb0SBarry Smith Level: intermediate 1405dc4c0fb0SBarry Smith 1406c8228a4eSBarry Smith Notes: 1407c8228a4eSBarry Smith For example, during the computation of iteration 2 this would return 1. 1408c8228a4eSBarry Smith 1409c8228a4eSBarry Smith This is useful for using lagged Jacobians (where one does not recompute the 1410f6dfbefdSBarry Smith Jacobian at each `SNES` iteration). For example, the code 141108405cd6SLois Curfman McInnes .vb 141208405cd6SLois Curfman McInnes ierr = SNESGetIterationNumber(snes,&it); 141308405cd6SLois Curfman McInnes if (!(it % 2)) { 141408405cd6SLois Curfman McInnes [compute Jacobian here] 141508405cd6SLois Curfman McInnes } 141608405cd6SLois Curfman McInnes .ve 1417f6dfbefdSBarry Smith can be used in your function that computes the Jacobian to cause the Jacobian to be 1418f6dfbefdSBarry Smith recomputed every second `SNES` iteration. See also `SNESSetLagJacobian()` 1419c8228a4eSBarry Smith 1420f6dfbefdSBarry Smith After the `SNES` solve is complete this will return the number of nonlinear iterations used. 1421c04deec6SBarry Smith 1422420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetLagJacobian()`, `SNESGetLinearSolveIterations()`, `SNESSetMonitor()` 14239b94acceSBarry Smith @*/ 1424d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetIterationNumber(SNES snes, PetscInt *iter) 1425d71ae5a4SJacob Faibussowitsch { 14263a40ed3dSBarry Smith PetscFunctionBegin; 14270700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 14284f572ea9SToby Isaac PetscAssertPointer(iter, 2); 14299b94acceSBarry Smith *iter = snes->iter; 14303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14319b94acceSBarry Smith } 143274679c65SBarry Smith 1433360c497dSPeter Brune /*@ 1434360c497dSPeter Brune SNESSetIterationNumber - Sets the current iteration number. 1435360c497dSPeter Brune 1436360c497dSPeter Brune Not Collective 1437360c497dSPeter Brune 1438d8d19677SJose E. Roman Input Parameters: 1439f6dfbefdSBarry Smith + snes - `SNES` context 1440a2b725a8SWilliam Gropp - iter - iteration number 1441360c497dSPeter Brune 1442360c497dSPeter Brune Level: developer 1443360c497dSPeter Brune 1444420bcc1bSBarry Smith Note: 1445420bcc1bSBarry Smith This should only be called inside a `SNES` nonlinear solver. 1446420bcc1bSBarry Smith 14471cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetLinearSolveIterations()` 1448360c497dSPeter Brune @*/ 1449d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetIterationNumber(SNES snes, PetscInt iter) 1450d71ae5a4SJacob Faibussowitsch { 1451360c497dSPeter Brune PetscFunctionBegin; 1452360c497dSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 14539566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes)); 1454360c497dSPeter Brune snes->iter = iter; 14559566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes)); 14563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1457360c497dSPeter Brune } 1458360c497dSPeter Brune 14599b94acceSBarry Smith /*@ 1460b850b91aSLisandro Dalcin SNESGetNonlinearStepFailures - Gets the number of unsuccessful steps 1461420bcc1bSBarry Smith attempted by the nonlinear solver in the current or most recent `SNESSolve()` . 14629b94acceSBarry Smith 1463c7afd0dbSLois Curfman McInnes Not Collective 1464c7afd0dbSLois Curfman McInnes 14659b94acceSBarry Smith Input Parameter: 1466f6dfbefdSBarry Smith . snes - `SNES` context 14679b94acceSBarry Smith 14689b94acceSBarry Smith Output Parameter: 14699b94acceSBarry Smith . nfails - number of unsuccessful steps attempted 14709b94acceSBarry Smith 1471dc4c0fb0SBarry Smith Level: intermediate 1472dc4c0fb0SBarry Smith 1473f6dfbefdSBarry Smith Note: 1474f6dfbefdSBarry Smith This counter is reset to zero for each successive call to `SNESSolve()`. 1475c96a6f78SLois Curfman McInnes 14761cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, 1477db781477SPatrick Sanan `SNESSetMaxNonlinearStepFailures()`, `SNESGetMaxNonlinearStepFailures()` 14789b94acceSBarry Smith @*/ 1479d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNonlinearStepFailures(SNES snes, PetscInt *nfails) 1480d71ae5a4SJacob Faibussowitsch { 14813a40ed3dSBarry Smith PetscFunctionBegin; 14820700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 14834f572ea9SToby Isaac PetscAssertPointer(nfails, 2); 148450ffb88aSMatthew Knepley *nfails = snes->numFailures; 14853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 148650ffb88aSMatthew Knepley } 148750ffb88aSMatthew Knepley 148850ffb88aSMatthew Knepley /*@ 1489b850b91aSLisandro Dalcin SNESSetMaxNonlinearStepFailures - Sets the maximum number of unsuccessful steps 1490420bcc1bSBarry Smith attempted by the nonlinear solver before it gives up and returns unconverged or generates an error 149150ffb88aSMatthew Knepley 149250ffb88aSMatthew Knepley Not Collective 149350ffb88aSMatthew Knepley 149450ffb88aSMatthew Knepley Input Parameters: 1495f6dfbefdSBarry Smith + snes - `SNES` context 149677e5a1f9SBarry Smith - maxFails - maximum of unsuccessful steps allowed, use `PETSC_UNLIMITED` to have no limit on the number of failures 149750ffb88aSMatthew Knepley 1498420bcc1bSBarry Smith Options Database Key: 1499420bcc1bSBarry Smith . -snes_max_fail <n> - maximum number of unsuccessful steps allowed 1500420bcc1bSBarry Smith 150150ffb88aSMatthew Knepley Level: intermediate 150250ffb88aSMatthew Knepley 1503420bcc1bSBarry Smith Developer Note: 1504420bcc1bSBarry Smith The options database key is wrong for this function name 1505420bcc1bSBarry Smith 15061cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, 1507db781477SPatrick Sanan `SNESGetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()` 150850ffb88aSMatthew Knepley @*/ 1509d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxNonlinearStepFailures(SNES snes, PetscInt maxFails) 1510d71ae5a4SJacob Faibussowitsch { 151150ffb88aSMatthew Knepley PetscFunctionBegin; 15120700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 151377e5a1f9SBarry Smith 151477e5a1f9SBarry Smith if (maxFails == PETSC_UNLIMITED) { 15151690c2aeSBarry Smith snes->maxFailures = PETSC_INT_MAX; 151677e5a1f9SBarry Smith } else { 151777e5a1f9SBarry Smith PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures"); 151850ffb88aSMatthew Knepley snes->maxFailures = maxFails; 151977e5a1f9SBarry Smith } 15203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 152150ffb88aSMatthew Knepley } 152250ffb88aSMatthew Knepley 152350ffb88aSMatthew Knepley /*@ 1524b850b91aSLisandro Dalcin SNESGetMaxNonlinearStepFailures - Gets the maximum number of unsuccessful steps 1525420bcc1bSBarry Smith attempted by the nonlinear solver before it gives up and returns unconverged or generates an error 152650ffb88aSMatthew Knepley 152750ffb88aSMatthew Knepley Not Collective 152850ffb88aSMatthew Knepley 152950ffb88aSMatthew Knepley Input Parameter: 153020f4b53cSBarry Smith . snes - `SNES` context 153150ffb88aSMatthew Knepley 153250ffb88aSMatthew Knepley Output Parameter: 153350ffb88aSMatthew Knepley . maxFails - maximum of unsuccessful steps 153450ffb88aSMatthew Knepley 153550ffb88aSMatthew Knepley Level: intermediate 153650ffb88aSMatthew Knepley 15371cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, 1538db781477SPatrick Sanan `SNESSetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()` 153950ffb88aSMatthew Knepley @*/ 1540d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxNonlinearStepFailures(SNES snes, PetscInt *maxFails) 1541d71ae5a4SJacob Faibussowitsch { 154250ffb88aSMatthew Knepley PetscFunctionBegin; 15430700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 15444f572ea9SToby Isaac PetscAssertPointer(maxFails, 2); 154550ffb88aSMatthew Knepley *maxFails = snes->maxFailures; 15463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15479b94acceSBarry Smith } 1548a847f771SSatish Balay 15492541af92SBarry Smith /*@ 15502541af92SBarry Smith SNESGetNumberFunctionEvals - Gets the number of user provided function evaluations 1551420bcc1bSBarry Smith done by the `SNES` object in the current or most recent `SNESSolve()` 15522541af92SBarry Smith 15532541af92SBarry Smith Not Collective 15542541af92SBarry Smith 15552541af92SBarry Smith Input Parameter: 1556f6dfbefdSBarry Smith . snes - `SNES` context 15572541af92SBarry Smith 15582541af92SBarry Smith Output Parameter: 15592541af92SBarry Smith . nfuncs - number of evaluations 15602541af92SBarry Smith 15612541af92SBarry Smith Level: intermediate 15622541af92SBarry Smith 1563f6dfbefdSBarry Smith Note: 1564f6dfbefdSBarry Smith Reset every time `SNESSolve()` is called unless `SNESSetCountersReset()` is used. 1565971e163fSPeter Brune 15661cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, `SNESSetCountersReset()` 15672541af92SBarry Smith @*/ 1568d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNumberFunctionEvals(SNES snes, PetscInt *nfuncs) 1569d71ae5a4SJacob Faibussowitsch { 15702541af92SBarry Smith PetscFunctionBegin; 15710700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 15724f572ea9SToby Isaac PetscAssertPointer(nfuncs, 2); 15732541af92SBarry Smith *nfuncs = snes->nfuncs; 15743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15752541af92SBarry Smith } 15762541af92SBarry Smith 15773d4c4710SBarry Smith /*@ 15783d4c4710SBarry Smith SNESGetLinearSolveFailures - Gets the number of failed (non-converged) 1579420bcc1bSBarry Smith linear solvers in the current or most recent `SNESSolve()` 15803d4c4710SBarry Smith 15813d4c4710SBarry Smith Not Collective 15823d4c4710SBarry Smith 15833d4c4710SBarry Smith Input Parameter: 1584f6dfbefdSBarry Smith . snes - `SNES` context 15853d4c4710SBarry Smith 15863d4c4710SBarry Smith Output Parameter: 15873d4c4710SBarry Smith . nfails - number of failed solves 15883d4c4710SBarry Smith 1589f6dfbefdSBarry Smith Options Database Key: 15909d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated 15919d85da0cSMatthew G. Knepley 1592f6dfbefdSBarry Smith Level: intermediate 1593f6dfbefdSBarry Smith 1594f6dfbefdSBarry Smith Note: 1595f6dfbefdSBarry Smith This counter is reset to zero for each successive call to `SNESSolve()`. 15963d4c4710SBarry Smith 15971cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()` 15983d4c4710SBarry Smith @*/ 1599d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveFailures(SNES snes, PetscInt *nfails) 1600d71ae5a4SJacob Faibussowitsch { 16013d4c4710SBarry Smith PetscFunctionBegin; 16020700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 16034f572ea9SToby Isaac PetscAssertPointer(nfails, 2); 16043d4c4710SBarry Smith *nfails = snes->numLinearSolveFailures; 16053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16063d4c4710SBarry Smith } 16073d4c4710SBarry Smith 16083d4c4710SBarry Smith /*@ 16093d4c4710SBarry Smith SNESSetMaxLinearSolveFailures - the number of failed linear solve attempts 1610f6dfbefdSBarry Smith allowed before `SNES` returns with a diverged reason of `SNES_DIVERGED_LINEAR_SOLVE` 16113d4c4710SBarry Smith 1612c3339decSBarry Smith Logically Collective 16133d4c4710SBarry Smith 16143d4c4710SBarry Smith Input Parameters: 1615f6dfbefdSBarry Smith + snes - `SNES` context 161677e5a1f9SBarry Smith - maxFails - maximum allowed linear solve failures, use `PETSC_UNLIMITED` to have no limit on the number of failures 16173d4c4710SBarry Smith 1618f6dfbefdSBarry Smith Options Database Key: 16199d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated 16209d85da0cSMatthew G. Knepley 1621dc4c0fb0SBarry Smith Level: intermediate 1622dc4c0fb0SBarry Smith 1623f6dfbefdSBarry Smith Note: 1624f6dfbefdSBarry Smith By default this is 0; that is `SNES` returns on the first failed linear solve 16253d4c4710SBarry Smith 1626420bcc1bSBarry Smith Developer Note: 1627420bcc1bSBarry Smith The options database key is wrong for this function name 1628420bcc1bSBarry Smith 16291cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()` 16303d4c4710SBarry Smith @*/ 1631d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxLinearSolveFailures(SNES snes, PetscInt maxFails) 1632d71ae5a4SJacob Faibussowitsch { 16333d4c4710SBarry Smith PetscFunctionBegin; 16340700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1635c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, maxFails, 2); 163677e5a1f9SBarry Smith 163777e5a1f9SBarry Smith if (maxFails == PETSC_UNLIMITED) { 16381690c2aeSBarry Smith snes->maxLinearSolveFailures = PETSC_INT_MAX; 163977e5a1f9SBarry Smith } else { 164077e5a1f9SBarry Smith PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures"); 16413d4c4710SBarry Smith snes->maxLinearSolveFailures = maxFails; 164277e5a1f9SBarry Smith } 16433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16443d4c4710SBarry Smith } 16453d4c4710SBarry Smith 16463d4c4710SBarry Smith /*@ 16473d4c4710SBarry Smith SNESGetMaxLinearSolveFailures - gets the maximum number of linear solve failures that 1648f6dfbefdSBarry Smith are allowed before `SNES` returns as unsuccessful 16493d4c4710SBarry Smith 16503d4c4710SBarry Smith Not Collective 16513d4c4710SBarry Smith 16523d4c4710SBarry Smith Input Parameter: 1653f6dfbefdSBarry Smith . snes - `SNES` context 16543d4c4710SBarry Smith 16553d4c4710SBarry Smith Output Parameter: 16563d4c4710SBarry Smith . maxFails - maximum of unsuccessful solves allowed 16573d4c4710SBarry Smith 16583d4c4710SBarry Smith Level: intermediate 16593d4c4710SBarry Smith 1660f6dfbefdSBarry Smith Note: 1661f6dfbefdSBarry Smith By default this is 1; that is `SNES` returns on the first failed linear solve 16623d4c4710SBarry Smith 16631cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, 16643d4c4710SBarry Smith @*/ 1665d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxLinearSolveFailures(SNES snes, PetscInt *maxFails) 1666d71ae5a4SJacob Faibussowitsch { 16673d4c4710SBarry Smith PetscFunctionBegin; 16680700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 16694f572ea9SToby Isaac PetscAssertPointer(maxFails, 2); 16703d4c4710SBarry Smith *maxFails = snes->maxLinearSolveFailures; 16713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16723d4c4710SBarry Smith } 16733d4c4710SBarry Smith 1674c96a6f78SLois Curfman McInnes /*@ 1675b850b91aSLisandro Dalcin SNESGetLinearSolveIterations - Gets the total number of linear iterations 1676420bcc1bSBarry Smith used by the nonlinear solver in the most recent `SNESSolve()` 1677c96a6f78SLois Curfman McInnes 1678c7afd0dbSLois Curfman McInnes Not Collective 1679c7afd0dbSLois Curfman McInnes 1680c96a6f78SLois Curfman McInnes Input Parameter: 1681f6dfbefdSBarry Smith . snes - `SNES` context 1682c96a6f78SLois Curfman McInnes 1683c96a6f78SLois Curfman McInnes Output Parameter: 1684c96a6f78SLois Curfman McInnes . lits - number of linear iterations 1685c96a6f78SLois Curfman McInnes 1686dc4c0fb0SBarry Smith Level: intermediate 1687dc4c0fb0SBarry Smith 1688c96a6f78SLois Curfman McInnes Notes: 1689f6dfbefdSBarry Smith This counter is reset to zero for each successive call to `SNESSolve()` unless `SNESSetCountersReset()` is used. 1690c96a6f78SLois Curfman McInnes 1691f6dfbefdSBarry Smith If the linear solver fails inside the `SNESSolve()` the iterations for that call to the linear solver are not included. If you wish to count them 1692f6dfbefdSBarry Smith then call `KSPGetIterationNumber()` after the failed solve. 1693010be392SBarry Smith 16941cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetIterationNumber()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESSetCountersReset()` 1695c96a6f78SLois Curfman McInnes @*/ 1696d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveIterations(SNES snes, PetscInt *lits) 1697d71ae5a4SJacob Faibussowitsch { 16983a40ed3dSBarry Smith PetscFunctionBegin; 16990700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 17004f572ea9SToby Isaac PetscAssertPointer(lits, 2); 1701c96a6f78SLois Curfman McInnes *lits = snes->linear_its; 17023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1703c96a6f78SLois Curfman McInnes } 1704c96a6f78SLois Curfman McInnes 1705971e163fSPeter Brune /*@ 1706971e163fSPeter Brune SNESSetCountersReset - Sets whether or not the counters for linear iterations and function evaluations 1707f6dfbefdSBarry Smith are reset every time `SNESSolve()` is called. 1708971e163fSPeter Brune 1709c3339decSBarry Smith Logically Collective 1710971e163fSPeter Brune 1711d8d19677SJose E. Roman Input Parameters: 1712f6dfbefdSBarry Smith + snes - `SNES` context 1713f6dfbefdSBarry Smith - reset - whether to reset the counters or not, defaults to `PETSC_TRUE` 1714971e163fSPeter Brune 1715971e163fSPeter Brune Level: developer 1716971e163fSPeter Brune 17171cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()` 1718971e163fSPeter Brune @*/ 1719d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCountersReset(SNES snes, PetscBool reset) 1720d71ae5a4SJacob Faibussowitsch { 1721971e163fSPeter Brune PetscFunctionBegin; 1722971e163fSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1723971e163fSPeter Brune PetscValidLogicalCollectiveBool(snes, reset, 2); 1724971e163fSPeter Brune snes->counters_reset = reset; 17253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1726971e163fSPeter Brune } 1727971e163fSPeter Brune 17282999313aSBarry Smith /*@ 172912b1dd1aSStefano Zampini SNESResetCounters - Reset counters for linear iterations and function evaluations. 173012b1dd1aSStefano Zampini 173112b1dd1aSStefano Zampini Logically Collective 173212b1dd1aSStefano Zampini 173312b1dd1aSStefano Zampini Input Parameters: 173412b1dd1aSStefano Zampini . snes - `SNES` context 173512b1dd1aSStefano Zampini 173612b1dd1aSStefano Zampini Level: developer 173712b1dd1aSStefano Zampini 173812b1dd1aSStefano Zampini Note: 173912b1dd1aSStefano Zampini It honors the flag set with `SNESSetCountersReset()` 174012b1dd1aSStefano Zampini 174112b1dd1aSStefano Zampini .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()` 174212b1dd1aSStefano Zampini @*/ 174312b1dd1aSStefano Zampini PetscErrorCode SNESResetCounters(SNES snes) 174412b1dd1aSStefano Zampini { 174512b1dd1aSStefano Zampini PetscFunctionBegin; 174612b1dd1aSStefano Zampini PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 174712b1dd1aSStefano Zampini if (snes->counters_reset) { 174812b1dd1aSStefano Zampini snes->nfuncs = 0; 174912b1dd1aSStefano Zampini snes->linear_its = 0; 175012b1dd1aSStefano Zampini snes->numFailures = 0; 175112b1dd1aSStefano Zampini } 175212b1dd1aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 175312b1dd1aSStefano Zampini } 175412b1dd1aSStefano Zampini 175512b1dd1aSStefano Zampini /*@ 1756f6dfbefdSBarry Smith SNESSetKSP - Sets a `KSP` context for the `SNES` object to use 17572999313aSBarry Smith 1758420bcc1bSBarry Smith Not Collective, but the `SNES` and `KSP` objects must live on the same `MPI_Comm` 17592999313aSBarry Smith 17602999313aSBarry Smith Input Parameters: 1761f6dfbefdSBarry Smith + snes - the `SNES` context 1762f6dfbefdSBarry Smith - ksp - the `KSP` context 17632999313aSBarry Smith 1764dc4c0fb0SBarry Smith Level: developer 1765dc4c0fb0SBarry Smith 17662999313aSBarry Smith Notes: 1767f6dfbefdSBarry Smith The `SNES` object already has its `KSP` object, you can obtain with `SNESGetKSP()` 17682999313aSBarry Smith so this routine is rarely needed. 17692999313aSBarry Smith 1770f6dfbefdSBarry Smith The `KSP` object that is already in the `SNES` object has its reference count 1771420bcc1bSBarry Smith decreased by one when this is called. 17722999313aSBarry Smith 177342747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `KSP`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()` 17742999313aSBarry Smith @*/ 1775d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetKSP(SNES snes, KSP ksp) 1776d71ae5a4SJacob Faibussowitsch { 17772999313aSBarry Smith PetscFunctionBegin; 17780700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 17790700a824SBarry Smith PetscValidHeaderSpecific(ksp, KSP_CLASSID, 2); 17802999313aSBarry Smith PetscCheckSameComm(snes, 1, ksp, 2); 17819566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)ksp)); 17829566063dSJacob Faibussowitsch if (snes->ksp) PetscCall(PetscObjectDereference((PetscObject)snes->ksp)); 17832999313aSBarry Smith snes->ksp = ksp; 17843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17852999313aSBarry Smith } 17862999313aSBarry Smith 178752baeb72SSatish Balay /*@ 178877e5a1f9SBarry Smith SNESParametersInitialize - Sets all the parameters in `snes` to their default value (when `SNESCreate()` was called) if they 178977e5a1f9SBarry Smith currently contain default values 179077e5a1f9SBarry Smith 179177e5a1f9SBarry Smith Collective 179277e5a1f9SBarry Smith 179377e5a1f9SBarry Smith Input Parameter: 179477e5a1f9SBarry Smith . snes - the `SNES` object 179577e5a1f9SBarry Smith 179677e5a1f9SBarry Smith Level: developer 179777e5a1f9SBarry Smith 179877e5a1f9SBarry Smith Developer Note: 179977e5a1f9SBarry Smith This is called by all the `SNESCreate_XXX()` routines. 180077e5a1f9SBarry Smith 180177e5a1f9SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`, 180277e5a1f9SBarry Smith `PetscObjectParameterSetDefault()` 180377e5a1f9SBarry Smith @*/ 180477e5a1f9SBarry Smith PetscErrorCode SNESParametersInitialize(SNES snes) 180577e5a1f9SBarry Smith { 180677e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, max_its, 50); 180777e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, max_funcs, 10000); 180877e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, rtol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8); 180977e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, abstol, PetscDefined(USE_REAL_SINGLE) ? 1.e-25 : 1.e-50); 181077e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, stol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8); 181177e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, divtol, 1.e4); 181277e5a1f9SBarry Smith return PETSC_SUCCESS; 181377e5a1f9SBarry Smith } 181477e5a1f9SBarry Smith 181577e5a1f9SBarry Smith /*@ 1816dc4c0fb0SBarry Smith SNESCreate - Creates a nonlinear solver context used to manage a set of nonlinear solves 18179b94acceSBarry Smith 1818d083f849SBarry Smith Collective 1819c7afd0dbSLois Curfman McInnes 1820f6dfbefdSBarry Smith Input Parameter: 1821906ed7ccSBarry Smith . comm - MPI communicator 18229b94acceSBarry Smith 18239b94acceSBarry Smith Output Parameter: 182420f4b53cSBarry Smith . outsnes - the new `SNES` context 18259b94acceSBarry Smith 1826c7afd0dbSLois Curfman McInnes Options Database Keys: 18277addb90fSBarry Smith + -snes_mf - Activates default matrix-free Jacobian-vector products, and no matrix to construct a preconditioner 18287addb90fSBarry Smith . -snes_mf_operator - Activates default matrix-free Jacobian-vector products, and a user-provided matrix as set by `SNESSetJacobian()` 1829dc4c0fb0SBarry Smith . -snes_fd_coloring - uses a relative fast computation of the Jacobian using finite differences and a graph coloring 1830c7afd0dbSLois Curfman McInnes - -snes_fd - Uses (slow!) finite differences to compute Jacobian 1831c1f60f51SBarry Smith 183236851e7fSLois Curfman McInnes Level: beginner 183336851e7fSLois Curfman McInnes 183495452b02SPatrick Sanan Developer Notes: 1835f6dfbefdSBarry Smith `SNES` always creates a `KSP` object even though many `SNES` methods do not use it. This is 1836efd4aadfSBarry Smith unfortunate and should be fixed at some point. The flag snes->usesksp indicates if the 1837f6dfbefdSBarry Smith particular method does use `KSP` and regulates if the information about the `KSP` is printed 1838f6dfbefdSBarry Smith in `SNESView()`. 1839efd4aadfSBarry Smith 1840f6dfbefdSBarry Smith `TSSetFromOptions()` does call `SNESSetFromOptions()` which can lead to users being confused 1841f6dfbefdSBarry Smith by help messages about meaningless `SNES` options. 1842f6dfbefdSBarry Smith 18437addb90fSBarry Smith `SNES` always creates the `snes->kspconvctx` even though it is used by only one type. This should be fixed. 1844efd4aadfSBarry Smith 1845e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()` 18469b94acceSBarry Smith @*/ 1847d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESCreate(MPI_Comm comm, SNES *outsnes) 1848d71ae5a4SJacob Faibussowitsch { 18499b94acceSBarry Smith SNES snes; 1850fa9f3622SBarry Smith SNESKSPEW *kctx; 185137fcc0dbSBarry Smith 18523a40ed3dSBarry Smith PetscFunctionBegin; 18534f572ea9SToby Isaac PetscAssertPointer(outsnes, 2); 18549566063dSJacob Faibussowitsch PetscCall(SNESInitializePackage()); 18558ba1e511SMatthew Knepley 18569566063dSJacob Faibussowitsch PetscCall(PetscHeaderCreate(snes, SNES_CLASSID, "SNES", "Nonlinear solver", "SNES", comm, SNESDestroy, SNESView)); 18578d359177SBarry Smith snes->ops->converged = SNESConvergedDefault; 18582c155ee1SBarry Smith snes->usesksp = PETSC_TRUE; 18599b94acceSBarry Smith snes->norm = 0.0; 1860c1e67a49SFande Kong snes->xnorm = 0.0; 1861c1e67a49SFande Kong snes->ynorm = 0.0; 1862365a6726SPeter Brune snes->normschedule = SNES_NORM_ALWAYS; 18636c67d002SPeter Brune snes->functype = SNES_FUNCTION_DEFAULT; 1864b4874afaSBarry Smith snes->ttol = 0.0; 186577e5a1f9SBarry Smith 1866e37c518bSBarry Smith snes->rnorm0 = 0; 18679b94acceSBarry Smith snes->nfuncs = 0; 186850ffb88aSMatthew Knepley snes->numFailures = 0; 186950ffb88aSMatthew Knepley snes->maxFailures = 1; 18707a00f4a9SLois Curfman McInnes snes->linear_its = 0; 1871e35cf81dSBarry Smith snes->lagjacobian = 1; 187237ec4e1aSPeter Brune snes->jac_iter = 0; 187337ec4e1aSPeter Brune snes->lagjac_persist = PETSC_FALSE; 1874a8054027SBarry Smith snes->lagpreconditioner = 1; 187537ec4e1aSPeter Brune snes->pre_iter = 0; 187637ec4e1aSPeter Brune snes->lagpre_persist = PETSC_FALSE; 1877639f9d9dSBarry Smith snes->numbermonitors = 0; 1878c4421ceaSFande Kong snes->numberreasonviews = 0; 18799e5d0892SLisandro Dalcin snes->data = NULL; 18804dc4c822SBarry Smith snes->setupcalled = PETSC_FALSE; 1881186905e3SBarry Smith snes->ksp_ewconv = PETSC_FALSE; 18826f24a144SLois Curfman McInnes snes->nwork = 0; 18839e5d0892SLisandro Dalcin snes->work = NULL; 188458c9b817SLisandro Dalcin snes->nvwork = 0; 18859e5d0892SLisandro Dalcin snes->vwork = NULL; 1886758f92a0SBarry Smith snes->conv_hist_len = 0; 1887758f92a0SBarry Smith snes->conv_hist_max = 0; 18880298fd71SBarry Smith snes->conv_hist = NULL; 18890298fd71SBarry Smith snes->conv_hist_its = NULL; 1890758f92a0SBarry Smith snes->conv_hist_reset = PETSC_TRUE; 1891971e163fSPeter Brune snes->counters_reset = PETSC_TRUE; 1892e4ed7901SPeter Brune snes->vec_func_init_set = PETSC_FALSE; 1893184914b5SBarry Smith snes->reason = SNES_CONVERGED_ITERATING; 1894efd4aadfSBarry Smith snes->npcside = PC_RIGHT; 1895b3cd9a81SMatthew G. Knepley snes->setfromoptionscalled = 0; 1896c40d0f55SPeter Brune 1897d8f46077SPeter Brune snes->mf = PETSC_FALSE; 1898d8f46077SPeter Brune snes->mf_operator = PETSC_FALSE; 1899d8f46077SPeter Brune snes->mf_version = 1; 1900d8f46077SPeter Brune 19013d4c4710SBarry Smith snes->numLinearSolveFailures = 0; 19023d4c4710SBarry Smith snes->maxLinearSolveFailures = 1; 19033d4c4710SBarry Smith 1904349187a7SBarry Smith snes->vizerotolerance = 1.e-8; 190576bd3646SJed Brown snes->checkjacdomainerror = PetscDefined(USE_DEBUG) ? PETSC_TRUE : PETSC_FALSE; 1906349187a7SBarry Smith 19074fc747eaSLawrence Mitchell /* Set this to true if the implementation of SNESSolve_XXX does compute the residual at the final solution. */ 19084fc747eaSLawrence Mitchell snes->alwayscomputesfinalresidual = PETSC_FALSE; 19094fc747eaSLawrence Mitchell 19109b94acceSBarry Smith /* Create context to compute Eisenstat-Walker relative tolerance for KSP */ 19114dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&kctx)); 1912f5af7f23SKarl Rupp 1913835f2295SStefano Zampini snes->kspconvctx = kctx; 19149b94acceSBarry Smith kctx->version = 2; 19150f0abf79SStefano Zampini kctx->rtol_0 = 0.3; /* Eisenstat and Walker suggest rtol_0=.5, but 19169b94acceSBarry Smith this was too large for some test cases */ 191775567043SBarry Smith kctx->rtol_last = 0.0; 19180f0abf79SStefano Zampini kctx->rtol_max = 0.9; 19199b94acceSBarry Smith kctx->gamma = 1.0; 19200f0abf79SStefano Zampini kctx->alpha = 0.5 * (1.0 + PetscSqrtReal(5.0)); 192171f87433Sdalcinl kctx->alpha2 = kctx->alpha; 19220f0abf79SStefano Zampini kctx->threshold = 0.1; 192375567043SBarry Smith kctx->lresid_last = 0.0; 192475567043SBarry Smith kctx->norm_last = 0.0; 19259b94acceSBarry Smith 19260f0abf79SStefano Zampini kctx->rk_last = 0.0; 19270f0abf79SStefano Zampini kctx->rk_last_2 = 0.0; 19280f0abf79SStefano Zampini kctx->rtol_last_2 = 0.0; 19290f0abf79SStefano Zampini kctx->v4_p1 = 0.1; 19300f0abf79SStefano Zampini kctx->v4_p2 = 0.4; 19310f0abf79SStefano Zampini kctx->v4_p3 = 0.7; 19320f0abf79SStefano Zampini kctx->v4_m1 = 0.8; 19330f0abf79SStefano Zampini kctx->v4_m2 = 0.5; 19340f0abf79SStefano Zampini kctx->v4_m3 = 0.1; 19350f0abf79SStefano Zampini kctx->v4_m4 = 0.5; 19360f0abf79SStefano Zampini 1937b50c806fSBarry Smith PetscCall(SNESParametersInitialize(snes)); 19389b94acceSBarry Smith *outsnes = snes; 19393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19409b94acceSBarry Smith } 19419b94acceSBarry Smith 19429b94acceSBarry Smith /*@C 19439b94acceSBarry Smith SNESSetFunction - Sets the function evaluation routine and function 1944f6dfbefdSBarry Smith vector for use by the `SNES` routines in solving systems of nonlinear 19459b94acceSBarry Smith equations. 19469b94acceSBarry Smith 1947c3339decSBarry Smith Logically Collective 1948fee21e36SBarry Smith 1949c7afd0dbSLois Curfman McInnes Input Parameters: 1950f6dfbefdSBarry Smith + snes - the `SNES` context 1951dc4c0fb0SBarry Smith . r - vector to store function values, may be `NULL` 19528434afd1SBarry Smith . f - function evaluation routine; for calling sequence see `SNESFunctionFn` 1953c7afd0dbSLois Curfman McInnes - ctx - [optional] user-defined context for private data for the 1954dc4c0fb0SBarry Smith function evaluation routine (may be `NULL`) 19559b94acceSBarry Smith 195636851e7fSLois Curfman McInnes Level: beginner 195736851e7fSLois Curfman McInnes 19588434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetPicard()`, `SNESFunctionFn` 19599b94acceSBarry Smith @*/ 19608434afd1SBarry Smith PetscErrorCode SNESSetFunction(SNES snes, Vec r, SNESFunctionFn *f, void *ctx) 1961d71ae5a4SJacob Faibussowitsch { 19626cab3a1bSJed Brown DM dm; 19636cab3a1bSJed Brown 19643a40ed3dSBarry Smith PetscFunctionBegin; 19650700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1966d2a683ecSLisandro Dalcin if (r) { 1967d2a683ecSLisandro Dalcin PetscValidHeaderSpecific(r, VEC_CLASSID, 2); 1968d2a683ecSLisandro Dalcin PetscCheckSameComm(snes, 1, r, 2); 19699566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)r)); 19709566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_func)); 197185385478SLisandro Dalcin snes->vec_func = r; 1972d2a683ecSLisandro Dalcin } 19739566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 19749566063dSJacob Faibussowitsch PetscCall(DMSNESSetFunction(dm, f, ctx)); 197548a46eb9SPierre Jolivet if (f == SNESPicardComputeFunction) PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx)); 19763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19779b94acceSBarry Smith } 19789b94acceSBarry Smith 1979e4ed7901SPeter Brune /*@C 19800b4db180SJacob Faibussowitsch SNESSetInitialFunction - Set an already computed function evaluation at the initial guess to be reused by `SNESSolve()`. 1981e4ed7901SPeter Brune 1982c3339decSBarry Smith Logically Collective 1983e4ed7901SPeter Brune 1984e4ed7901SPeter Brune Input Parameters: 1985f6dfbefdSBarry Smith + snes - the `SNES` context 1986e4ed7901SPeter Brune - f - vector to store function value 1987e4ed7901SPeter Brune 1988dc4c0fb0SBarry Smith Level: developer 1989dc4c0fb0SBarry Smith 1990e4ed7901SPeter Brune Notes: 1991e4ed7901SPeter Brune This should not be modified during the solution procedure. 1992e4ed7901SPeter Brune 1993f6dfbefdSBarry Smith This is used extensively in the `SNESFAS` hierarchy and in nonlinear preconditioning. 1994e4ed7901SPeter Brune 19951cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetInitialFunctionNorm()` 1996e4ed7901SPeter Brune @*/ 1997d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetInitialFunction(SNES snes, Vec f) 1998d71ae5a4SJacob Faibussowitsch { 1999e4ed7901SPeter Brune Vec vec_func; 2000e4ed7901SPeter Brune 2001e4ed7901SPeter Brune PetscFunctionBegin; 2002e4ed7901SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2003e4ed7901SPeter Brune PetscValidHeaderSpecific(f, VEC_CLASSID, 2); 2004e4ed7901SPeter Brune PetscCheckSameComm(snes, 1, f, 2); 2005efd4aadfSBarry Smith if (snes->npcside == PC_LEFT && snes->functype == SNES_FUNCTION_PRECONDITIONED) { 2006902f982fSPeter Brune snes->vec_func_init_set = PETSC_FALSE; 20073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2008902f982fSPeter Brune } 20099566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &vec_func, NULL, NULL)); 20109566063dSJacob Faibussowitsch PetscCall(VecCopy(f, vec_func)); 2011f5af7f23SKarl Rupp 2012217b9c2eSPeter Brune snes->vec_func_init_set = PETSC_TRUE; 20133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2014e4ed7901SPeter Brune } 2015e4ed7901SPeter Brune 2016534ebe21SPeter Brune /*@ 2017f6dfbefdSBarry Smith SNESSetNormSchedule - Sets the `SNESNormSchedule` used in convergence and monitoring 2018f6dfbefdSBarry Smith of the `SNES` method, when norms are computed in the solving process 2019534ebe21SPeter Brune 2020c3339decSBarry Smith Logically Collective 2021534ebe21SPeter Brune 2022534ebe21SPeter Brune Input Parameters: 2023f6dfbefdSBarry Smith + snes - the `SNES` context 2024365a6726SPeter Brune - normschedule - the frequency of norm computation 2025534ebe21SPeter Brune 2026517f1916SMatthew G. Knepley Options Database Key: 202767b8a455SSatish Balay . -snes_norm_schedule <none, always, initialonly, finalonly, initialfinalonly> - set the schedule 2028517f1916SMatthew G. Knepley 2029dc4c0fb0SBarry Smith Level: advanced 2030dc4c0fb0SBarry Smith 2031534ebe21SPeter Brune Notes: 2032f6dfbefdSBarry Smith Only certain `SNES` methods support certain `SNESNormSchedules`. Most require evaluation 2033534ebe21SPeter Brune of the nonlinear function and the taking of its norm at every iteration to 2034534ebe21SPeter Brune even ensure convergence at all. However, methods such as custom Gauss-Seidel methods 2035f6dfbefdSBarry Smith `SNESNGS` and the like do not require the norm of the function to be computed, and therefore 2036534ebe21SPeter Brune may either be monitored for convergence or not. As these are often used as nonlinear 2037534ebe21SPeter Brune preconditioners, monitoring the norm of their error is not a useful enterprise within 2038534ebe21SPeter Brune their solution. 2039534ebe21SPeter Brune 2040e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNESNormSchedule`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()` 2041534ebe21SPeter Brune @*/ 2042d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNormSchedule(SNES snes, SNESNormSchedule normschedule) 2043d71ae5a4SJacob Faibussowitsch { 2044534ebe21SPeter Brune PetscFunctionBegin; 2045534ebe21SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2046365a6726SPeter Brune snes->normschedule = normschedule; 20473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2048534ebe21SPeter Brune } 2049534ebe21SPeter Brune 2050534ebe21SPeter Brune /*@ 2051f6dfbefdSBarry Smith SNESGetNormSchedule - Gets the `SNESNormSchedule` used in convergence and monitoring 2052f6dfbefdSBarry Smith of the `SNES` method. 2053534ebe21SPeter Brune 2054c3339decSBarry Smith Logically Collective 2055534ebe21SPeter Brune 2056534ebe21SPeter Brune Input Parameters: 2057f6dfbefdSBarry Smith + snes - the `SNES` context 2058365a6726SPeter Brune - normschedule - the type of the norm used 2059534ebe21SPeter Brune 2060534ebe21SPeter Brune Level: advanced 2061534ebe21SPeter Brune 20621cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 2063534ebe21SPeter Brune @*/ 2064d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNormSchedule(SNES snes, SNESNormSchedule *normschedule) 2065d71ae5a4SJacob Faibussowitsch { 2066534ebe21SPeter Brune PetscFunctionBegin; 2067534ebe21SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2068365a6726SPeter Brune *normschedule = snes->normschedule; 20693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2070534ebe21SPeter Brune } 2071534ebe21SPeter Brune 2072c5ce4427SMatthew G. Knepley /*@ 2073c5ce4427SMatthew G. Knepley SNESSetFunctionNorm - Sets the last computed residual norm. 2074c5ce4427SMatthew G. Knepley 2075c3339decSBarry Smith Logically Collective 2076c5ce4427SMatthew G. Knepley 2077c5ce4427SMatthew G. Knepley Input Parameters: 2078f6dfbefdSBarry Smith + snes - the `SNES` context 2079f6dfbefdSBarry Smith - norm - the value of the norm 2080c5ce4427SMatthew G. Knepley 2081c5ce4427SMatthew G. Knepley Level: developer 2082c5ce4427SMatthew G. Knepley 20831cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 2084c5ce4427SMatthew G. Knepley @*/ 2085d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionNorm(SNES snes, PetscReal norm) 2086d71ae5a4SJacob Faibussowitsch { 2087c5ce4427SMatthew G. Knepley PetscFunctionBegin; 2088c5ce4427SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2089c5ce4427SMatthew G. Knepley snes->norm = norm; 20903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2091c5ce4427SMatthew G. Knepley } 2092c5ce4427SMatthew G. Knepley 2093c5ce4427SMatthew G. Knepley /*@ 2094c5ce4427SMatthew G. Knepley SNESGetFunctionNorm - Gets the last computed norm of the residual 2095c5ce4427SMatthew G. Knepley 2096c5ce4427SMatthew G. Knepley Not Collective 2097c5ce4427SMatthew G. Knepley 2098c5ce4427SMatthew G. Knepley Input Parameter: 2099f6dfbefdSBarry Smith . snes - the `SNES` context 2100c5ce4427SMatthew G. Knepley 2101c5ce4427SMatthew G. Knepley Output Parameter: 2102c5ce4427SMatthew G. Knepley . norm - the last computed residual norm 2103c5ce4427SMatthew G. Knepley 2104c5ce4427SMatthew G. Knepley Level: developer 2105c5ce4427SMatthew G. Knepley 21061cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 2107c5ce4427SMatthew G. Knepley @*/ 2108d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionNorm(SNES snes, PetscReal *norm) 2109d71ae5a4SJacob Faibussowitsch { 2110c5ce4427SMatthew G. Knepley PetscFunctionBegin; 2111c5ce4427SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 21124f572ea9SToby Isaac PetscAssertPointer(norm, 2); 2113c5ce4427SMatthew G. Knepley *norm = snes->norm; 21143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2115c5ce4427SMatthew G. Knepley } 2116c5ce4427SMatthew G. Knepley 2117c1e67a49SFande Kong /*@ 2118f6dfbefdSBarry Smith SNESGetUpdateNorm - Gets the last computed norm of the solution update 2119c1e67a49SFande Kong 2120c1e67a49SFande Kong Not Collective 2121c1e67a49SFande Kong 2122c1e67a49SFande Kong Input Parameter: 2123f6dfbefdSBarry Smith . snes - the `SNES` context 2124c1e67a49SFande Kong 2125c1e67a49SFande Kong Output Parameter: 2126c1e67a49SFande Kong . ynorm - the last computed update norm 2127c1e67a49SFande Kong 2128c1e67a49SFande Kong Level: developer 2129c1e67a49SFande Kong 2130f6dfbefdSBarry Smith Note: 2131f6dfbefdSBarry Smith The new solution is the current solution plus the update, so this norm is an indication of the size of the update 2132f6dfbefdSBarry Smith 21331cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()` 2134c1e67a49SFande Kong @*/ 2135d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUpdateNorm(SNES snes, PetscReal *ynorm) 2136d71ae5a4SJacob Faibussowitsch { 2137c1e67a49SFande Kong PetscFunctionBegin; 2138c1e67a49SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 21394f572ea9SToby Isaac PetscAssertPointer(ynorm, 2); 2140c1e67a49SFande Kong *ynorm = snes->ynorm; 21413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2142c1e67a49SFande Kong } 2143c1e67a49SFande Kong 2144c1e67a49SFande Kong /*@ 21454591eaf2SFande Kong SNESGetSolutionNorm - Gets the last computed norm of the solution 2146c1e67a49SFande Kong 2147c1e67a49SFande Kong Not Collective 2148c1e67a49SFande Kong 2149c1e67a49SFande Kong Input Parameter: 2150f6dfbefdSBarry Smith . snes - the `SNES` context 2151c1e67a49SFande Kong 2152c1e67a49SFande Kong Output Parameter: 2153c1e67a49SFande Kong . xnorm - the last computed solution norm 2154c1e67a49SFande Kong 2155c1e67a49SFande Kong Level: developer 2156c1e67a49SFande Kong 21571cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`, `SNESGetUpdateNorm()` 2158c1e67a49SFande Kong @*/ 2159d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionNorm(SNES snes, PetscReal *xnorm) 2160d71ae5a4SJacob Faibussowitsch { 2161c1e67a49SFande Kong PetscFunctionBegin; 2162c1e67a49SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 21634f572ea9SToby Isaac PetscAssertPointer(xnorm, 2); 2164c1e67a49SFande Kong *xnorm = snes->xnorm; 21653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2166c1e67a49SFande Kong } 2167c1e67a49SFande Kong 2168cc4c1da9SBarry Smith /*@ 2169f6dfbefdSBarry Smith SNESSetFunctionType - Sets the `SNESFunctionType` 2170f6dfbefdSBarry Smith of the `SNES` method. 217147073ea2SPeter Brune 2172c3339decSBarry Smith Logically Collective 217347073ea2SPeter Brune 217447073ea2SPeter Brune Input Parameters: 2175f6dfbefdSBarry Smith + snes - the `SNES` context 2176f6dfbefdSBarry Smith - type - the function type 217747073ea2SPeter Brune 217847073ea2SPeter Brune Level: developer 217947073ea2SPeter Brune 2180420bcc1bSBarry Smith Values of the function type\: 2181f6dfbefdSBarry Smith + `SNES_FUNCTION_DEFAULT` - the default for the given `SNESType` 2182f6dfbefdSBarry Smith . `SNES_FUNCTION_UNPRECONDITIONED` - an unpreconditioned function evaluation (this is the function provided with `SNESSetFunction()` 2183f6dfbefdSBarry Smith - `SNES_FUNCTION_PRECONDITIONED` - a transformation of the function provided with `SNESSetFunction()` 2184f6dfbefdSBarry Smith 2185420bcc1bSBarry Smith Note: 2186f6dfbefdSBarry Smith Different `SNESType`s use this value in different ways 2187f6dfbefdSBarry Smith 21881cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFunctionType`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 218947073ea2SPeter Brune @*/ 2190d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionType(SNES snes, SNESFunctionType type) 2191d71ae5a4SJacob Faibussowitsch { 219247073ea2SPeter Brune PetscFunctionBegin; 219347073ea2SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 219447073ea2SPeter Brune snes->functype = type; 21953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 219647073ea2SPeter Brune } 219747073ea2SPeter Brune 2198cc4c1da9SBarry Smith /*@ 2199f6dfbefdSBarry Smith SNESGetFunctionType - Gets the `SNESFunctionType` used in convergence and monitoring set with `SNESSetFunctionType()` 220047073ea2SPeter Brune of the SNES method. 220147073ea2SPeter Brune 2202c3339decSBarry Smith Logically Collective 220347073ea2SPeter Brune 220447073ea2SPeter Brune Input Parameters: 2205f6dfbefdSBarry Smith + snes - the `SNES` context 2206f6dfbefdSBarry Smith - type - the type of the function evaluation, see `SNESSetFunctionType()` 220747073ea2SPeter Brune 220847073ea2SPeter Brune Level: advanced 220947073ea2SPeter Brune 22101cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetFunctionType()`, `SNESFunctionType`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 221147073ea2SPeter Brune @*/ 2212d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionType(SNES snes, SNESFunctionType *type) 2213d71ae5a4SJacob Faibussowitsch { 221447073ea2SPeter Brune PetscFunctionBegin; 221547073ea2SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 221647073ea2SPeter Brune *type = snes->functype; 22173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2218534ebe21SPeter Brune } 2219534ebe21SPeter Brune 2220c79ef259SPeter Brune /*@C 2221be95d8f1SBarry Smith SNESSetNGS - Sets the user nonlinear Gauss-Seidel routine for 2222c79ef259SPeter Brune use with composed nonlinear solvers. 2223c79ef259SPeter Brune 2224c79ef259SPeter Brune Input Parameters: 22259bcc50f1SBarry Smith + snes - the `SNES` context, usually of the `SNESType` `SNESNGS` 22268434afd1SBarry Smith . f - function evaluation routine to apply Gauss-Seidel, see `SNESNGSFn` for calling sequence 222777e5a1f9SBarry Smith - ctx - [optional] user-defined context for private data for the smoother evaluation routine (may be `NULL`) 2228c79ef259SPeter Brune 2229dc4c0fb0SBarry Smith Level: intermediate 2230dc4c0fb0SBarry Smith 2231f6dfbefdSBarry Smith Note: 2232f6dfbefdSBarry Smith The `SNESNGS` routines are used by the composed nonlinear solver to generate 2233f6dfbefdSBarry Smith a problem appropriate update to the solution, particularly `SNESFAS`. 2234c79ef259SPeter Brune 22358434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGS`, `SNESGetNGS()`, `SNESNCG`, `SNESGetFunction()`, `SNESComputeNGS()`, `SNESNGSFn` 2236c79ef259SPeter Brune @*/ 22378434afd1SBarry Smith PetscErrorCode SNESSetNGS(SNES snes, SNESNGSFn *f, void *ctx) 2238d71ae5a4SJacob Faibussowitsch { 22396cab3a1bSJed Brown DM dm; 22406cab3a1bSJed Brown 2241646217ecSPeter Brune PetscFunctionBegin; 22426cab3a1bSJed Brown PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 22439566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 22449566063dSJacob Faibussowitsch PetscCall(DMSNESSetNGS(dm, f, ctx)); 22453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2246646217ecSPeter Brune } 2247646217ecSPeter Brune 2248bbc1464cSBarry Smith /* 2249bbc1464cSBarry Smith This is used for -snes_mf_operator; it uses a duplicate of snes->jacobian_pre because snes->jacobian_pre cannot be 2250bbc1464cSBarry Smith changed during the KSPSolve() 2251bbc1464cSBarry Smith */ 2252d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeMFFunction(SNES snes, Vec x, Vec f, void *ctx) 2253d71ae5a4SJacob Faibussowitsch { 2254bbc1464cSBarry Smith DM dm; 2255bbc1464cSBarry Smith DMSNES sdm; 2256bbc1464cSBarry Smith 2257bbc1464cSBarry Smith PetscFunctionBegin; 22589566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 22599566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 2260bbc1464cSBarry Smith /* A(x)*x - b(x) */ 2261bbc1464cSBarry Smith if (sdm->ops->computepfunction) { 2262792fecdfSBarry Smith PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx)); 22639566063dSJacob Faibussowitsch PetscCall(VecScale(f, -1.0)); 22640df40c35SBarry Smith /* Cannot share nonzero pattern because of the possible use of SNESComputeJacobianDefault() */ 2265ef1023bdSBarry Smith if (!snes->picard) PetscCall(MatDuplicate(snes->jacobian_pre, MAT_DO_NOT_COPY_VALUES, &snes->picard)); 2266792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx)); 22679566063dSJacob Faibussowitsch PetscCall(MatMultAdd(snes->picard, x, f, f)); 2268bbc1464cSBarry Smith } else { 2269792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx)); 22709566063dSJacob Faibussowitsch PetscCall(MatMult(snes->picard, x, f)); 2271bbc1464cSBarry Smith } 22723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2273bbc1464cSBarry Smith } 2274bbc1464cSBarry Smith 2275d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeFunction(SNES snes, Vec x, Vec f, void *ctx) 2276d71ae5a4SJacob Faibussowitsch { 2277e03ab78fSPeter Brune DM dm; 2278942e3340SBarry Smith DMSNES sdm; 22796cab3a1bSJed Brown 22808b0a5094SBarry Smith PetscFunctionBegin; 22819566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 22829566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 22838b0a5094SBarry Smith /* A(x)*x - b(x) */ 2284bbc1464cSBarry Smith if (sdm->ops->computepfunction) { 2285792fecdfSBarry Smith PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx)); 22869566063dSJacob Faibussowitsch PetscCall(VecScale(f, -1.0)); 2287792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx)); 22889566063dSJacob Faibussowitsch PetscCall(MatMultAdd(snes->jacobian_pre, x, f, f)); 2289bbc1464cSBarry Smith } else { 2290792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx)); 22919566063dSJacob Faibussowitsch PetscCall(MatMult(snes->jacobian_pre, x, f)); 2292bbc1464cSBarry Smith } 22933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22948b0a5094SBarry Smith } 22958b0a5094SBarry Smith 2296d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeJacobian(SNES snes, Vec x1, Mat J, Mat B, void *ctx) 2297d71ae5a4SJacob Faibussowitsch { 22988b0a5094SBarry Smith PetscFunctionBegin; 2299e03ab78fSPeter Brune /* the jacobian matrix should be pre-filled in SNESPicardComputeFunction */ 2300bbc1464cSBarry Smith /* must assembly if matrix-free to get the last SNES solution */ 23019566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 23029566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 23033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23048b0a5094SBarry Smith } 23058b0a5094SBarry Smith 23068b0a5094SBarry Smith /*@C 23071d27aa22SBarry Smith SNESSetPicard - Use `SNES` to solve the system $A(x) x = bp(x) + b $ via a Picard type iteration (Picard linearization) 23088b0a5094SBarry Smith 2309c3339decSBarry Smith Logically Collective 23108b0a5094SBarry Smith 23118b0a5094SBarry Smith Input Parameters: 2312f6dfbefdSBarry Smith + snes - the `SNES` context 2313dc4c0fb0SBarry Smith . r - vector to store function values, may be `NULL` 23148434afd1SBarry Smith . bp - function evaluation routine, may be `NULL`, for the calling sequence see `SNESFunctionFn` 231526a11704SBarry Smith . Amat - matrix with which $A(x) x - bp(x) - b$ is to be computed 2316dc4c0fb0SBarry Smith . Pmat - matrix from which preconditioner is computed (usually the same as `Amat`) 23178434afd1SBarry Smith . J - function to compute matrix values, for the calling sequence see `SNESJacobianFn` 2318dc4c0fb0SBarry Smith - ctx - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`) 2319dc4c0fb0SBarry Smith 2320dc4c0fb0SBarry Smith Level: intermediate 23218b0a5094SBarry Smith 23228b0a5094SBarry Smith Notes: 232326a11704SBarry Smith It is often better to provide the nonlinear function $F()$ and some approximation to its Jacobian directly and use 2324f450aa47SBarry Smith an approximate Newton solver. This interface is provided to allow porting/testing a previous Picard based code in PETSc before converting it to approximate Newton. 2325f450aa47SBarry Smith 2326f6dfbefdSBarry Smith One can call `SNESSetPicard()` or `SNESSetFunction()` (and possibly `SNESSetJacobian()`) but cannot call both 23278b0a5094SBarry Smith 23281d27aa22SBarry Smith Solves the equation $A(x) x = bp(x) - b$ via the defect correction algorithm $A(x^{n}) (x^{n+1} - x^{n}) = bp(x^{n}) + b - A(x^{n})x^{n}$. 23291d27aa22SBarry Smith When an exact solver is used this corresponds to the "classic" Picard $A(x^{n}) x^{n+1} = bp(x^{n}) + b$ iteration. 23308b0a5094SBarry Smith 233126a11704SBarry Smith Run with `-snes_mf_operator` to solve the system with Newton's method using $A(x^{n})$ to construct the preconditioner. 23328b0a5094SBarry Smith 23330d04baf8SBarry Smith We implement the defect correction form of the Picard iteration because it converges much more generally when inexact linear solvers are used then 23341d27aa22SBarry Smith the direct Picard iteration $A(x^n) x^{n+1} = bp(x^n) + b$ 23358b0a5094SBarry Smith 23368b0a5094SBarry Smith There is some controversity over the definition of a Picard iteration for nonlinear systems but almost everyone agrees that it involves a linear solve and some 23371d27aa22SBarry Smith believe it is the iteration $A(x^{n}) x^{n+1} = b(x^{n})$ hence we use the name Picard. If anyone has an authoritative reference that defines the Picard iteration 23381d27aa22SBarry Smith different please contact us at petsc-dev@mcs.anl.gov and we'll have an entirely new argument \:-). 23398b0a5094SBarry Smith 23401d27aa22SBarry Smith When used with `-snes_mf_operator` this will run matrix-free Newton's method where the matrix-vector product is of the true Jacobian of $A(x)x - bp(x) - b$ and 234126a11704SBarry Smith $A(x^{n})$ is used to build the preconditioner 23426b7fb656SBarry Smith 234315229ffcSPierre Jolivet When used with `-snes_fd` this will compute the true Jacobian (very slowly one column at a time) and thus represent Newton's method. 23446b7fb656SBarry Smith 2345dc4c0fb0SBarry Smith When used with `-snes_fd_coloring` this will compute the Jacobian via coloring and thus represent a faster implementation of Newton's method. But the 234626a11704SBarry Smith the nonzero structure of the Jacobian is, in general larger than that of the Picard matrix $A$ so you must provide in $A$ the needed nonzero structure for the correct 234726a11704SBarry Smith coloring. When using `DMDA` this may mean creating the matrix $A$ with `DMCreateMatrix()` using a wider stencil than strictly needed for $A$ or with a `DMDA_STENCIL_BOX`. 2348aaa8cc7dSPierre Jolivet See the comment in src/snes/tutorials/ex15.c. 2349bbc1464cSBarry Smith 23509bcc50f1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESGetPicard()`, `SNESLineSearchPreCheckPicard()`, 23518434afd1SBarry Smith `SNESFunctionFn`, `SNESJacobianFn` 23528b0a5094SBarry Smith @*/ 23538434afd1SBarry Smith PetscErrorCode SNESSetPicard(SNES snes, Vec r, SNESFunctionFn *bp, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx) 2354d71ae5a4SJacob Faibussowitsch { 2355e03ab78fSPeter Brune DM dm; 2356e03ab78fSPeter Brune 23578b0a5094SBarry Smith PetscFunctionBegin; 23588b0a5094SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 23599566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 23609566063dSJacob Faibussowitsch PetscCall(DMSNESSetPicard(dm, bp, J, ctx)); 23619566063dSJacob Faibussowitsch PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx)); 23629566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes, r, SNESPicardComputeFunction, ctx)); 23639566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESPicardComputeJacobian, ctx)); 23643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23658b0a5094SBarry Smith } 23668b0a5094SBarry Smith 23677971a8bfSPeter Brune /*@C 23687971a8bfSPeter Brune SNESGetPicard - Returns the context for the Picard iteration 23697971a8bfSPeter Brune 2370f6dfbefdSBarry Smith Not Collective, but `Vec` is parallel if `SNES` is parallel. Collective if `Vec` is requested, but has not been created yet. 23717971a8bfSPeter Brune 23727971a8bfSPeter Brune Input Parameter: 2373f6dfbefdSBarry Smith . snes - the `SNES` context 23747971a8bfSPeter Brune 2375d8d19677SJose E. Roman Output Parameters: 2376dc4c0fb0SBarry Smith + r - the function (or `NULL`) 23778434afd1SBarry Smith . f - the function (or `NULL`); for calling sequence see `SNESFunctionFn` 2378dc4c0fb0SBarry Smith . Amat - the matrix used to defined the operation A(x) x - b(x) (or `NULL`) 2379dc4c0fb0SBarry Smith . Pmat - the matrix from which the preconditioner will be constructed (or `NULL`) 23808434afd1SBarry Smith . J - the function for matrix evaluation (or `NULL`); for calling sequence see `SNESJacobianFn` 2381dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`) 23827971a8bfSPeter Brune 23837971a8bfSPeter Brune Level: advanced 23847971a8bfSPeter Brune 23858434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetFunction()`, `SNESSetPicard()`, `SNESGetFunction()`, `SNESGetJacobian()`, `SNESGetDM()`, `SNESFunctionFn`, `SNESJacobianFn` 23867971a8bfSPeter Brune @*/ 23878434afd1SBarry Smith PetscErrorCode SNESGetPicard(SNES snes, Vec *r, SNESFunctionFn **f, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx) 2388d71ae5a4SJacob Faibussowitsch { 23897971a8bfSPeter Brune DM dm; 23907971a8bfSPeter Brune 23917971a8bfSPeter Brune PetscFunctionBegin; 23927971a8bfSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 23939566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, r, NULL, NULL)); 23949566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL)); 23959566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 23969566063dSJacob Faibussowitsch PetscCall(DMSNESGetPicard(dm, f, J, ctx)); 23973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23987971a8bfSPeter Brune } 23997971a8bfSPeter Brune 2400d25893d9SBarry Smith /*@C 2401dc4c0fb0SBarry Smith SNESSetComputeInitialGuess - Sets a routine used to compute an initial guess for the nonlinear problem 2402d25893d9SBarry Smith 2403c3339decSBarry Smith Logically Collective 2404d25893d9SBarry Smith 2405d25893d9SBarry Smith Input Parameters: 2406f6dfbefdSBarry Smith + snes - the `SNES` context 24078434afd1SBarry Smith . func - function evaluation routine, see `SNESInitialGuessFn` for the calling sequence 2408d25893d9SBarry Smith - ctx - [optional] user-defined context for private data for the 2409dc4c0fb0SBarry Smith function evaluation routine (may be `NULL`) 2410d25893d9SBarry Smith 2411d25893d9SBarry Smith Level: intermediate 2412d25893d9SBarry Smith 24138434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESInitialGuessFn` 2414d25893d9SBarry Smith @*/ 24158434afd1SBarry Smith PetscErrorCode SNESSetComputeInitialGuess(SNES snes, SNESInitialGuessFn *func, void *ctx) 2416d71ae5a4SJacob Faibussowitsch { 2417d25893d9SBarry Smith PetscFunctionBegin; 2418d25893d9SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2419d25893d9SBarry Smith if (func) snes->ops->computeinitialguess = func; 2420d25893d9SBarry Smith if (ctx) snes->initialguessP = ctx; 24213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2422d25893d9SBarry Smith } 2423d25893d9SBarry Smith 24241096aae1SMatthew Knepley /*@C 2425dc4c0fb0SBarry Smith SNESGetRhs - Gets the vector for solving F(x) = `rhs`. If `rhs` is not set 2426dd8e379bSPierre Jolivet it assumes a zero right-hand side. 24271096aae1SMatthew Knepley 2428c3339decSBarry Smith Logically Collective 24291096aae1SMatthew Knepley 24301096aae1SMatthew Knepley Input Parameter: 2431f6dfbefdSBarry Smith . snes - the `SNES` context 24321096aae1SMatthew Knepley 24331096aae1SMatthew Knepley Output Parameter: 2434dd8e379bSPierre Jolivet . rhs - the right-hand side vector or `NULL` if there is no right-hand side vector 24351096aae1SMatthew Knepley 24361096aae1SMatthew Knepley Level: intermediate 24371096aae1SMatthew Knepley 24381cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetFunction()` 24391096aae1SMatthew Knepley @*/ 2440d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetRhs(SNES snes, Vec *rhs) 2441d71ae5a4SJacob Faibussowitsch { 24421096aae1SMatthew Knepley PetscFunctionBegin; 24430700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 24444f572ea9SToby Isaac PetscAssertPointer(rhs, 2); 244585385478SLisandro Dalcin *rhs = snes->vec_rhs; 24463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24471096aae1SMatthew Knepley } 24481096aae1SMatthew Knepley 24499b94acceSBarry Smith /*@ 2450f6dfbefdSBarry Smith SNESComputeFunction - Calls the function that has been set with `SNESSetFunction()`. 24519b94acceSBarry Smith 2452c3339decSBarry Smith Collective 2453c7afd0dbSLois Curfman McInnes 24549b94acceSBarry Smith Input Parameters: 2455f6dfbefdSBarry Smith + snes - the `SNES` context 2456c7afd0dbSLois Curfman McInnes - x - input vector 24579b94acceSBarry Smith 24589b94acceSBarry Smith Output Parameter: 2459f6dfbefdSBarry Smith . y - function vector, as set by `SNESSetFunction()` 24609b94acceSBarry Smith 2461dc4c0fb0SBarry Smith Level: developer 2462dc4c0fb0SBarry Smith 246300677de2SStefano Zampini Notes: 2464f6dfbefdSBarry Smith `SNESComputeFunction()` is typically used within nonlinear solvers 2465bbc1464cSBarry Smith implementations, so users would not generally call this routine themselves. 246636851e7fSLois Curfman McInnes 246700677de2SStefano Zampini When solving for $F(x) = b$, this routine computes $y = F(x) - b$. 246800677de2SStefano Zampini 24691cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeMFFunction()` 24709b94acceSBarry Smith @*/ 2471d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeFunction(SNES snes, Vec x, Vec y) 2472d71ae5a4SJacob Faibussowitsch { 24736cab3a1bSJed Brown DM dm; 2474942e3340SBarry Smith DMSNES sdm; 24759b94acceSBarry Smith 24763a40ed3dSBarry Smith PetscFunctionBegin; 24770700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 24780700a824SBarry Smith PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 24790700a824SBarry Smith PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2480c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, x, 2); 2481c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, y, 3); 2482e0f629ddSJacob Faibussowitsch PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2483184914b5SBarry Smith 24849566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 24859566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 24860fdf79fbSJacob 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()."); 248732f3f7c2SPeter Brune if (sdm->ops->computefunction) { 248848a46eb9SPierre Jolivet if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0)); 24899566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(x)); 24908ddeebeaSSteve Benbow /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */ 24918ddeebeaSSteve Benbow snes->domainerror = PETSC_FALSE; 2492800f99ffSJeremy L Thompson { 2493800f99ffSJeremy L Thompson void *ctx; 24948434afd1SBarry Smith SNESFunctionFn *computefunction; 2495800f99ffSJeremy L Thompson PetscCall(DMSNESGetFunction(dm, &computefunction, &ctx)); 2496800f99ffSJeremy L Thompson PetscCallBack("SNES callback function", (*computefunction)(snes, x, y, ctx)); 2497800f99ffSJeremy L Thompson } 24989566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(x)); 249948a46eb9SPierre Jolivet if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0)); 25000fdf79fbSJacob Faibussowitsch } else /* if (snes->vec_rhs) */ { 25019566063dSJacob Faibussowitsch PetscCall(MatMult(snes->jacobian, x, y)); 25020fdf79fbSJacob Faibussowitsch } 25031baa6e33SBarry Smith if (snes->vec_rhs) PetscCall(VecAXPY(y, -1.0, snes->vec_rhs)); 2504ae3c334cSLois Curfman McInnes snes->nfuncs++; 2505422a814eSBarry Smith /* 2506422a814eSBarry Smith domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will 2507422a814eSBarry Smith propagate the value to all processes 2508422a814eSBarry Smith */ 2509f480ea8aSBarry Smith PetscCall(VecFlag(y, snes->domainerror)); 25103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 25119b94acceSBarry Smith } 25129b94acceSBarry Smith 2513c79ef259SPeter Brune /*@ 25140b4b7b1cSBarry Smith SNESComputeMFFunction - Calls the function that has been set with `DMSNESSetMFFunction()`. 2515bbc1464cSBarry Smith 2516c3339decSBarry Smith Collective 2517bbc1464cSBarry Smith 2518bbc1464cSBarry Smith Input Parameters: 2519f6dfbefdSBarry Smith + snes - the `SNES` context 2520bbc1464cSBarry Smith - x - input vector 2521bbc1464cSBarry Smith 2522bbc1464cSBarry Smith Output Parameter: 25230b4b7b1cSBarry Smith . y - output vector 2524bbc1464cSBarry Smith 2525dc4c0fb0SBarry Smith Level: developer 2526dc4c0fb0SBarry Smith 2527bbc1464cSBarry Smith Notes: 2528420bcc1bSBarry Smith `SNESComputeMFFunction()` is used within the matrix-vector products called by the matrix created with `MatCreateSNESMF()` 2529bbc1464cSBarry Smith so users would not generally call this routine themselves. 2530bbc1464cSBarry Smith 2531dd8e379bSPierre Jolivet Since this function is intended for use with finite differencing it does not subtract the right-hand side vector provided with `SNESSolve()` 2532f6dfbefdSBarry Smith while `SNESComputeFunction()` does. As such, this routine cannot be used with `MatMFFDSetBase()` with a provided F function value even if it applies the 2533dd8e379bSPierre 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. 2534bbc1464cSBarry Smith 25350b4b7b1cSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `MatCreateSNESMF()`, `DMSNESSetMFFunction()` 2536bbc1464cSBarry Smith @*/ 2537d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeMFFunction(SNES snes, Vec x, Vec y) 2538d71ae5a4SJacob Faibussowitsch { 2539bbc1464cSBarry Smith DM dm; 2540bbc1464cSBarry Smith DMSNES sdm; 2541bbc1464cSBarry Smith 2542bbc1464cSBarry Smith PetscFunctionBegin; 2543bbc1464cSBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2544bbc1464cSBarry Smith PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2545bbc1464cSBarry Smith PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2546bbc1464cSBarry Smith PetscCheckSameComm(snes, 1, x, 2); 2547bbc1464cSBarry Smith PetscCheckSameComm(snes, 1, y, 3); 2548e0f629ddSJacob Faibussowitsch PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2549bbc1464cSBarry Smith 25509566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 25519566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 25529566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0)); 25539566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(x)); 2554bbc1464cSBarry Smith /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */ 2555bbc1464cSBarry Smith snes->domainerror = PETSC_FALSE; 2556792fecdfSBarry Smith PetscCallBack("SNES callback function", (*sdm->ops->computemffunction)(snes, x, y, sdm->mffunctionctx)); 25579566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(x)); 25589566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0)); 2559bbc1464cSBarry Smith snes->nfuncs++; 2560bbc1464cSBarry Smith /* 2561bbc1464cSBarry Smith domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will 2562bbc1464cSBarry Smith propagate the value to all processes 2563bbc1464cSBarry Smith */ 2564f480ea8aSBarry Smith PetscCall(VecFlag(y, snes->domainerror)); 25653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2566bbc1464cSBarry Smith } 2567bbc1464cSBarry Smith 2568bbc1464cSBarry Smith /*@ 2569f6dfbefdSBarry Smith SNESComputeNGS - Calls the Gauss-Seidel function that has been set with `SNESSetNGS()`. 2570c79ef259SPeter Brune 2571c3339decSBarry Smith Collective 2572c79ef259SPeter Brune 2573c79ef259SPeter Brune Input Parameters: 2574f6dfbefdSBarry Smith + snes - the `SNES` context 2575c79ef259SPeter Brune . x - input vector 2576c79ef259SPeter Brune - b - rhs vector 2577c79ef259SPeter Brune 2578c79ef259SPeter Brune Output Parameter: 2579c79ef259SPeter Brune . x - new solution vector 2580c79ef259SPeter Brune 2581dc4c0fb0SBarry Smith Level: developer 2582dc4c0fb0SBarry Smith 2583f6dfbefdSBarry Smith Note: 2584f6dfbefdSBarry Smith `SNESComputeNGS()` is typically used within composed nonlinear solver 2585c79ef259SPeter Brune implementations, so most users would not generally call this routine 2586c79ef259SPeter Brune themselves. 2587c79ef259SPeter Brune 25888434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGSFn`, `SNESSetNGS()`, `SNESComputeFunction()`, `SNESNGS` 2589c79ef259SPeter Brune @*/ 2590d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeNGS(SNES snes, Vec b, Vec x) 2591d71ae5a4SJacob Faibussowitsch { 25926cab3a1bSJed Brown DM dm; 2593942e3340SBarry Smith DMSNES sdm; 2594646217ecSPeter Brune 2595646217ecSPeter Brune PetscFunctionBegin; 2596646217ecSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2597064a246eSJacob Faibussowitsch PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 2598064a246eSJacob Faibussowitsch if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 2599064a246eSJacob Faibussowitsch PetscCheckSameComm(snes, 1, x, 3); 2600064a246eSJacob Faibussowitsch if (b) PetscCheckSameComm(snes, 1, b, 2); 2601e0f629ddSJacob Faibussowitsch if (b) PetscCall(VecValidValues_Internal(b, 2, PETSC_TRUE)); 26029566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_NGSEval, snes, x, b, 0)); 26039566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 26049566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 26050fdf79fbSJacob Faibussowitsch PetscCheck(sdm->ops->computegs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetNGS() before SNESComputeNGS(), likely called from SNESSolve()."); 26069566063dSJacob Faibussowitsch if (b) PetscCall(VecLockReadPush(b)); 2607792fecdfSBarry Smith PetscCallBack("SNES callback NGS", (*sdm->ops->computegs)(snes, x, b, sdm->gsctx)); 26089566063dSJacob Faibussowitsch if (b) PetscCall(VecLockReadPop(b)); 26099566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_NGSEval, snes, x, b, 0)); 26103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2611646217ecSPeter Brune } 2612646217ecSPeter Brune 2613494a190aSStefano Zampini static PetscErrorCode SNESComputeFunction_FD(SNES snes, Vec Xin, Vec G) 2614494a190aSStefano Zampini { 2615494a190aSStefano Zampini Vec X; 2616494a190aSStefano Zampini PetscScalar *g; 2617494a190aSStefano Zampini PetscReal f, f2; 2618494a190aSStefano Zampini PetscInt low, high, N, i; 2619494a190aSStefano Zampini PetscBool flg; 2620494a190aSStefano Zampini PetscReal h = .5 * PETSC_SQRT_MACHINE_EPSILON; 2621494a190aSStefano Zampini 2622494a190aSStefano Zampini PetscFunctionBegin; 2623494a190aSStefano Zampini PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_fd_delta", &h, &flg)); 2624494a190aSStefano Zampini PetscCall(VecDuplicate(Xin, &X)); 2625494a190aSStefano Zampini PetscCall(VecCopy(Xin, X)); 2626494a190aSStefano Zampini PetscCall(VecGetSize(X, &N)); 2627494a190aSStefano Zampini PetscCall(VecGetOwnershipRange(X, &low, &high)); 2628494a190aSStefano Zampini PetscCall(VecSetOption(X, VEC_IGNORE_OFF_PROC_ENTRIES, PETSC_TRUE)); 2629494a190aSStefano Zampini PetscCall(VecGetArray(G, &g)); 2630494a190aSStefano Zampini for (i = 0; i < N; i++) { 2631494a190aSStefano Zampini PetscCall(VecSetValue(X, i, -h, ADD_VALUES)); 2632494a190aSStefano Zampini PetscCall(VecAssemblyBegin(X)); 2633494a190aSStefano Zampini PetscCall(VecAssemblyEnd(X)); 2634494a190aSStefano Zampini PetscCall(SNESComputeObjective(snes, X, &f)); 2635494a190aSStefano Zampini PetscCall(VecSetValue(X, i, 2.0 * h, ADD_VALUES)); 2636494a190aSStefano Zampini PetscCall(VecAssemblyBegin(X)); 2637494a190aSStefano Zampini PetscCall(VecAssemblyEnd(X)); 2638494a190aSStefano Zampini PetscCall(SNESComputeObjective(snes, X, &f2)); 2639494a190aSStefano Zampini PetscCall(VecSetValue(X, i, -h, ADD_VALUES)); 2640494a190aSStefano Zampini PetscCall(VecAssemblyBegin(X)); 2641494a190aSStefano Zampini PetscCall(VecAssemblyEnd(X)); 2642494a190aSStefano Zampini if (i >= low && i < high) g[i - low] = (f2 - f) / (2.0 * h); 2643494a190aSStefano Zampini } 2644494a190aSStefano Zampini PetscCall(VecRestoreArray(G, &g)); 2645494a190aSStefano Zampini PetscCall(VecDestroy(&X)); 2646494a190aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2647494a190aSStefano Zampini } 2648494a190aSStefano Zampini 26491dfd7622SMatthew Knepley /*@ 26501dfd7622SMatthew Knepley SNESTestFunction - Computes the difference between the computed and finite-difference functions 26511dfd7622SMatthew Knepley 26521dfd7622SMatthew Knepley Collective 26531dfd7622SMatthew Knepley 2654d5bfe6baSJose E. Roman Input Parameter: 26551dfd7622SMatthew Knepley . snes - the `SNES` context 26561dfd7622SMatthew Knepley 26571dfd7622SMatthew Knepley Options Database Keys: 26581dfd7622SMatthew Knepley + -snes_test_function - compare the user provided function with one compute via finite differences to check for errors. 26591dfd7622SMatthew Knepley - -snes_test_function_view - display the user provided function, the finite difference function and the difference 26601dfd7622SMatthew Knepley 26611dfd7622SMatthew Knepley Level: developer 26621dfd7622SMatthew Knepley 26631dfd7622SMatthew Knepley .seealso: [](ch_snes), `SNESTestJacobian()`, `SNESSetFunction()`, `SNESComputeFunction()` 26641dfd7622SMatthew Knepley @*/ 2665494a190aSStefano Zampini PetscErrorCode SNESTestFunction(SNES snes) 2666494a190aSStefano Zampini { 2667494a190aSStefano Zampini Vec x, g1, g2, g3; 26681dfd7622SMatthew Knepley PetscBool complete_print = PETSC_FALSE; 2669494a190aSStefano Zampini PetscReal hcnorm, fdnorm, hcmax, fdmax, diffmax, diffnorm; 2670494a190aSStefano Zampini PetscScalar dot; 2671494a190aSStefano Zampini MPI_Comm comm; 2672494a190aSStefano Zampini PetscViewer viewer, mviewer; 2673494a190aSStefano Zampini PetscViewerFormat format; 2674494a190aSStefano Zampini PetscInt tabs; 2675494a190aSStefano Zampini static PetscBool directionsprinted = PETSC_FALSE; 26768434afd1SBarry Smith SNESObjectiveFn *objective; 2677494a190aSStefano Zampini 2678494a190aSStefano Zampini PetscFunctionBegin; 2679494a190aSStefano Zampini PetscCall(SNESGetObjective(snes, &objective, NULL)); 2680494a190aSStefano Zampini if (!objective) PetscFunctionReturn(PETSC_SUCCESS); 2681494a190aSStefano Zampini 2682494a190aSStefano Zampini PetscObjectOptionsBegin((PetscObject)snes); 2683494a190aSStefano Zampini PetscCall(PetscOptionsViewer("-snes_test_function_view", "View difference between hand-coded and finite difference function element entries", "None", &mviewer, &format, &complete_print)); 2684494a190aSStefano Zampini PetscOptionsEnd(); 2685494a190aSStefano Zampini 2686494a190aSStefano Zampini PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 2687494a190aSStefano Zampini PetscCall(PetscViewerASCIIGetStdout(comm, &viewer)); 2688494a190aSStefano Zampini PetscCall(PetscViewerASCIIGetTab(viewer, &tabs)); 2689494a190aSStefano Zampini PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel)); 2690494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Function -------------\n")); 2691494a190aSStefano Zampini if (!complete_print && !directionsprinted) { 2692494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Run with -snes_test_function_view and optionally -snes_test_function <threshold> to show difference\n")); 2693494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " of hand-coded and finite difference function entries greater than <threshold>.\n")); 2694494a190aSStefano Zampini } 2695494a190aSStefano Zampini if (!directionsprinted) { 2696494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Testing hand-coded Function, if (for double precision runs) ||F - Ffd||/||F|| is\n")); 2697494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " O(1.e-8), the hand-coded Function is probably correct.\n")); 2698494a190aSStefano Zampini directionsprinted = PETSC_TRUE; 2699494a190aSStefano Zampini } 2700494a190aSStefano Zampini if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format)); 2701494a190aSStefano Zampini 2702494a190aSStefano Zampini PetscCall(SNESGetSolution(snes, &x)); 2703494a190aSStefano Zampini PetscCall(VecDuplicate(x, &g1)); 2704494a190aSStefano Zampini PetscCall(VecDuplicate(x, &g2)); 2705494a190aSStefano Zampini PetscCall(VecDuplicate(x, &g3)); 2706494a190aSStefano Zampini PetscCall(SNESComputeFunction(snes, x, g1)); 2707494a190aSStefano Zampini PetscCall(SNESComputeFunction_FD(snes, x, g2)); 2708494a190aSStefano Zampini 2709494a190aSStefano Zampini PetscCall(VecNorm(g2, NORM_2, &fdnorm)); 2710494a190aSStefano Zampini PetscCall(VecNorm(g1, NORM_2, &hcnorm)); 2711494a190aSStefano Zampini PetscCall(VecNorm(g2, NORM_INFINITY, &fdmax)); 2712494a190aSStefano Zampini PetscCall(VecNorm(g1, NORM_INFINITY, &hcmax)); 2713494a190aSStefano Zampini PetscCall(VecDot(g1, g2, &dot)); 2714494a190aSStefano Zampini PetscCall(VecCopy(g1, g3)); 2715494a190aSStefano Zampini PetscCall(VecAXPY(g3, -1.0, g2)); 2716494a190aSStefano Zampini PetscCall(VecNorm(g3, NORM_2, &diffnorm)); 2717494a190aSStefano Zampini PetscCall(VecNorm(g3, NORM_INFINITY, &diffmax)); 2718494a190aSStefano 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)))); 2719494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " 2-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffnorm / PetscMax(hcnorm, fdnorm)), (double)diffnorm)); 2720494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " max-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffmax / PetscMax(hcmax, fdmax)), (double)diffmax)); 2721494a190aSStefano Zampini 2722494a190aSStefano Zampini if (complete_print) { 2723494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded function ----------\n")); 2724494a190aSStefano Zampini PetscCall(VecView(g1, mviewer)); 2725494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Finite difference function ----------\n")); 2726494a190aSStefano Zampini PetscCall(VecView(g2, mviewer)); 2727494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded minus finite-difference function ----------\n")); 2728494a190aSStefano Zampini PetscCall(VecView(g3, mviewer)); 2729494a190aSStefano Zampini } 2730494a190aSStefano Zampini PetscCall(VecDestroy(&g1)); 2731494a190aSStefano Zampini PetscCall(VecDestroy(&g2)); 2732494a190aSStefano Zampini PetscCall(VecDestroy(&g3)); 2733494a190aSStefano Zampini 2734494a190aSStefano Zampini if (complete_print) { 2735494a190aSStefano Zampini PetscCall(PetscViewerPopFormat(mviewer)); 2736494a190aSStefano Zampini PetscCall(PetscViewerDestroy(&mviewer)); 2737494a190aSStefano Zampini } 2738494a190aSStefano Zampini PetscCall(PetscViewerASCIISetTab(viewer, tabs)); 2739494a190aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2740494a190aSStefano Zampini } 2741494a190aSStefano Zampini 2742cbf8f02cSMatthew G. Knepley /*@ 2743cbf8f02cSMatthew G. Knepley SNESTestJacobian - Computes the difference between the computed and finite-difference Jacobians 2744cbf8f02cSMatthew G. Knepley 2745cbf8f02cSMatthew G. Knepley Collective 2746cbf8f02cSMatthew G. Knepley 2747d5bfe6baSJose E. Roman Input Parameter: 2748cbf8f02cSMatthew G. Knepley . snes - the `SNES` context 2749cbf8f02cSMatthew G. Knepley 2750cbf8f02cSMatthew G. Knepley Output Parameters: 27511dfd7622SMatthew Knepley + Jnorm - the Frobenius norm of the computed Jacobian, or `NULL` 27521dfd7622SMatthew Knepley - diffNorm - the Frobenius norm of the difference of the computed and finite-difference Jacobians, or `NULL` 2753cbf8f02cSMatthew G. Knepley 2754cbf8f02cSMatthew G. Knepley Options Database Keys: 2755cbf8f02cSMatthew 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. 2756cbf8f02cSMatthew G. Knepley - -snes_test_jacobian_view - display the user provided Jacobian, the finite difference Jacobian and the difference 2757cbf8f02cSMatthew G. Knepley 2758cbf8f02cSMatthew G. Knepley Level: developer 2759cbf8f02cSMatthew G. Knepley 27601dfd7622SMatthew Knepley Note: 27611dfd7622SMatthew Knepley Directions and norms are printed to stdout if `diffNorm` is `NULL`. 27621dfd7622SMatthew Knepley 27631dfd7622SMatthew Knepley .seealso: [](ch_snes), `SNESTestFunction()`, `SNESSetJacobian()`, `SNESComputeJacobian()` 2764cbf8f02cSMatthew G. Knepley @*/ 2765cbf8f02cSMatthew G. Knepley PetscErrorCode SNESTestJacobian(SNES snes, PetscReal *Jnorm, PetscReal *diffNorm) 2766d71ae5a4SJacob Faibussowitsch { 276712837594SBarry Smith Mat A, B, C, D, jacobian; 27684df93895SStefano Zampini Vec x = snes->vec_sol, f; 2769e885f1abSBarry Smith PetscReal nrm, gnorm; 277081e7118cSBarry Smith PetscReal threshold = 1.e-5; 27710e276705SLisandro Dalcin MatType mattype; 2772e885f1abSBarry Smith PetscInt m, n, M, N; 2773e885f1abSBarry Smith void *functx; 27741dfd7622SMatthew Knepley PetscBool complete_print = PETSC_FALSE, threshold_print = PETSC_FALSE, flg, istranspose; 27751dfd7622SMatthew Knepley PetscBool silent = diffNorm != PETSC_NULLPTR ? PETSC_TRUE : PETSC_FALSE; 27763325ff46SBarry Smith PetscViewer viewer, mviewer; 2777e885f1abSBarry Smith MPI_Comm comm; 2778e885f1abSBarry Smith PetscInt tabs; 277912837594SBarry Smith static PetscBool directionsprinted = PETSC_FALSE; 27803325ff46SBarry Smith PetscViewerFormat format; 2781e885f1abSBarry Smith 2782e885f1abSBarry Smith PetscFunctionBegin; 2783d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)snes); 27849566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-snes_test_jacobian", "Threshold for element difference between hand-coded and finite difference being meaningful", "None", threshold, &threshold, NULL)); 27859566063dSJacob Faibussowitsch PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display", "-snes_test_jacobian_view", "3.13", NULL)); 27864ead3382SBarry Smith PetscCall(PetscOptionsViewer("-snes_test_jacobian_view", "View difference between hand-coded and finite difference Jacobians element entries", "None", &mviewer, &format, &complete_print)); 27879566063dSJacob Faibussowitsch PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display_threshold", "-snes_test_jacobian", "3.13", "-snes_test_jacobian accepts an optional threshold (since v3.10)")); 27889566063dSJacob 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)); 2789d0609cedSBarry Smith PetscOptionsEnd(); 2790e885f1abSBarry Smith 27919566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 27929566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(comm, &viewer)); 27939566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetTab(viewer, &tabs)); 27949566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel)); 27951dfd7622SMatthew Knepley if (!silent) PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Jacobian -------------\n")); 27961dfd7622SMatthew Knepley if (!complete_print && !silent && !directionsprinted) { 27979566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Run with -snes_test_jacobian_view and optionally -snes_test_jacobian <threshold> to show difference\n")); 27989566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " of hand-coded and finite difference Jacobian entries greater than <threshold>.\n")); 279912837594SBarry Smith } 28001dfd7622SMatthew Knepley if (!directionsprinted && !silent) { 28019566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Testing hand-coded Jacobian, if (for double precision runs) ||J - Jfd||_F/||J||_F is\n")); 28029566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " O(1.e-8), the hand-coded Jacobian is probably correct.\n")); 280312837594SBarry Smith directionsprinted = PETSC_TRUE; 2804e885f1abSBarry Smith } 28051baa6e33SBarry Smith if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format)); 2806e885f1abSBarry Smith 28079566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes->jacobian, MATMFFD, &flg)); 280812837594SBarry Smith if (!flg) jacobian = snes->jacobian; 280912837594SBarry Smith else jacobian = snes->jacobian_pre; 281012837594SBarry Smith 28114df93895SStefano Zampini if (!x) PetscCall(MatCreateVecs(jacobian, &x, NULL)); 28124df93895SStefano Zampini else PetscCall(PetscObjectReference((PetscObject)x)); 28139566063dSJacob Faibussowitsch PetscCall(VecDuplicate(x, &f)); 28144df93895SStefano Zampini 2815a82339d0SMatthew G. Knepley /* evaluate the function at this point because SNESComputeJacobianDefault() assumes that the function has been evaluated and put into snes->vec_func */ 28169566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, x, f)); 28179566063dSJacob Faibussowitsch PetscCall(VecDestroy(&f)); 28189566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESKSPTRANSPOSEONLY, &istranspose)); 281912837594SBarry Smith while (jacobian) { 28202cd624f9SStefano Zampini Mat JT = NULL, Jsave = NULL; 28212cd624f9SStefano Zampini 28222cd624f9SStefano Zampini if (istranspose) { 28239566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(jacobian, &JT)); 28242cd624f9SStefano Zampini Jsave = jacobian; 28252cd624f9SStefano Zampini jacobian = JT; 28262cd624f9SStefano Zampini } 28279566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)jacobian, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, "")); 282812837594SBarry Smith if (flg) { 282912837594SBarry Smith A = jacobian; 28309566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 283112837594SBarry Smith } else { 28329566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(jacobian, MATAIJ, &A)); 283312837594SBarry Smith } 2834e885f1abSBarry Smith 28359566063dSJacob Faibussowitsch PetscCall(MatGetType(A, &mattype)); 28369566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &M, &N)); 28379566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &m, &n)); 28389566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B)); 28399566063dSJacob Faibussowitsch PetscCall(MatSetType(B, mattype)); 28409566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, m, n, M, N)); 28419566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(B, A, A)); 28429566063dSJacob Faibussowitsch PetscCall(MatSetUp(B)); 28439566063dSJacob Faibussowitsch PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 2844e885f1abSBarry Smith 28459566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, NULL, &functx)); 28469566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobianDefault(snes, x, B, B, functx)); 284712837594SBarry Smith 28489566063dSJacob Faibussowitsch PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &D)); 28499566063dSJacob Faibussowitsch PetscCall(MatAYPX(D, -1.0, A, DIFFERENT_NONZERO_PATTERN)); 28509566063dSJacob Faibussowitsch PetscCall(MatNorm(D, NORM_FROBENIUS, &nrm)); 28519566063dSJacob Faibussowitsch PetscCall(MatNorm(A, NORM_FROBENIUS, &gnorm)); 28529566063dSJacob Faibussowitsch PetscCall(MatDestroy(&D)); 285312837594SBarry Smith if (!gnorm) gnorm = 1; /* just in case */ 28541dfd7622SMatthew Knepley if (!silent) PetscCall(PetscViewerASCIIPrintf(viewer, " ||J - Jfd||_F/||J||_F = %g, ||J - Jfd||_F = %g\n", (double)(nrm / gnorm), (double)nrm)); 2855e885f1abSBarry Smith if (complete_print) { 28569566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded Jacobian ----------\n")); 28579566063dSJacob Faibussowitsch PetscCall(MatView(A, mviewer)); 28589566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Finite difference Jacobian ----------\n")); 28599566063dSJacob Faibussowitsch PetscCall(MatView(B, mviewer)); 2860e885f1abSBarry Smith } 2861e885f1abSBarry Smith 2862df10fb39SFande Kong if (threshold_print || complete_print) { 2863e885f1abSBarry Smith PetscInt Istart, Iend, *ccols, bncols, cncols, j, row; 2864e885f1abSBarry Smith PetscScalar *cvals; 2865e885f1abSBarry Smith const PetscInt *bcols; 2866e885f1abSBarry Smith const PetscScalar *bvals; 2867e885f1abSBarry Smith 28689566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C)); 28699566063dSJacob Faibussowitsch PetscCall(MatSetType(C, mattype)); 28709566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, m, n, M, N)); 28719566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(C, A, A)); 28729566063dSJacob Faibussowitsch PetscCall(MatSetUp(C)); 28739566063dSJacob Faibussowitsch PetscCall(MatSetOption(C, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 28740e276705SLisandro Dalcin 28759566063dSJacob Faibussowitsch PetscCall(MatAYPX(B, -1.0, A, DIFFERENT_NONZERO_PATTERN)); 28769566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(B, &Istart, &Iend)); 2877e885f1abSBarry Smith 2878e885f1abSBarry Smith for (row = Istart; row < Iend; row++) { 28799566063dSJacob Faibussowitsch PetscCall(MatGetRow(B, row, &bncols, &bcols, &bvals)); 28809566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(bncols, &ccols, bncols, &cvals)); 2881e885f1abSBarry Smith for (j = 0, cncols = 0; j < bncols; j++) { 288223a52b1dSBarry Smith if (PetscAbsScalar(bvals[j]) > threshold) { 2883e885f1abSBarry Smith ccols[cncols] = bcols[j]; 2884e885f1abSBarry Smith cvals[cncols] = bvals[j]; 2885e885f1abSBarry Smith cncols += 1; 2886e885f1abSBarry Smith } 2887e885f1abSBarry Smith } 288848a46eb9SPierre Jolivet if (cncols) PetscCall(MatSetValues(C, 1, &row, cncols, ccols, cvals, INSERT_VALUES)); 28899566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(B, row, &bncols, &bcols, &bvals)); 28909566063dSJacob Faibussowitsch PetscCall(PetscFree2(ccols, cvals)); 2891e885f1abSBarry Smith } 28929566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 28939566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 28949566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded minus finite-difference Jacobian with tolerance %g ----------\n", (double)threshold)); 28959566063dSJacob Faibussowitsch PetscCall(MatView(C, complete_print ? mviewer : viewer)); 28969566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C)); 2897e885f1abSBarry Smith } 28989566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A)); 28999566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 29009566063dSJacob Faibussowitsch PetscCall(MatDestroy(&JT)); 29012cd624f9SStefano Zampini if (Jsave) jacobian = Jsave; 290212837594SBarry Smith if (jacobian != snes->jacobian_pre) { 290312837594SBarry Smith jacobian = snes->jacobian_pre; 29041dfd7622SMatthew Knepley if (!silent) PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Jacobian for preconditioner -------------\n")); 29059371c9d4SSatish Balay } else jacobian = NULL; 290612837594SBarry Smith } 29079566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); 29081baa6e33SBarry Smith if (complete_print) PetscCall(PetscViewerPopFormat(mviewer)); 2909648c30bcSBarry Smith if (mviewer) PetscCall(PetscViewerDestroy(&mviewer)); 29109566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISetTab(viewer, tabs)); 2911cbf8f02cSMatthew G. Knepley 2912cbf8f02cSMatthew G. Knepley if (Jnorm) *Jnorm = gnorm; 2913cbf8f02cSMatthew G. Knepley if (diffNorm) *diffNorm = nrm; 29143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2915e885f1abSBarry Smith } 2916e885f1abSBarry Smith 291762fef451SLois Curfman McInnes /*@ 2918f6dfbefdSBarry Smith SNESComputeJacobian - Computes the Jacobian matrix that has been set with `SNESSetJacobian()`. 291962fef451SLois Curfman McInnes 2920c3339decSBarry Smith Collective 2921c7afd0dbSLois Curfman McInnes 292262fef451SLois Curfman McInnes Input Parameters: 2923f6dfbefdSBarry Smith + snes - the `SNES` context 2924e4094ef1SJacob Faibussowitsch - X - input vector 292562fef451SLois Curfman McInnes 292662fef451SLois Curfman McInnes Output Parameters: 2927c7afd0dbSLois Curfman McInnes + A - Jacobian matrix 2928420bcc1bSBarry Smith - B - optional matrix for building the preconditioner, usually the same as `A` 2929fee21e36SBarry Smith 2930e35cf81dSBarry Smith Options Database Keys: 293167b8a455SSatish Balay + -snes_lag_preconditioner <lag> - how often to rebuild preconditioner 293267b8a455SSatish Balay . -snes_lag_jacobian <lag> - how often to rebuild Jacobian 2933455a5933SJed 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. 2934455a5933SJed 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 2935693365a8SJed Brown . -snes_compare_explicit - Compare the computed Jacobian to the finite difference Jacobian and output the differences 2936693365a8SJed Brown . -snes_compare_explicit_draw - Compare the computed Jacobian to the finite difference Jacobian and draw the result 2937693365a8SJed Brown . -snes_compare_explicit_contour - Compare the computed Jacobian to the finite difference Jacobian and draw a contour plot with the result 29387addb90fSBarry Smith . -snes_compare_operator - Make the comparison options above use the operator instead of the matrix used to construct the preconditioner 293994d6a431SBarry Smith . -snes_compare_coloring - Compute the finite difference Jacobian using coloring and display norms of difference 2940a5b23f4aSJose E. Roman . -snes_compare_coloring_display - Compute the finite difference Jacobian using coloring and display verbose differences 2941c01495d3SJed Brown . -snes_compare_coloring_threshold - Display only those matrix entries that differ by more than a given threshold 2942dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_atol - Absolute tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold` 2943dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_rtol - Relative tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold` 2944a5b23f4aSJose E. Roman . -snes_compare_coloring_draw - Compute the finite difference Jacobian using coloring and draw differences 2945a5b23f4aSJose E. Roman - -snes_compare_coloring_draw_contour - Compute the finite difference Jacobian using coloring and show contours of matrices and differences 2946c01495d3SJed Brown 2947dc4c0fb0SBarry Smith Level: developer 2948dc4c0fb0SBarry Smith 2949f6dfbefdSBarry Smith Note: 295062fef451SLois Curfman McInnes Most users should not need to explicitly call this routine, as it 295162fef451SLois Curfman McInnes is used internally within the nonlinear solvers. 295262fef451SLois Curfman McInnes 2953420bcc1bSBarry Smith Developer Note: 2954dc4c0fb0SBarry 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 2955420bcc1bSBarry Smith with the `SNESType` of test that has been removed. 2956e885f1abSBarry Smith 29571cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetJacobian()`, `KSPSetOperators()`, `MatStructure`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()` 295862fef451SLois Curfman McInnes @*/ 2959d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeJacobian(SNES snes, Vec X, Mat A, Mat B) 2960d71ae5a4SJacob Faibussowitsch { 2961ace3abfcSBarry Smith PetscBool flag; 29626cab3a1bSJed Brown DM dm; 2963942e3340SBarry Smith DMSNES sdm; 2964e0e3a89bSBarry Smith KSP ksp; 29653a40ed3dSBarry Smith 29663a40ed3dSBarry Smith PetscFunctionBegin; 29670700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 29680700a824SBarry Smith PetscValidHeaderSpecific(X, VEC_CLASSID, 2); 2969c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, X, 2); 2970e0f629ddSJacob Faibussowitsch PetscCall(VecValidValues_Internal(X, 2, PETSC_TRUE)); 29719566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 29729566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 29733232da50SPeter Brune 297401c1178eSBarry Smith /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix-free */ 2975fe3ffe1eSBarry Smith if (snes->lagjacobian == -2) { 2976fe3ffe1eSBarry Smith snes->lagjacobian = -1; 2977f5af7f23SKarl Rupp 29789566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n")); 2979fe3ffe1eSBarry Smith } else if (snes->lagjacobian == -1) { 29809566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is -1\n")); 29819566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag)); 2982ebd3b9afSBarry Smith if (flag) { 29839566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 29849566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 2985ebd3b9afSBarry Smith } 29863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 298737ec4e1aSPeter Brune } else if (snes->lagjacobian > 1 && (snes->iter + snes->jac_iter) % snes->lagjacobian) { 298863a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagjacobian, snes->iter)); 29899566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag)); 2990ebd3b9afSBarry Smith if (flag) { 29919566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 29929566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 2993ebd3b9afSBarry Smith } 29943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2995e35cf81dSBarry Smith } 2996efd4aadfSBarry Smith if (snes->npc && snes->npcside == PC_LEFT) { 29979566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 29989566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 29993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3000d728fb7dSPeter Brune } 3001e35cf81dSBarry Smith 30029566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_JacobianEval, snes, X, A, B)); 30039566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(X)); 3004800f99ffSJeremy L Thompson { 3005800f99ffSJeremy L Thompson void *ctx; 30068434afd1SBarry Smith SNESJacobianFn *J; 3007800f99ffSJeremy L Thompson PetscCall(DMSNESGetJacobian(dm, &J, &ctx)); 3008800f99ffSJeremy L Thompson PetscCallBack("SNES callback Jacobian", (*J)(snes, X, A, B, ctx)); 3009800f99ffSJeremy L Thompson } 30109566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(X)); 30119566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_JacobianEval, snes, X, A, B)); 301228d58a37SPierre Jolivet 30137addb90fSBarry Smith /* attach latest linearization point to the matrix used to construct the preconditioner */ 30149566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)B, "__SNES_latest_X", (PetscObject)X)); 3015a8054027SBarry Smith 3016e0e3a89bSBarry Smith /* the next line ensures that snes->ksp exists */ 30179566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 30183b4f5425SBarry Smith if (snes->lagpreconditioner == -2) { 30199566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Rebuilding preconditioner exactly once since lag is -2\n")); 30209566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE)); 30213b4f5425SBarry Smith snes->lagpreconditioner = -1; 30223b4f5425SBarry Smith } else if (snes->lagpreconditioner == -1) { 30239566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is -1\n")); 30249566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE)); 302537ec4e1aSPeter Brune } else if (snes->lagpreconditioner > 1 && (snes->iter + snes->pre_iter) % snes->lagpreconditioner) { 302663a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagpreconditioner, snes->iter)); 30279566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE)); 3028d1e9a80fSBarry Smith } else { 30299566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Rebuilding preconditioner\n")); 30309566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE)); 3031a8054027SBarry Smith } 3032a8054027SBarry Smith 30334df93895SStefano Zampini /* monkey business to allow testing Jacobians in multilevel solvers. 30344df93895SStefano Zampini This is needed because the SNESTestXXX interface does not accept vectors and matrices */ 30354df93895SStefano Zampini { 30364df93895SStefano Zampini Vec xsave = snes->vec_sol; 30374df93895SStefano Zampini Mat jacobiansave = snes->jacobian; 30384df93895SStefano Zampini Mat jacobian_presave = snes->jacobian_pre; 30394df93895SStefano Zampini 30404df93895SStefano Zampini snes->vec_sol = X; 30414df93895SStefano Zampini snes->jacobian = A; 30424df93895SStefano Zampini snes->jacobian_pre = B; 30431dfd7622SMatthew Knepley if (snes->testFunc) PetscCall(SNESTestFunction(snes)); 30441dfd7622SMatthew Knepley if (snes->testJac) PetscCall(SNESTestJacobian(snes, NULL, NULL)); 3045494a190aSStefano Zampini 30464df93895SStefano Zampini snes->vec_sol = xsave; 30474df93895SStefano Zampini snes->jacobian = jacobiansave; 30484df93895SStefano Zampini snes->jacobian_pre = jacobian_presave; 30494df93895SStefano Zampini } 30504df93895SStefano Zampini 3051693365a8SJed Brown { 3052693365a8SJed Brown PetscBool flag = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_operator = PETSC_FALSE; 3053648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit", NULL, NULL, &flag)); 3054648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw", NULL, NULL, &flag_draw)); 3055648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw_contour", NULL, NULL, &flag_contour)); 3056648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_operator", NULL, NULL, &flag_operator)); 3057693365a8SJed Brown if (flag || flag_draw || flag_contour) { 30580298fd71SBarry Smith Mat Bexp_mine = NULL, Bexp, FDexp; 3059693365a8SJed Brown PetscViewer vdraw, vstdout; 30606b3a5b13SJed Brown PetscBool flg; 3061693365a8SJed Brown if (flag_operator) { 30629566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(A, MATAIJ, &Bexp_mine)); 3063693365a8SJed Brown Bexp = Bexp_mine; 3064693365a8SJed Brown } else { 30657addb90fSBarry Smith /* See if the matrix used to construct the preconditioner can be viewed and added directly */ 30669566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)B, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPIBAIJ, "")); 306794ab13aaSBarry Smith if (flg) Bexp = B; 3068693365a8SJed Brown else { 3069693365a8SJed Brown /* If the "preconditioning" matrix is itself MATSHELL or some other type without direct support */ 30709566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(B, MATAIJ, &Bexp_mine)); 3071693365a8SJed Brown Bexp = Bexp_mine; 3072693365a8SJed Brown } 3073693365a8SJed Brown } 30749566063dSJacob Faibussowitsch PetscCall(MatConvert(Bexp, MATSAME, MAT_INITIAL_MATRIX, &FDexp)); 30759566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobianDefault(snes, X, FDexp, FDexp, NULL)); 30769566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout)); 3077693365a8SJed Brown if (flag_draw || flag_contour) { 30789566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Explicit Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw)); 30799566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 30800298fd71SBarry Smith } else vdraw = NULL; 30819566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit %s\n", flag_operator ? "Jacobian" : "preconditioning Jacobian")); 30829566063dSJacob Faibussowitsch if (flag) PetscCall(MatView(Bexp, vstdout)); 30839566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(Bexp, vdraw)); 30849566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Finite difference Jacobian\n")); 30859566063dSJacob Faibussowitsch if (flag) PetscCall(MatView(FDexp, vstdout)); 30869566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(FDexp, vdraw)); 30879566063dSJacob Faibussowitsch PetscCall(MatAYPX(FDexp, -1.0, Bexp, SAME_NONZERO_PATTERN)); 30889566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian\n")); 30899566063dSJacob Faibussowitsch if (flag) PetscCall(MatView(FDexp, vstdout)); 3090693365a8SJed Brown if (vdraw) { /* Always use contour for the difference */ 30919566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 30929566063dSJacob Faibussowitsch PetscCall(MatView(FDexp, vdraw)); 30939566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(vdraw)); 3094693365a8SJed Brown } 30959566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw)); 30969566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&vdraw)); 30979566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bexp_mine)); 30989566063dSJacob Faibussowitsch PetscCall(MatDestroy(&FDexp)); 3099693365a8SJed Brown } 3100693365a8SJed Brown } 31014c30e9fbSJed Brown { 31026719d8e4SJed Brown PetscBool flag = PETSC_FALSE, flag_display = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_threshold = PETSC_FALSE; 31036719d8e4SJed Brown PetscReal threshold_atol = PETSC_SQRT_MACHINE_EPSILON, threshold_rtol = 10 * PETSC_SQRT_MACHINE_EPSILON; 3104648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring", NULL, NULL, &flag)); 3105648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_display", NULL, NULL, &flag_display)); 3106648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw", NULL, NULL, &flag_draw)); 3107648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw_contour", NULL, NULL, &flag_contour)); 3108648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold", NULL, NULL, &flag_threshold)); 310927b0f280SBarry Smith if (flag_threshold) { 31109566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_rtol", &threshold_rtol, NULL)); 31119566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_atol", &threshold_atol, NULL)); 311227b0f280SBarry Smith } 31136719d8e4SJed Brown if (flag || flag_display || flag_draw || flag_contour || flag_threshold) { 31144c30e9fbSJed Brown Mat Bfd; 31154c30e9fbSJed Brown PetscViewer vdraw, vstdout; 3116335efc43SPeter Brune MatColoring coloring; 31174c30e9fbSJed Brown ISColoring iscoloring; 31184c30e9fbSJed Brown MatFDColoring matfdcoloring; 31198434afd1SBarry Smith SNESFunctionFn *func; 31204c30e9fbSJed Brown void *funcctx; 31216719d8e4SJed Brown PetscReal norm1, norm2, normmax; 31224c30e9fbSJed Brown 31239566063dSJacob Faibussowitsch PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &Bfd)); 31249566063dSJacob Faibussowitsch PetscCall(MatColoringCreate(Bfd, &coloring)); 31259566063dSJacob Faibussowitsch PetscCall(MatColoringSetType(coloring, MATCOLORINGSL)); 31269566063dSJacob Faibussowitsch PetscCall(MatColoringSetFromOptions(coloring)); 31279566063dSJacob Faibussowitsch PetscCall(MatColoringApply(coloring, &iscoloring)); 31289566063dSJacob Faibussowitsch PetscCall(MatColoringDestroy(&coloring)); 31299566063dSJacob Faibussowitsch PetscCall(MatFDColoringCreate(Bfd, iscoloring, &matfdcoloring)); 31309566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFromOptions(matfdcoloring)); 31319566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetUp(Bfd, iscoloring, matfdcoloring)); 31329566063dSJacob Faibussowitsch PetscCall(ISColoringDestroy(&iscoloring)); 31334c30e9fbSJed Brown 31344c30e9fbSJed Brown /* This method of getting the function is currently unreliable since it doesn't work for DM local functions. */ 31359566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, &func, &funcctx)); 31362ba42892SBarry Smith PetscCall(MatFDColoringSetFunction(matfdcoloring, (MatFDColoringFn *)func, funcctx)); 31379566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)matfdcoloring, ((PetscObject)snes)->prefix)); 31389566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)matfdcoloring, "coloring_")); 31399566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFromOptions(matfdcoloring)); 31409566063dSJacob Faibussowitsch PetscCall(MatFDColoringApply(Bfd, matfdcoloring, X, snes)); 31419566063dSJacob Faibussowitsch PetscCall(MatFDColoringDestroy(&matfdcoloring)); 31424c30e9fbSJed Brown 31439566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout)); 31444c30e9fbSJed Brown if (flag_draw || flag_contour) { 31459566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Colored Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw)); 31469566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 31470298fd71SBarry Smith } else vdraw = NULL; 31489566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit preconditioning Jacobian\n")); 31499566063dSJacob Faibussowitsch if (flag_display) PetscCall(MatView(B, vstdout)); 31509566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(B, vdraw)); 31519566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Colored Finite difference Jacobian\n")); 31529566063dSJacob Faibussowitsch if (flag_display) PetscCall(MatView(Bfd, vstdout)); 31539566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(Bfd, vdraw)); 31549566063dSJacob Faibussowitsch PetscCall(MatAYPX(Bfd, -1.0, B, SAME_NONZERO_PATTERN)); 31559566063dSJacob Faibussowitsch PetscCall(MatNorm(Bfd, NORM_1, &norm1)); 31569566063dSJacob Faibussowitsch PetscCall(MatNorm(Bfd, NORM_FROBENIUS, &norm2)); 31579566063dSJacob Faibussowitsch PetscCall(MatNorm(Bfd, NORM_MAX, &normmax)); 31589566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian, norm1=%g normFrob=%g normmax=%g\n", (double)norm1, (double)norm2, (double)normmax)); 31599566063dSJacob Faibussowitsch if (flag_display) PetscCall(MatView(Bfd, vstdout)); 31604c30e9fbSJed Brown if (vdraw) { /* Always use contour for the difference */ 31619566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 31629566063dSJacob Faibussowitsch PetscCall(MatView(Bfd, vdraw)); 31639566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(vdraw)); 31644c30e9fbSJed Brown } 31659566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw)); 31666719d8e4SJed Brown 31676719d8e4SJed Brown if (flag_threshold) { 31686719d8e4SJed Brown PetscInt bs, rstart, rend, i; 31699566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(B, &bs)); 31709566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(B, &rstart, &rend)); 31716719d8e4SJed Brown for (i = rstart; i < rend; i++) { 31726719d8e4SJed Brown const PetscScalar *ba, *ca; 31736719d8e4SJed Brown const PetscInt *bj, *cj; 31746719d8e4SJed Brown PetscInt bn, cn, j, maxentrycol = -1, maxdiffcol = -1, maxrdiffcol = -1; 31756719d8e4SJed Brown PetscReal maxentry = 0, maxdiff = 0, maxrdiff = 0; 31769566063dSJacob Faibussowitsch PetscCall(MatGetRow(B, i, &bn, &bj, &ba)); 31779566063dSJacob Faibussowitsch PetscCall(MatGetRow(Bfd, i, &cn, &cj, &ca)); 31785f80ce2aSJacob Faibussowitsch PetscCheck(bn == cn, ((PetscObject)A)->comm, PETSC_ERR_PLIB, "Unexpected different nonzero pattern in -snes_compare_coloring_threshold"); 31796719d8e4SJed Brown for (j = 0; j < bn; j++) { 31806719d8e4SJed Brown PetscReal rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j])); 31816719d8e4SJed Brown if (PetscAbsScalar(ba[j]) > PetscAbs(maxentry)) { 31826719d8e4SJed Brown maxentrycol = bj[j]; 31836719d8e4SJed Brown maxentry = PetscRealPart(ba[j]); 31846719d8e4SJed Brown } 31856719d8e4SJed Brown if (PetscAbsScalar(ca[j]) > PetscAbs(maxdiff)) { 31866719d8e4SJed Brown maxdiffcol = bj[j]; 31876719d8e4SJed Brown maxdiff = PetscRealPart(ca[j]); 31886719d8e4SJed Brown } 31896719d8e4SJed Brown if (rdiff > maxrdiff) { 31906719d8e4SJed Brown maxrdiffcol = bj[j]; 31916719d8e4SJed Brown maxrdiff = rdiff; 31926719d8e4SJed Brown } 31936719d8e4SJed Brown } 31946719d8e4SJed Brown if (maxrdiff > 1) { 319563a3b9bcSJacob 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)); 31966719d8e4SJed Brown for (j = 0; j < bn; j++) { 31976719d8e4SJed Brown PetscReal rdiff; 31986719d8e4SJed Brown rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j])); 319948a46eb9SPierre Jolivet if (rdiff > 1) PetscCall(PetscViewerASCIIPrintf(vstdout, " (%" PetscInt_FMT ",%g:%g)", bj[j], (double)PetscRealPart(ba[j]), (double)PetscRealPart(ca[j]))); 32006719d8e4SJed Brown } 320163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "\n")); 32026719d8e4SJed Brown } 32039566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(B, i, &bn, &bj, &ba)); 32049566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(Bfd, i, &cn, &cj, &ca)); 32056719d8e4SJed Brown } 32066719d8e4SJed Brown } 32079566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&vdraw)); 32089566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bfd)); 32094c30e9fbSJed Brown } 32104c30e9fbSJed Brown } 32113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 32129b94acceSBarry Smith } 32139b94acceSBarry Smith 32149b94acceSBarry Smith /*@C 32159b94acceSBarry Smith SNESSetJacobian - Sets the function to compute Jacobian as well as the 3216044dda88SLois Curfman McInnes location to store the matrix. 32179b94acceSBarry Smith 3218c3339decSBarry Smith Logically Collective 3219c7afd0dbSLois Curfman McInnes 32209b94acceSBarry Smith Input Parameters: 3221f6dfbefdSBarry Smith + snes - the `SNES` context 3222e5d3d808SBarry Smith . Amat - the matrix that defines the (approximate) Jacobian 3223dc4c0fb0SBarry Smith . Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`. 32248434afd1SBarry Smith . J - Jacobian evaluation routine (if `NULL` then `SNES` retains any previously set value), see `SNESJacobianFn` for details 3225c7afd0dbSLois Curfman McInnes - ctx - [optional] user-defined context for private data for the 3226dc4c0fb0SBarry Smith Jacobian evaluation routine (may be `NULL`) (if `NULL` then `SNES` retains any previously set value) 3227dc4c0fb0SBarry Smith 3228dc4c0fb0SBarry Smith Level: beginner 32299b94acceSBarry Smith 32309b94acceSBarry Smith Notes: 3231dc4c0fb0SBarry Smith If the `Amat` matrix and `Pmat` matrix are different you must call `MatAssemblyBegin()`/`MatAssemblyEnd()` on 323216913363SBarry Smith each matrix. 323316913363SBarry Smith 3234dc4c0fb0SBarry Smith If you know the operator `Amat` has a null space you can use `MatSetNullSpace()` and `MatSetTransposeNullSpace()` to supply the null 3235dc4c0fb0SBarry Smith space to `Amat` and the `KSP` solvers will automatically use that null space as needed during the solution process. 3236895c21f2SBarry Smith 3237dc4c0fb0SBarry Smith If using `SNESComputeJacobianDefaultColor()` to assemble a Jacobian, the `ctx` argument 3238f6dfbefdSBarry Smith must be a `MatFDColoring`. 3239a8a26c1eSJed Brown 3240c3cc8fd1SJed Brown Other defect-correction schemes can be used by computing a different matrix in place of the Jacobian. One common 3241f6dfbefdSBarry Smith example is to use the "Picard linearization" which only differentiates through the highest order parts of each term using `SNESSetPicard()` 3242c3cc8fd1SJed Brown 32431cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSPSetOperators()`, `SNESSetFunction()`, `MatMFFDComputeJacobian()`, `SNESComputeJacobianDefaultColor()`, `MatStructure`, 32448434afd1SBarry Smith `SNESSetPicard()`, `SNESJacobianFn`, `SNESFunctionFn` 32459b94acceSBarry Smith @*/ 32468434afd1SBarry Smith PetscErrorCode SNESSetJacobian(SNES snes, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx) 3247d71ae5a4SJacob Faibussowitsch { 32486cab3a1bSJed Brown DM dm; 32493a7fca6bSBarry Smith 32503a40ed3dSBarry Smith PetscFunctionBegin; 32510700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3252e5d3d808SBarry Smith if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2); 3253e5d3d808SBarry Smith if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3); 3254e5d3d808SBarry Smith if (Amat) PetscCheckSameComm(snes, 1, Amat, 2); 3255e5d3d808SBarry Smith if (Pmat) PetscCheckSameComm(snes, 1, Pmat, 3); 32569566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 32579566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, J, ctx)); 3258e5d3d808SBarry Smith if (Amat) { 32599566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)Amat)); 32609566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian)); 3261f5af7f23SKarl Rupp 3262e5d3d808SBarry Smith snes->jacobian = Amat; 32633a7fca6bSBarry Smith } 3264e5d3d808SBarry Smith if (Pmat) { 32659566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)Pmat)); 32669566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian_pre)); 3267f5af7f23SKarl Rupp 3268e5d3d808SBarry Smith snes->jacobian_pre = Pmat; 32693a7fca6bSBarry Smith } 32703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 32719b94acceSBarry Smith } 327262fef451SLois Curfman McInnes 3273c2aafc4cSSatish Balay /*@C 3274b4fd4287SBarry Smith SNESGetJacobian - Returns the Jacobian matrix and optionally the user 3275b4fd4287SBarry Smith provided context for evaluating the Jacobian. 3276b4fd4287SBarry Smith 3277420bcc1bSBarry Smith Not Collective, but `Mat` object will be parallel if `SNES` is 3278c7afd0dbSLois Curfman McInnes 3279b4fd4287SBarry Smith Input Parameter: 3280b4fd4287SBarry Smith . snes - the nonlinear solver context 3281b4fd4287SBarry Smith 3282b4fd4287SBarry Smith Output Parameters: 3283dc4c0fb0SBarry Smith + Amat - location to stash (approximate) Jacobian matrix (or `NULL`) 3284dc4c0fb0SBarry Smith . Pmat - location to stash matrix used to compute the preconditioner (or `NULL`) 32858434afd1SBarry Smith . J - location to put Jacobian function (or `NULL`), for calling sequence see `SNESJacobianFn` 3286dc4c0fb0SBarry Smith - ctx - location to stash Jacobian ctx (or `NULL`) 3287fee21e36SBarry Smith 328836851e7fSLois Curfman McInnes Level: advanced 328936851e7fSLois Curfman McInnes 32908434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `Mat`, `SNESSetJacobian()`, `SNESComputeJacobian()`, `SNESJacobianFn`, `SNESGetFunction()` 3291b4fd4287SBarry Smith @*/ 32928434afd1SBarry Smith PetscErrorCode SNESGetJacobian(SNES snes, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx) 3293d71ae5a4SJacob Faibussowitsch { 32946cab3a1bSJed Brown DM dm; 32956cab3a1bSJed Brown 32963a40ed3dSBarry Smith PetscFunctionBegin; 32970700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3298e5d3d808SBarry Smith if (Amat) *Amat = snes->jacobian; 3299e5d3d808SBarry Smith if (Pmat) *Pmat = snes->jacobian_pre; 33009566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 3301800f99ffSJeremy L Thompson PetscCall(DMSNESGetJacobian(dm, J, ctx)); 33023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3303b4fd4287SBarry Smith } 3304b4fd4287SBarry Smith 3305d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetDefaultComputeJacobian(SNES snes) 3306d71ae5a4SJacob Faibussowitsch { 330758b371f3SBarry Smith DM dm; 330858b371f3SBarry Smith DMSNES sdm; 330958b371f3SBarry Smith 331058b371f3SBarry Smith PetscFunctionBegin; 33119566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 33129566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 331358b371f3SBarry Smith if (!sdm->ops->computejacobian && snes->jacobian_pre) { 331458b371f3SBarry Smith DM dm; 331558b371f3SBarry Smith PetscBool isdense, ismf; 331658b371f3SBarry Smith 33179566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 33189566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &isdense, MATSEQDENSE, MATMPIDENSE, MATDENSE, NULL)); 33199566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &ismf, MATMFFD, MATSHELL, NULL)); 332058b371f3SBarry Smith if (isdense) { 33219566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefault, NULL)); 332258b371f3SBarry Smith } else if (!ismf) { 33239566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefaultColor, NULL)); 332458b371f3SBarry Smith } 332558b371f3SBarry Smith } 33263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 332758b371f3SBarry Smith } 332858b371f3SBarry Smith 33299b94acceSBarry Smith /*@ 33309b94acceSBarry Smith SNESSetUp - Sets up the internal data structures for the later use 33310b4b7b1cSBarry Smith of a nonlinear solver `SNESSolve()`. 33329b94acceSBarry Smith 3333c3339decSBarry Smith Collective 3334fee21e36SBarry Smith 33352fe279fdSBarry Smith Input Parameter: 3336f6dfbefdSBarry Smith . snes - the `SNES` context 3337c7afd0dbSLois Curfman McInnes 3338dc4c0fb0SBarry Smith Level: advanced 3339dc4c0fb0SBarry Smith 3340f6dfbefdSBarry Smith Note: 33410b4b7b1cSBarry Smith For basic use of the `SNES` solvers the user does not need to explicitly call 3342f6dfbefdSBarry Smith `SNESSetUp()`, since these actions will automatically occur during 3343f6dfbefdSBarry Smith the call to `SNESSolve()`. However, if one wishes to control this 3344f6dfbefdSBarry Smith phase separately, `SNESSetUp()` should be called after `SNESCreate()` 3345f6dfbefdSBarry Smith and optional routines of the form SNESSetXXX(), but before `SNESSolve()`. 3346272ac6f2SLois Curfman McInnes 33470b4b7b1cSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`, `SNESDestroy()`, `SNESSetFromOptions()` 33489b94acceSBarry Smith @*/ 3349d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUp(SNES snes) 3350d71ae5a4SJacob Faibussowitsch { 33516cab3a1bSJed Brown DM dm; 3352942e3340SBarry Smith DMSNES sdm; 3353c35f09e5SBarry Smith SNESLineSearch linesearch, pclinesearch; 33546e2a1849SPeter Brune void *lsprectx, *lspostctx; 33559b5c1c08SStefano Zampini PetscBool mf_operator, mf; 33569b5c1c08SStefano Zampini Vec f, fpc; 33579b5c1c08SStefano Zampini void *funcctx; 33589b5c1c08SStefano Zampini void *jacctx, *appctx; 33599b5c1c08SStefano Zampini Mat j, jpre; 33606b2b7091SBarry Smith PetscErrorCode (*precheck)(SNESLineSearch, Vec, Vec, PetscBool *, void *); 33616b2b7091SBarry Smith PetscErrorCode (*postcheck)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *); 33628434afd1SBarry Smith SNESFunctionFn *func; 33638434afd1SBarry Smith SNESJacobianFn *jac; 33643a40ed3dSBarry Smith 33653a40ed3dSBarry Smith PetscFunctionBegin; 33660700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 33673ba16761SJacob Faibussowitsch if (snes->setupcalled) PetscFunctionReturn(PETSC_SUCCESS); 3368fc8bc0e3SRichard Tran Mills PetscCall(PetscLogEventBegin(SNES_SetUp, snes, 0, 0, 0)); 33699b94acceSBarry Smith 337048a46eb9SPierre Jolivet if (!((PetscObject)snes)->type_name) PetscCall(SNESSetType(snes, SNESNEWTONLS)); 337185385478SLisandro Dalcin 33729566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &snes->vec_func, NULL, NULL)); 337358c9b817SLisandro Dalcin 33749566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 33759566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 33769566063dSJacob Faibussowitsch PetscCall(SNESSetDefaultComputeJacobian(snes)); 337758b371f3SBarry Smith 337848a46eb9SPierre Jolivet if (!snes->vec_func) PetscCall(DMCreateGlobalVector(dm, &snes->vec_func)); 3379efd51863SBarry Smith 338048a46eb9SPierre Jolivet if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 3381b710008aSBarry Smith 3382d8d34be6SBarry Smith if (snes->linesearch) { 33839566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 33849566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetFunction(snes->linesearch, SNESComputeFunction)); 3385d8d34be6SBarry Smith } 33869e764e56SPeter Brune 33879b5c1c08SStefano Zampini PetscCall(SNESGetUseMatrixFree(snes, &mf_operator, &mf)); 3388b552625fSStefano Zampini if (snes->npc && snes->npcside == PC_LEFT) { 3389172a4300SPeter Brune snes->mf = PETSC_TRUE; 3390172a4300SPeter Brune snes->mf_operator = PETSC_FALSE; 3391172a4300SPeter Brune } 3392d8f46077SPeter Brune 3393efd4aadfSBarry Smith if (snes->npc) { 33946e2a1849SPeter Brune /* copy the DM over */ 33959566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 33969566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes->npc, dm)); 33976e2a1849SPeter Brune 33989566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &f, &func, &funcctx)); 33999566063dSJacob Faibussowitsch PetscCall(VecDuplicate(f, &fpc)); 34009566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes->npc, fpc, func, funcctx)); 34019566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, &j, &jpre, &jac, &jacctx)); 34029566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes->npc, j, jpre, jac, jacctx)); 34039566063dSJacob Faibussowitsch PetscCall(SNESGetApplicationContext(snes, &appctx)); 34049566063dSJacob Faibussowitsch PetscCall(SNESSetApplicationContext(snes->npc, appctx)); 34059b5c1c08SStefano Zampini PetscCall(SNESSetUseMatrixFree(snes->npc, mf_operator, mf)); 34069566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fpc)); 34076e2a1849SPeter Brune 34086e2a1849SPeter Brune /* copy the function pointers over */ 34099566063dSJacob Faibussowitsch PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)snes->npc)); 34106e2a1849SPeter Brune 34116e2a1849SPeter Brune /* default to 1 iteration */ 34129566063dSJacob Faibussowitsch PetscCall(SNESSetTolerances(snes->npc, 0.0, 0.0, 0.0, 1, snes->npc->max_funcs)); 3413efd4aadfSBarry Smith if (snes->npcside == PC_RIGHT) { 34149566063dSJacob Faibussowitsch PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_FINAL_ONLY)); 3415a9936a0cSPeter Brune } else { 34169566063dSJacob Faibussowitsch PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_NONE)); 3417a9936a0cSPeter Brune } 34189566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes->npc)); 34196e2a1849SPeter Brune 34206e2a1849SPeter Brune /* copy the line search context over */ 3421d8d34be6SBarry Smith if (snes->linesearch && snes->npc->linesearch) { 34229566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &linesearch)); 34239566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes->npc, &pclinesearch)); 34249566063dSJacob Faibussowitsch PetscCall(SNESLineSearchGetPreCheck(linesearch, &precheck, &lsprectx)); 34259566063dSJacob Faibussowitsch PetscCall(SNESLineSearchGetPostCheck(linesearch, &postcheck, &lspostctx)); 34269566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetPreCheck(pclinesearch, precheck, lsprectx)); 34279566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetPostCheck(pclinesearch, postcheck, lspostctx)); 34289566063dSJacob Faibussowitsch PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch)); 34296e2a1849SPeter Brune } 3430d8d34be6SBarry Smith } 34311baa6e33SBarry Smith if (snes->mf) PetscCall(SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version)); 3432835f2295SStefano Zampini if (snes->ops->usercompute && !snes->ctx) PetscCallBack("SNES callback compute application context", (*snes->ops->usercompute)(snes, &snes->ctx)); 34336e2a1849SPeter Brune 343437ec4e1aSPeter Brune snes->jac_iter = 0; 343537ec4e1aSPeter Brune snes->pre_iter = 0; 343637ec4e1aSPeter Brune 3437dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, setup); 343858c9b817SLisandro Dalcin 34399566063dSJacob Faibussowitsch PetscCall(SNESSetDefaultComputeJacobian(snes)); 344058b371f3SBarry Smith 3441b552625fSStefano Zampini if (snes->npc && snes->npcside == PC_LEFT) { 34426c67d002SPeter Brune if (snes->functype == SNES_FUNCTION_PRECONDITIONED) { 3443d8d34be6SBarry Smith if (snes->linesearch) { 34449566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &linesearch)); 34459566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunctionDefaultNPC)); 34466c67d002SPeter Brune } 34476c67d002SPeter Brune } 3448d8d34be6SBarry Smith } 3449fc8bc0e3SRichard Tran Mills PetscCall(PetscLogEventEnd(SNES_SetUp, snes, 0, 0, 0)); 34507aaed0d8SBarry Smith snes->setupcalled = PETSC_TRUE; 34513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 34529b94acceSBarry Smith } 34539b94acceSBarry Smith 345437596af1SLisandro Dalcin /*@ 34550b4b7b1cSBarry 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 345637596af1SLisandro Dalcin 3457c3339decSBarry Smith Collective 345837596af1SLisandro Dalcin 345937596af1SLisandro Dalcin Input Parameter: 34600b4b7b1cSBarry Smith . snes - the nonlinear iterative solver context obtained from `SNESCreate()` 346137596af1SLisandro Dalcin 3462d25893d9SBarry Smith Level: intermediate 3463d25893d9SBarry Smith 346495452b02SPatrick Sanan Notes: 34650b4b7b1cSBarry Smith Any options set on the `SNES` object, including those set with `SNESSetFromOptions()` remain. 34660b4b7b1cSBarry Smith 3467f6dfbefdSBarry Smith Call this if you wish to reuse a `SNES` but with different size vectors 346837596af1SLisandro Dalcin 3469f6dfbefdSBarry Smith Also calls the application context destroy routine set with `SNESSetComputeApplicationContext()` 3470f6dfbefdSBarry Smith 34711cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESDestroy()`, `SNESCreate()`, `SNESSetUp()`, `SNESSolve()` 347237596af1SLisandro Dalcin @*/ 3473d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESReset(SNES snes) 3474d71ae5a4SJacob Faibussowitsch { 347537596af1SLisandro Dalcin PetscFunctionBegin; 347637596af1SLisandro Dalcin PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 347749abdd8aSBarry Smith if (snes->ops->ctxdestroy && snes->ctx) { 3478835f2295SStefano Zampini PetscCallBack("SNES callback destroy application context", (*snes->ops->ctxdestroy)(&snes->ctx)); 347949abdd8aSBarry Smith snes->ctx = NULL; 3480d25893d9SBarry Smith } 34811baa6e33SBarry Smith if (snes->npc) PetscCall(SNESReset(snes->npc)); 34828a23116dSBarry Smith 3483dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, reset); 34841baa6e33SBarry Smith if (snes->ksp) PetscCall(KSPReset(snes->ksp)); 34859e764e56SPeter Brune 34861baa6e33SBarry Smith if (snes->linesearch) PetscCall(SNESLineSearchReset(snes->linesearch)); 34879e764e56SPeter Brune 34889566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_rhs)); 34899566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol)); 34909566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol_update)); 34919566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_func)); 34929566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian)); 34939566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian_pre)); 34949566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->picard)); 34959566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(snes->nwork, &snes->work)); 34969566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(snes->nvwork, &snes->vwork)); 3497f5af7f23SKarl Rupp 349840fdac6aSLawrence Mitchell snes->alwayscomputesfinalresidual = PETSC_FALSE; 349940fdac6aSLawrence Mitchell 350037596af1SLisandro Dalcin snes->nwork = snes->nvwork = 0; 350137596af1SLisandro Dalcin snes->setupcalled = PETSC_FALSE; 35023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 350337596af1SLisandro Dalcin } 350437596af1SLisandro Dalcin 350552baeb72SSatish Balay /*@ 350636d43d94SBarry Smith SNESConvergedReasonViewCancel - Clears all the reason view functions for a `SNES` object provided with `SNESConvergedReasonViewSet()` also 350736d43d94SBarry Smith removes the default viewer. 3508c4421ceaSFande Kong 3509c3339decSBarry Smith Collective 3510c4421ceaSFande Kong 3511c4421ceaSFande Kong Input Parameter: 35120b4b7b1cSBarry Smith . snes - the nonlinear iterative solver context obtained from `SNESCreate()` 3513c4421ceaSFande Kong 3514c4421ceaSFande Kong Level: intermediate 3515c4421ceaSFande Kong 3516420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESReset()`, `SNESConvergedReasonViewSet()` 3517c4421ceaSFande Kong @*/ 3518d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewCancel(SNES snes) 3519d71ae5a4SJacob Faibussowitsch { 3520c4421ceaSFande Kong PetscInt i; 3521c4421ceaSFande Kong 3522c4421ceaSFande Kong PetscFunctionBegin; 3523c4421ceaSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3524c4421ceaSFande Kong for (i = 0; i < snes->numberreasonviews; i++) { 352548a46eb9SPierre Jolivet if (snes->reasonviewdestroy[i]) PetscCall((*snes->reasonviewdestroy[i])(&snes->reasonviewcontext[i])); 3526c4421ceaSFande Kong } 3527c4421ceaSFande Kong snes->numberreasonviews = 0; 3528648c30bcSBarry Smith PetscCall(PetscViewerDestroy(&snes->convergedreasonviewer)); 35293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3530c4421ceaSFande Kong } 3531c4421ceaSFande Kong 35320764c050SBarry Smith /*@ 35339b94acceSBarry Smith SNESDestroy - Destroys the nonlinear solver context that was created 3534f6dfbefdSBarry Smith with `SNESCreate()`. 35359b94acceSBarry Smith 3536c3339decSBarry Smith Collective 3537c7afd0dbSLois Curfman McInnes 35389b94acceSBarry Smith Input Parameter: 3539f6dfbefdSBarry Smith . snes - the `SNES` context 35409b94acceSBarry Smith 354136851e7fSLois Curfman McInnes Level: beginner 354236851e7fSLois Curfman McInnes 35431cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()` 35449b94acceSBarry Smith @*/ 3545d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESDestroy(SNES *snes) 3546d71ae5a4SJacob Faibussowitsch { 354792e852f7SPablo Brubeck DM dm; 354892e852f7SPablo Brubeck 35493a40ed3dSBarry Smith PetscFunctionBegin; 35503ba16761SJacob Faibussowitsch if (!*snes) PetscFunctionReturn(PETSC_SUCCESS); 3551f4f49eeaSPierre Jolivet PetscValidHeaderSpecific(*snes, SNES_CLASSID, 1); 3552f4f49eeaSPierre Jolivet if (--((PetscObject)*snes)->refct > 0) { 35539371c9d4SSatish Balay *snes = NULL; 35543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 35559371c9d4SSatish Balay } 3556d4bb536fSBarry Smith 3557f4f49eeaSPierre Jolivet PetscCall(SNESReset(*snes)); 35589566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&(*snes)->npc)); 35596b8b9a38SLisandro Dalcin 3560e04113cfSBarry Smith /* if memory was published with SAWs then destroy it */ 35619566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsViewOff((PetscObject)*snes)); 3562f4f49eeaSPierre Jolivet PetscTryTypeMethod(*snes, destroy); 35636d4c513bSLisandro Dalcin 356492e852f7SPablo Brubeck dm = (*snes)->dm; 356592e852f7SPablo Brubeck while (dm) { 356692e852f7SPablo Brubeck PetscCall(DMCoarsenHookRemove(dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, *snes)); 356792e852f7SPablo Brubeck PetscCall(DMGetCoarseDM(dm, &dm)); 356892e852f7SPablo Brubeck } 356992e852f7SPablo Brubeck 35709566063dSJacob Faibussowitsch PetscCall(DMDestroy(&(*snes)->dm)); 35719566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&(*snes)->ksp)); 35729566063dSJacob Faibussowitsch PetscCall(SNESLineSearchDestroy(&(*snes)->linesearch)); 35736b8b9a38SLisandro Dalcin 35749566063dSJacob Faibussowitsch PetscCall(PetscFree((*snes)->kspconvctx)); 3575*12651944SBarry Smith if ((*snes)->ops->convergeddestroy) PetscCall((*(*snes)->ops->convergeddestroy)(&(*snes)->cnvP)); 357648a46eb9SPierre Jolivet if ((*snes)->conv_hist_alloc) PetscCall(PetscFree2((*snes)->conv_hist, (*snes)->conv_hist_its)); 3577f4f49eeaSPierre Jolivet PetscCall(SNESMonitorCancel(*snes)); 3578f4f49eeaSPierre Jolivet PetscCall(SNESConvergedReasonViewCancel(*snes)); 35799566063dSJacob Faibussowitsch PetscCall(PetscHeaderDestroy(snes)); 35803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 35819b94acceSBarry Smith } 35829b94acceSBarry Smith 35839b94acceSBarry Smith /* ----------- Routines to set solver parameters ---------- */ 35849b94acceSBarry Smith 3585a8054027SBarry Smith /*@ 35860b4b7b1cSBarry Smith SNESSetLagPreconditioner - Sets when the preconditioner is rebuilt in the nonlinear solve `SNESSolve()`. 3587a8054027SBarry Smith 3588c3339decSBarry Smith Logically Collective 3589a8054027SBarry Smith 3590a8054027SBarry Smith Input Parameters: 3591f6dfbefdSBarry Smith + snes - the `SNES` context 3592d8e291bfSBarry Smith - lag - 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time 35933b4f5425SBarry Smith the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that 3594a8054027SBarry Smith 3595a8054027SBarry Smith Options Database Keys: 3596420bcc1bSBarry Smith + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple `SNESSolve()` 35973d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 3598420bcc1bSBarry Smith . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple `SNESSolve()` 35993d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 3600a8054027SBarry Smith 3601dc4c0fb0SBarry Smith Level: intermediate 3602dc4c0fb0SBarry Smith 3603420bcc1bSBarry Smith Notes: 3604a8054027SBarry Smith The default is 1 3605420bcc1bSBarry Smith 3606f6dfbefdSBarry Smith The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagPreconditionerPersists()` was called 3607d8e291bfSBarry Smith 3608f6dfbefdSBarry Smith `SNESSetLagPreconditionerPersists()` allows using the same uniform lagging (for example every second linear solve) across multiple nonlinear solves. 3609a8054027SBarry Smith 36103201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetLagPreconditionerPersists()`, 3611f6dfbefdSBarry Smith `SNESSetLagJacobianPersists()`, `SNES`, `SNESSolve()` 3612a8054027SBarry Smith @*/ 3613d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditioner(SNES snes, PetscInt lag) 3614d71ae5a4SJacob Faibussowitsch { 3615a8054027SBarry Smith PetscFunctionBegin; 36160700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 36175f80ce2aSJacob Faibussowitsch PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater"); 36185f80ce2aSJacob Faibussowitsch PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0"); 3619c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, lag, 2); 3620a8054027SBarry Smith snes->lagpreconditioner = lag; 36213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3622a8054027SBarry Smith } 3623a8054027SBarry Smith 3624efd51863SBarry Smith /*@ 3625f6dfbefdSBarry Smith SNESSetGridSequence - sets the number of steps of grid sequencing that `SNES` will do 3626efd51863SBarry Smith 3627c3339decSBarry Smith Logically Collective 3628efd51863SBarry Smith 3629efd51863SBarry Smith Input Parameters: 3630f6dfbefdSBarry Smith + snes - the `SNES` context 3631efd51863SBarry Smith - steps - the number of refinements to do, defaults to 0 3632efd51863SBarry Smith 3633f6dfbefdSBarry Smith Options Database Key: 363467b8a455SSatish Balay . -snes_grid_sequence <steps> - Use grid sequencing to generate initial guess 3635efd51863SBarry Smith 3636efd51863SBarry Smith Level: intermediate 3637efd51863SBarry Smith 36380b4b7b1cSBarry Smith Notes: 36390b4b7b1cSBarry Smith Once grid sequencing is turned on `SNESSolve()` will automatically perform the solve on each grid refinement. 36400b4b7b1cSBarry Smith 3641f6dfbefdSBarry Smith Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing. 3642c0df2a02SJed Brown 36433201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetGridSequence()`, 364454c05997SPierre Jolivet `SNESSetDM()`, `SNESSolve()` 3645efd51863SBarry Smith @*/ 3646d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetGridSequence(SNES snes, PetscInt steps) 3647d71ae5a4SJacob Faibussowitsch { 3648efd51863SBarry Smith PetscFunctionBegin; 3649efd51863SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3650efd51863SBarry Smith PetscValidLogicalCollectiveInt(snes, steps, 2); 3651efd51863SBarry Smith snes->gridsequence = steps; 36523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3653efd51863SBarry Smith } 3654efd51863SBarry Smith 3655fa19ca70SBarry Smith /*@ 3656f6dfbefdSBarry Smith SNESGetGridSequence - gets the number of steps of grid sequencing that `SNES` will do 3657fa19ca70SBarry Smith 3658c3339decSBarry Smith Logically Collective 3659fa19ca70SBarry Smith 3660fa19ca70SBarry Smith Input Parameter: 3661f6dfbefdSBarry Smith . snes - the `SNES` context 3662fa19ca70SBarry Smith 3663fa19ca70SBarry Smith Output Parameter: 3664fa19ca70SBarry Smith . steps - the number of refinements to do, defaults to 0 3665fa19ca70SBarry Smith 3666fa19ca70SBarry Smith Level: intermediate 3667fa19ca70SBarry Smith 36683201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetGridSequence()` 3669fa19ca70SBarry Smith @*/ 3670d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetGridSequence(SNES snes, PetscInt *steps) 3671d71ae5a4SJacob Faibussowitsch { 3672fa19ca70SBarry Smith PetscFunctionBegin; 3673fa19ca70SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3674fa19ca70SBarry Smith *steps = snes->gridsequence; 36753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3676fa19ca70SBarry Smith } 3677fa19ca70SBarry Smith 3678a8054027SBarry Smith /*@ 3679f6dfbefdSBarry Smith SNESGetLagPreconditioner - Return how often the preconditioner is rebuilt 3680a8054027SBarry Smith 36813f9fe445SBarry Smith Not Collective 3682a8054027SBarry Smith 3683a8054027SBarry Smith Input Parameter: 3684f6dfbefdSBarry Smith . snes - the `SNES` context 3685a8054027SBarry Smith 3686a8054027SBarry Smith Output Parameter: 3687a8054027SBarry 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 36883b4f5425SBarry Smith the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that 3689a8054027SBarry Smith 3690dc4c0fb0SBarry Smith Level: intermediate 3691dc4c0fb0SBarry Smith 3692a8054027SBarry Smith Notes: 3693a8054027SBarry Smith The default is 1 3694f6dfbefdSBarry Smith 3695a8054027SBarry Smith The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 3696a8054027SBarry Smith 36973201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3698a8054027SBarry Smith @*/ 3699d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagPreconditioner(SNES snes, PetscInt *lag) 3700d71ae5a4SJacob Faibussowitsch { 3701a8054027SBarry Smith PetscFunctionBegin; 37020700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3703a8054027SBarry Smith *lag = snes->lagpreconditioner; 37043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3705a8054027SBarry Smith } 3706a8054027SBarry Smith 3707e35cf81dSBarry Smith /*@ 3708f6dfbefdSBarry Smith SNESSetLagJacobian - Set when the Jacobian is rebuilt in the nonlinear solve. See `SNESSetLagPreconditioner()` for determining how 3709e35cf81dSBarry Smith often the preconditioner is rebuilt. 3710e35cf81dSBarry Smith 3711c3339decSBarry Smith Logically Collective 3712e35cf81dSBarry Smith 3713e35cf81dSBarry Smith Input Parameters: 3714f6dfbefdSBarry Smith + snes - the `SNES` context 3715e35cf81dSBarry 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 3716fe3ffe1eSBarry Smith the Jacobian is built etc. -2 means rebuild at next chance but then never again 3717e35cf81dSBarry Smith 3718e35cf81dSBarry Smith Options Database Keys: 371979a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 37203d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 372179a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 37223d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag. 3723e35cf81dSBarry Smith 3724dc4c0fb0SBarry Smith Level: intermediate 3725dc4c0fb0SBarry Smith 3726e35cf81dSBarry Smith Notes: 3727e35cf81dSBarry Smith The default is 1 3728f6dfbefdSBarry Smith 3729e35cf81dSBarry Smith The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 3730f6dfbefdSBarry Smith 3731fe3ffe1eSBarry 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 3732fe3ffe1eSBarry Smith at the next Newton step but never again (unless it is reset to another value) 3733e35cf81dSBarry Smith 37343201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagPreconditioner()`, `SNESGetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3735e35cf81dSBarry Smith @*/ 3736d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobian(SNES snes, PetscInt lag) 3737d71ae5a4SJacob Faibussowitsch { 3738e35cf81dSBarry Smith PetscFunctionBegin; 37390700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 37405f80ce2aSJacob Faibussowitsch PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater"); 37415f80ce2aSJacob Faibussowitsch PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0"); 3742c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, lag, 2); 3743e35cf81dSBarry Smith snes->lagjacobian = lag; 37443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3745e35cf81dSBarry Smith } 3746e35cf81dSBarry Smith 3747e35cf81dSBarry Smith /*@ 3748f6dfbefdSBarry Smith SNESGetLagJacobian - Get how often the Jacobian is rebuilt. See `SNESGetLagPreconditioner()` to determine when the preconditioner is rebuilt 3749e35cf81dSBarry Smith 37503f9fe445SBarry Smith Not Collective 3751e35cf81dSBarry Smith 3752e35cf81dSBarry Smith Input Parameter: 3753f6dfbefdSBarry Smith . snes - the `SNES` context 3754e35cf81dSBarry Smith 3755e35cf81dSBarry Smith Output Parameter: 3756e35cf81dSBarry 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 3757e35cf81dSBarry Smith the Jacobian is built etc. 3758e35cf81dSBarry Smith 3759dc4c0fb0SBarry Smith Level: intermediate 3760dc4c0fb0SBarry Smith 3761e35cf81dSBarry Smith Notes: 3762e35cf81dSBarry Smith The default is 1 3763f6dfbefdSBarry Smith 3764f6dfbefdSBarry Smith The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagJacobianPersists()` was called. 3765e35cf81dSBarry Smith 37663201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobian()`, `SNESSetLagPreconditioner()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3767e35cf81dSBarry Smith 3768e35cf81dSBarry Smith @*/ 3769d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagJacobian(SNES snes, PetscInt *lag) 3770d71ae5a4SJacob Faibussowitsch { 3771e35cf81dSBarry Smith PetscFunctionBegin; 37720700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3773e35cf81dSBarry Smith *lag = snes->lagjacobian; 37743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3775e35cf81dSBarry Smith } 3776e35cf81dSBarry Smith 377737ec4e1aSPeter Brune /*@ 3778f6dfbefdSBarry Smith SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple nonlinear solves 377937ec4e1aSPeter Brune 3780c3339decSBarry Smith Logically collective 378137ec4e1aSPeter Brune 3782d8d19677SJose E. Roman Input Parameters: 3783f6dfbefdSBarry Smith + snes - the `SNES` context 37849d7e2deaSPeter Brune - flg - jacobian lagging persists if true 378537ec4e1aSPeter Brune 378637ec4e1aSPeter Brune Options Database Keys: 378779a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 37883d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 378979a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 37903d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 37913d5a8a6aSBarry Smith 3792dc4c0fb0SBarry Smith Level: advanced 3793dc4c0fb0SBarry Smith 379495452b02SPatrick Sanan Notes: 3795420bcc1bSBarry Smith Normally when `SNESSetLagJacobian()` is used, the Jacobian is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior 3796f6dfbefdSBarry Smith 379795452b02SPatrick Sanan This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by 379837ec4e1aSPeter Brune several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several 379937ec4e1aSPeter Brune timesteps may present huge efficiency gains. 380037ec4e1aSPeter Brune 380142747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditionerPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()` 380237ec4e1aSPeter Brune @*/ 3803d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobianPersists(SNES snes, PetscBool flg) 3804d71ae5a4SJacob Faibussowitsch { 380537ec4e1aSPeter Brune PetscFunctionBegin; 380637ec4e1aSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 380737ec4e1aSPeter Brune PetscValidLogicalCollectiveBool(snes, flg, 2); 380837ec4e1aSPeter Brune snes->lagjac_persist = flg; 38093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 381037ec4e1aSPeter Brune } 381137ec4e1aSPeter Brune 381237ec4e1aSPeter Brune /*@ 3813d8e291bfSBarry Smith SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple nonlinear solves 381437ec4e1aSPeter Brune 3815c3339decSBarry Smith Logically Collective 381637ec4e1aSPeter Brune 3817d8d19677SJose E. Roman Input Parameters: 3818f6dfbefdSBarry Smith + snes - the `SNES` context 38199d7e2deaSPeter Brune - flg - preconditioner lagging persists if true 382037ec4e1aSPeter Brune 382137ec4e1aSPeter Brune Options Database Keys: 382279a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 38233d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 382479a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 38253d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 382637ec4e1aSPeter Brune 3827dc4c0fb0SBarry Smith Level: developer 3828dc4c0fb0SBarry Smith 382995452b02SPatrick Sanan Notes: 3830420bcc1bSBarry Smith Normally when `SNESSetLagPreconditioner()` is used, the preconditioner is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior 3831f6dfbefdSBarry Smith 383295452b02SPatrick Sanan This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale 383337ec4e1aSPeter Brune by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over 383437ec4e1aSPeter Brune several timesteps may present huge efficiency gains. 383537ec4e1aSPeter Brune 38361cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobianPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagPreconditioner()` 383737ec4e1aSPeter Brune @*/ 3838d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes, PetscBool flg) 3839d71ae5a4SJacob Faibussowitsch { 384037ec4e1aSPeter Brune PetscFunctionBegin; 384137ec4e1aSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 384237ec4e1aSPeter Brune PetscValidLogicalCollectiveBool(snes, flg, 2); 384337ec4e1aSPeter Brune snes->lagpre_persist = flg; 38443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 384537ec4e1aSPeter Brune } 384637ec4e1aSPeter Brune 38479b94acceSBarry Smith /*@ 3848f6dfbefdSBarry Smith SNESSetForceIteration - force `SNESSolve()` to take at least one iteration regardless of the initial residual norm 3849be5caee7SBarry Smith 3850c3339decSBarry Smith Logically Collective 3851be5caee7SBarry Smith 3852be5caee7SBarry Smith Input Parameters: 3853f6dfbefdSBarry Smith + snes - the `SNES` context 3854f6dfbefdSBarry Smith - force - `PETSC_TRUE` require at least one iteration 3855be5caee7SBarry Smith 3856f6dfbefdSBarry Smith Options Database Key: 3857be5caee7SBarry Smith . -snes_force_iteration <force> - Sets forcing an iteration 3858be5caee7SBarry Smith 3859dc4c0fb0SBarry Smith Level: intermediate 3860dc4c0fb0SBarry Smith 3861f6dfbefdSBarry Smith Note: 3862f6dfbefdSBarry Smith This is used sometimes with `TS` to prevent `TS` from detecting a false steady state solution 3863be5caee7SBarry Smith 38643201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `TS`, `SNESSetDivergenceTolerance()` 3865be5caee7SBarry Smith @*/ 3866d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetForceIteration(SNES snes, PetscBool force) 3867d71ae5a4SJacob Faibussowitsch { 3868be5caee7SBarry Smith PetscFunctionBegin; 3869be5caee7SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3870be5caee7SBarry Smith snes->forceiteration = force; 38713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3872be5caee7SBarry Smith } 3873be5caee7SBarry Smith 387485216dc7SFande Kong /*@ 3875f6dfbefdSBarry Smith SNESGetForceIteration - Check whether or not `SNESSolve()` take at least one iteration regardless of the initial residual norm 387685216dc7SFande Kong 3877c3339decSBarry Smith Logically Collective 387885216dc7SFande Kong 38792fe279fdSBarry Smith Input Parameter: 3880f6dfbefdSBarry Smith . snes - the `SNES` context 388185216dc7SFande Kong 388285216dc7SFande Kong Output Parameter: 3883dc4c0fb0SBarry Smith . force - `PETSC_TRUE` requires at least one iteration. 388485216dc7SFande Kong 388506dd6b0eSSatish Balay Level: intermediate 388606dd6b0eSSatish Balay 38873201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetForceIteration()`, `SNESSetDivergenceTolerance()` 388885216dc7SFande Kong @*/ 3889d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetForceIteration(SNES snes, PetscBool *force) 3890d71ae5a4SJacob Faibussowitsch { 389185216dc7SFande Kong PetscFunctionBegin; 389285216dc7SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 389385216dc7SFande Kong *force = snes->forceiteration; 38943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 389585216dc7SFande Kong } 3896be5caee7SBarry Smith 3897be5caee7SBarry Smith /*@ 38980b4b7b1cSBarry Smith SNESSetTolerances - Sets various parameters used in `SNES` convergence tests. 38999b94acceSBarry Smith 3900c3339decSBarry Smith Logically Collective 3901c7afd0dbSLois Curfman McInnes 39029b94acceSBarry Smith Input Parameters: 3903f6dfbefdSBarry Smith + snes - the `SNES` context 39040b4b7b1cSBarry Smith . abstol - the absolute convergence tolerance, $ F(x^n) \le abstol $ 39050b4b7b1cSBarry Smith . rtol - the relative convergence tolerance, $ F(x^n) \le reltol * F(x^0) $ 39065358d0d4SBarry Smith . stol - convergence tolerance in terms of the norm of the change in the solution between steps, || delta x || < stol*|| x || 39070b4b7b1cSBarry Smith . maxit - the maximum number of iterations allowed in the solver, default 50. 39080b4b7b1cSBarry Smith - maxf - the maximum number of function evaluations allowed in the solver (use `PETSC_UNLIMITED` indicates no limit), default 10,000 3909fee21e36SBarry Smith 391033174efeSLois Curfman McInnes Options Database Keys: 391177e5a1f9SBarry Smith + -snes_atol <abstol> - Sets `abstol` 391277e5a1f9SBarry Smith . -snes_rtol <rtol> - Sets `rtol` 391377e5a1f9SBarry Smith . -snes_stol <stol> - Sets `stol` 391477e5a1f9SBarry Smith . -snes_max_it <maxit> - Sets `maxit` 391577e5a1f9SBarry Smith - -snes_max_funcs <maxf> - Sets `maxf` (use `unlimited` to have no maximum) 39169b94acceSBarry Smith 391736851e7fSLois Curfman McInnes Level: intermediate 391836851e7fSLois Curfman McInnes 391977e5a1f9SBarry Smith Note: 392077e5a1f9SBarry Smith All parameters must be non-negative 392177e5a1f9SBarry Smith 392277e5a1f9SBarry Smith Use `PETSC_CURRENT` to retain the current value of any parameter and `PETSC_DETERMINE` to use the default value for the given `SNES`. 392377e5a1f9SBarry Smith The default value is the value in the object when its type is set. 392477e5a1f9SBarry Smith 392577e5a1f9SBarry Smith Use `PETSC_UNLIMITED` on `maxit` or `maxf` to indicate there is no bound on the number of iterations or number of function evaluations. 392677e5a1f9SBarry Smith 392777e5a1f9SBarry Smith Fortran Note: 392877e5a1f9SBarry Smith Use `PETSC_CURRENT_INTEGER`, `PETSC_CURRENT_REAL`, `PETSC_UNLIMITED_INTEGER`, `PETSC_DETERMINE_INTEGER`, or `PETSC_DETERMINE_REAL` 392977e5a1f9SBarry Smith 39303201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESSolve()`, `SNES`, `SNESSetDivergenceTolerance()`, `SNESSetForceIteration()` 39319b94acceSBarry Smith @*/ 3932d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTolerances(SNES snes, PetscReal abstol, PetscReal rtol, PetscReal stol, PetscInt maxit, PetscInt maxf) 3933d71ae5a4SJacob Faibussowitsch { 39343a40ed3dSBarry Smith PetscFunctionBegin; 39350700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3936c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, abstol, 2); 3937c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, rtol, 3); 3938c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, stol, 4); 3939c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, maxit, 5); 3940c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, maxf, 6); 3941c5eb9154SBarry Smith 394277e5a1f9SBarry Smith if (abstol == (PetscReal)PETSC_DETERMINE) { 394377e5a1f9SBarry Smith snes->abstol = snes->default_abstol; 394477e5a1f9SBarry Smith } else if (abstol != (PetscReal)PETSC_CURRENT) { 39455f80ce2aSJacob Faibussowitsch PetscCheck(abstol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)abstol); 3946ab54825eSJed Brown snes->abstol = abstol; 3947ab54825eSJed Brown } 394877e5a1f9SBarry Smith 394977e5a1f9SBarry Smith if (rtol == (PetscReal)PETSC_DETERMINE) { 395077e5a1f9SBarry Smith snes->rtol = snes->default_rtol; 395177e5a1f9SBarry Smith } else if (rtol != (PetscReal)PETSC_CURRENT) { 39525f80ce2aSJacob 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); 3953ab54825eSJed Brown snes->rtol = rtol; 3954ab54825eSJed Brown } 395577e5a1f9SBarry Smith 395677e5a1f9SBarry Smith if (stol == (PetscReal)PETSC_DETERMINE) { 395777e5a1f9SBarry Smith snes->stol = snes->default_stol; 395877e5a1f9SBarry Smith } else if (stol != (PetscReal)PETSC_CURRENT) { 39595f80ce2aSJacob Faibussowitsch PetscCheck(stol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Step tolerance %g must be non-negative", (double)stol); 3960c60f73f4SPeter Brune snes->stol = stol; 3961ab54825eSJed Brown } 396277e5a1f9SBarry Smith 3963835f2295SStefano Zampini if (maxit == PETSC_DETERMINE) { 396477e5a1f9SBarry Smith snes->max_its = snes->default_max_its; 3965835f2295SStefano Zampini } else if (maxit == PETSC_UNLIMITED) { 396677e5a1f9SBarry Smith snes->max_its = PETSC_INT_MAX; 396777e5a1f9SBarry Smith } else if (maxit != PETSC_CURRENT) { 396863a3b9bcSJacob Faibussowitsch PetscCheck(maxit >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", maxit); 3969ab54825eSJed Brown snes->max_its = maxit; 3970ab54825eSJed Brown } 397177e5a1f9SBarry Smith 3972835f2295SStefano Zampini if (maxf == PETSC_DETERMINE) { 397377e5a1f9SBarry Smith snes->max_funcs = snes->default_max_funcs; 3974835f2295SStefano Zampini } else if (maxf == PETSC_UNLIMITED || maxf == -1) { 397577e5a1f9SBarry Smith snes->max_funcs = PETSC_UNLIMITED; 397677e5a1f9SBarry Smith } else if (maxf != PETSC_CURRENT) { 397777e5a1f9SBarry Smith PetscCheck(maxf >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations %" PetscInt_FMT " must be nonnegative", maxf); 3978ab54825eSJed Brown snes->max_funcs = maxf; 3979ab54825eSJed Brown } 39803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 39819b94acceSBarry Smith } 39829b94acceSBarry Smith 3983e4d06f11SPatrick Farrell /*@ 3984f6dfbefdSBarry Smith SNESSetDivergenceTolerance - Sets the divergence tolerance used for the `SNES` divergence test. 3985e4d06f11SPatrick Farrell 3986c3339decSBarry Smith Logically Collective 3987e4d06f11SPatrick Farrell 3988e4d06f11SPatrick Farrell Input Parameters: 3989f6dfbefdSBarry Smith + snes - the `SNES` context 39900b4b7b1cSBarry 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 39910b4b7b1cSBarry Smith is stopped due to divergence. 3992e4d06f11SPatrick Farrell 3993f6dfbefdSBarry Smith Options Database Key: 3994dc4c0fb0SBarry Smith . -snes_divergence_tolerance <divtol> - Sets `divtol` 3995e4d06f11SPatrick Farrell 3996e4d06f11SPatrick Farrell Level: intermediate 3997e4d06f11SPatrick Farrell 399877e5a1f9SBarry Smith Notes: 399977e5a1f9SBarry Smith Use `PETSC_DETERMINE` to use the default value from when the object's type was set. 4000e5cd489fSStefano Zampini 400177e5a1f9SBarry Smith Fortran Note: 400277e5a1f9SBarry Smith Use ``PETSC_DETERMINE_REAL` or `PETSC_UNLIMITED_REAL` 400377e5a1f9SBarry Smith 400477e5a1f9SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetTolerances()`, `SNESGetDivergenceTolerance()` 4005e4d06f11SPatrick Farrell @*/ 4006d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDivergenceTolerance(SNES snes, PetscReal divtol) 4007d71ae5a4SJacob Faibussowitsch { 4008e4d06f11SPatrick Farrell PetscFunctionBegin; 4009e4d06f11SPatrick Farrell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4010e4d06f11SPatrick Farrell PetscValidLogicalCollectiveReal(snes, divtol, 2); 401177e5a1f9SBarry Smith 401277e5a1f9SBarry Smith if (divtol == (PetscReal)PETSC_DETERMINE) { 401377e5a1f9SBarry Smith snes->divtol = snes->default_divtol; 401477e5a1f9SBarry Smith } else if (divtol == (PetscReal)PETSC_UNLIMITED || divtol == -1) { 401577e5a1f9SBarry Smith snes->divtol = PETSC_UNLIMITED; 401677e5a1f9SBarry Smith } else if (divtol != (PetscReal)PETSC_CURRENT) { 401777e5a1f9SBarry Smith PetscCheck(divtol >= 1.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Divergence tolerance %g must be greater than 1.0", (double)divtol); 401877e5a1f9SBarry Smith snes->divtol = divtol; 401977e5a1f9SBarry Smith } 40203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4021e4d06f11SPatrick Farrell } 4022e4d06f11SPatrick Farrell 40239b94acceSBarry Smith /*@ 40240b4b7b1cSBarry Smith SNESGetTolerances - Gets various parameters used in `SNES` convergence tests. 402533174efeSLois Curfman McInnes 4026c7afd0dbSLois Curfman McInnes Not Collective 4027c7afd0dbSLois Curfman McInnes 402877e5a1f9SBarry Smith Input Parameter: 402977e5a1f9SBarry Smith . snes - the `SNES` context 403077e5a1f9SBarry Smith 403177e5a1f9SBarry Smith Output Parameters: 40320b4b7b1cSBarry Smith + atol - the absolute convergence tolerance 40330b4b7b1cSBarry Smith . rtol - the relative convergence tolerance 403477e5a1f9SBarry Smith . stol - convergence tolerance in terms of the norm of the change in the solution between steps 40350b4b7b1cSBarry Smith . maxit - the maximum number of iterations allowed 40360b4b7b1cSBarry Smith - maxf - the maximum number of function evaluations allowed, `PETSC_UNLIMITED` indicates no bound 4037fee21e36SBarry Smith 403836851e7fSLois Curfman McInnes Level: intermediate 403936851e7fSLois Curfman McInnes 40400b4b7b1cSBarry Smith Notes: 40410b4b7b1cSBarry Smith See `SNESSetTolerances()` for details on the parameters. 40420b4b7b1cSBarry Smith 4043dc4c0fb0SBarry Smith The user can specify `NULL` for any parameter that is not needed. 4044dc4c0fb0SBarry Smith 40451cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTolerances()` 404633174efeSLois Curfman McInnes @*/ 4047d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetTolerances(SNES snes, PetscReal *atol, PetscReal *rtol, PetscReal *stol, PetscInt *maxit, PetscInt *maxf) 4048d71ae5a4SJacob Faibussowitsch { 40493a40ed3dSBarry Smith PetscFunctionBegin; 40500700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 405185385478SLisandro Dalcin if (atol) *atol = snes->abstol; 405233174efeSLois Curfman McInnes if (rtol) *rtol = snes->rtol; 4053c60f73f4SPeter Brune if (stol) *stol = snes->stol; 405433174efeSLois Curfman McInnes if (maxit) *maxit = snes->max_its; 405533174efeSLois Curfman McInnes if (maxf) *maxf = snes->max_funcs; 40563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 405733174efeSLois Curfman McInnes } 405833174efeSLois Curfman McInnes 4059e4d06f11SPatrick Farrell /*@ 4060e4d06f11SPatrick Farrell SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test. 4061e4d06f11SPatrick Farrell 4062e4d06f11SPatrick Farrell Not Collective 4063e4d06f11SPatrick Farrell 4064e4d06f11SPatrick Farrell Input Parameters: 4065f6dfbefdSBarry Smith + snes - the `SNES` context 4066e4d06f11SPatrick Farrell - divtol - divergence tolerance 4067e4d06f11SPatrick Farrell 4068e4d06f11SPatrick Farrell Level: intermediate 4069e4d06f11SPatrick Farrell 40701cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetDivergenceTolerance()` 4071e4d06f11SPatrick Farrell @*/ 4072d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDivergenceTolerance(SNES snes, PetscReal *divtol) 4073d71ae5a4SJacob Faibussowitsch { 4074e4d06f11SPatrick Farrell PetscFunctionBegin; 4075e4d06f11SPatrick Farrell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4076e4d06f11SPatrick Farrell if (divtol) *divtol = snes->divtol; 40773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4078e4d06f11SPatrick Farrell } 4079e4d06f11SPatrick Farrell 40806ba87a44SLisandro Dalcin PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *); 40816ba87a44SLisandro Dalcin 4082d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorLGRange(SNES snes, PetscInt n, PetscReal rnorm, void *monctx) 4083d71ae5a4SJacob Faibussowitsch { 4084b271bb04SBarry Smith PetscDrawLG lg; 4085b271bb04SBarry Smith PetscReal x, y, per; 4086b271bb04SBarry Smith PetscViewer v = (PetscViewer)monctx; 4087b271bb04SBarry Smith static PetscReal prev; /* should be in the context */ 4088b271bb04SBarry Smith PetscDraw draw; 4089b271bb04SBarry Smith 4090459f5d12SBarry Smith PetscFunctionBegin; 40914d4332d5SBarry Smith PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 4); 40929566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 0, &lg)); 40939566063dSJacob Faibussowitsch if (!n) PetscCall(PetscDrawLGReset(lg)); 40949566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 40959566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "Residual norm")); 4096b271bb04SBarry Smith x = (PetscReal)n; 409777b4d14cSPeter Brune if (rnorm > 0.0) y = PetscLog10Real(rnorm); 409894c9c6d3SKarl Rupp else y = -15.0; 40999566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 41006934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 41019566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 41029566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 4103b271bb04SBarry Smith } 4104b271bb04SBarry Smith 41059566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 1, &lg)); 41069566063dSJacob Faibussowitsch if (!n) PetscCall(PetscDrawLGReset(lg)); 41079566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 4108aaa8cc7dSPierre Jolivet PetscCall(PetscDrawSetTitle(draw, "% elements > .2*max element")); 41099566063dSJacob Faibussowitsch PetscCall(SNESMonitorRange_Private(snes, n, &per)); 4110b271bb04SBarry Smith x = (PetscReal)n; 4111b271bb04SBarry Smith y = 100.0 * per; 41129566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 41136934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 41149566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 41159566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 4116b271bb04SBarry Smith } 4117b271bb04SBarry Smith 41189566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 2, &lg)); 41199371c9d4SSatish Balay if (!n) { 41209371c9d4SSatish Balay prev = rnorm; 41219371c9d4SSatish Balay PetscCall(PetscDrawLGReset(lg)); 41229371c9d4SSatish Balay } 41239566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 41249566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm")); 4125b271bb04SBarry Smith x = (PetscReal)n; 4126b271bb04SBarry Smith y = (prev - rnorm) / prev; 41279566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 41286934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 41299566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 41309566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 4131b271bb04SBarry Smith } 4132b271bb04SBarry Smith 41339566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 3, &lg)); 41349566063dSJacob Faibussowitsch if (!n) PetscCall(PetscDrawLGReset(lg)); 41359566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 41369566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm*(% > .2 max)")); 4137b271bb04SBarry Smith x = (PetscReal)n; 4138b271bb04SBarry Smith y = (prev - rnorm) / (prev * per); 4139b271bb04SBarry Smith if (n > 2) { /*skip initial crazy value */ 41409566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 4141b271bb04SBarry Smith } 41426934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 41439566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 41449566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 4145b271bb04SBarry Smith } 4146b271bb04SBarry Smith prev = rnorm; 41473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4148b271bb04SBarry Smith } 4149b271bb04SBarry Smith 4150228d79bcSJed Brown /*@ 41512d157150SStefano Zampini SNESConverged - Run the convergence test and update the `SNESConvergedReason`. 41522d157150SStefano Zampini 41532d157150SStefano Zampini Collective 41542d157150SStefano Zampini 41552d157150SStefano Zampini Input Parameters: 41562d157150SStefano Zampini + snes - the `SNES` context 41572d157150SStefano Zampini . it - current iteration 41582d157150SStefano Zampini . xnorm - 2-norm of current iterate 41592d157150SStefano Zampini . snorm - 2-norm of current step 41602d157150SStefano Zampini - fnorm - 2-norm of function 41612d157150SStefano Zampini 41622d157150SStefano Zampini Level: developer 41632d157150SStefano Zampini 41642d157150SStefano Zampini Note: 4165420bcc1bSBarry Smith This routine is called by the `SNESSolve()` implementations. 41662d157150SStefano Zampini It does not typically need to be called by the user. 41672d157150SStefano Zampini 4168c948abdaSPierre Jolivet .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()` 41692d157150SStefano Zampini @*/ 41702d157150SStefano Zampini PetscErrorCode SNESConverged(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm) 41712d157150SStefano Zampini { 41722d157150SStefano Zampini PetscFunctionBegin; 41732d157150SStefano Zampini if (!snes->reason) { 41742d157150SStefano Zampini if (snes->normschedule == SNES_NORM_ALWAYS) PetscUseTypeMethod(snes, converged, it, xnorm, snorm, fnorm, &snes->reason, snes->cnvP); 41752d157150SStefano Zampini if (it == snes->max_its && !snes->reason) { 41762d157150SStefano Zampini if (snes->normschedule == SNES_NORM_ALWAYS) { 41772d157150SStefano Zampini PetscCall(PetscInfo(snes, "Maximum number of iterations has been reached: %" PetscInt_FMT "\n", snes->max_its)); 41782d157150SStefano Zampini snes->reason = SNES_DIVERGED_MAX_IT; 41792d157150SStefano Zampini } else snes->reason = SNES_CONVERGED_ITS; 41802d157150SStefano Zampini } 41812d157150SStefano Zampini } 41822d157150SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 41832d157150SStefano Zampini } 41842d157150SStefano Zampini 41852d157150SStefano Zampini /*@ 41860b4b7b1cSBarry Smith SNESMonitor - runs any `SNES` monitor routines provided with `SNESMonitor()` or the options database 4187228d79bcSJed Brown 4188c3339decSBarry Smith Collective 4189228d79bcSJed Brown 4190228d79bcSJed Brown Input Parameters: 4191f6dfbefdSBarry Smith + snes - nonlinear solver context obtained from `SNESCreate()` 41920b4b7b1cSBarry Smith . iter - current iteration number 41930b4b7b1cSBarry Smith - rnorm - current relative norm of the residual 4194228d79bcSJed Brown 4195dc4c0fb0SBarry Smith Level: developer 4196dc4c0fb0SBarry Smith 4197f6dfbefdSBarry Smith Note: 4198420bcc1bSBarry Smith This routine is called by the `SNESSolve()` implementations. 4199228d79bcSJed Brown It does not typically need to be called by the user. 4200228d79bcSJed Brown 42011cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorSet()` 4202228d79bcSJed Brown @*/ 4203d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitor(SNES snes, PetscInt iter, PetscReal rnorm) 4204d71ae5a4SJacob Faibussowitsch { 42057a03ce2fSLisandro Dalcin PetscInt i, n = snes->numbermonitors; 42067a03ce2fSLisandro Dalcin 42077a03ce2fSLisandro Dalcin PetscFunctionBegin; 42089566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(snes->vec_sol)); 420948a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall((*snes->monitor[i])(snes, iter, rnorm, snes->monitorcontext[i])); 42109566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(snes->vec_sol)); 42113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 42127a03ce2fSLisandro Dalcin } 42137a03ce2fSLisandro Dalcin 42149b94acceSBarry Smith /* ------------ Routines to set performance monitoring options ----------- */ 42159b94acceSBarry Smith 4216bf388a1fSBarry Smith /*MC 4217f6dfbefdSBarry Smith SNESMonitorFunction - functional form passed to `SNESMonitorSet()` to monitor convergence of nonlinear solver 4218bf388a1fSBarry Smith 4219bf388a1fSBarry Smith Synopsis: 4220aaa7dc30SBarry Smith #include <petscsnes.h> 422137fdd005SBarry Smith PetscErrorCode SNESMonitorFunction(SNES snes, PetscInt its, PetscReal norm, void *mctx) 4222bf388a1fSBarry Smith 4223c3339decSBarry Smith Collective 42241843f636SBarry Smith 42251843f636SBarry Smith Input Parameters: 4226f6dfbefdSBarry Smith + snes - the `SNES` context 4227bf388a1fSBarry Smith . its - iteration number 4228bf388a1fSBarry Smith . norm - 2-norm function value (may be estimated) 4229bf388a1fSBarry Smith - mctx - [optional] monitoring context 4230bf388a1fSBarry Smith 4231878cb397SSatish Balay Level: advanced 4232878cb397SSatish Balay 423356296ac4SStefano Zampini .seealso: [](ch_snes), `SNESMonitorSet()` 4234bf388a1fSBarry Smith M*/ 4235bf388a1fSBarry Smith 42369b94acceSBarry Smith /*@C 4237a6570f20SBarry Smith SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every 42380b4b7b1cSBarry Smith iteration of the `SNES` nonlinear solver to display the iteration's 42399b94acceSBarry Smith progress. 42409b94acceSBarry Smith 4241c3339decSBarry Smith Logically Collective 4242fee21e36SBarry Smith 4243c7afd0dbSLois Curfman McInnes Input Parameters: 4244f6dfbefdSBarry Smith + snes - the `SNES` context 424520f4b53cSBarry Smith . f - the monitor function, for the calling sequence see `SNESMonitorFunction` 4246420bcc1bSBarry Smith . mctx - [optional] user-defined context for private data for the monitor routine (use `NULL` if no context is desired) 424749abdd8aSBarry Smith - monitordestroy - [optional] routine that frees monitor context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence 42489b94acceSBarry Smith 42499665c990SLois Curfman McInnes Options Database Keys: 4250f6dfbefdSBarry Smith + -snes_monitor - sets `SNESMonitorDefault()` 4251798534f6SMatthew G. Knepley . -snes_monitor draw::draw_lg - sets line graph monitor, 4252dc4c0fb0SBarry 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 4253c7afd0dbSLois Curfman McInnes the options database. 42549665c990SLois Curfman McInnes 4255dc4c0fb0SBarry Smith Level: intermediate 4256dc4c0fb0SBarry Smith 4257f6dfbefdSBarry Smith Note: 42586bc08f3fSLois Curfman McInnes Several different monitoring routines may be set by calling 4259f6dfbefdSBarry Smith `SNESMonitorSet()` multiple times; all will be called in the 42606bc08f3fSLois Curfman McInnes order in which they were set. 4261639f9d9dSBarry Smith 4262420bcc1bSBarry Smith Fortran Note: 4263f6dfbefdSBarry Smith Only a single monitor function can be set for each `SNES` object 4264025f1a04SBarry Smith 426549abdd8aSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESMonitorDefault()`, `SNESMonitorCancel()`, `SNESMonitorFunction`, `PetscCtxDestroyFn` 42669b94acceSBarry Smith @*/ 426749abdd8aSBarry Smith PetscErrorCode SNESMonitorSet(SNES snes, PetscErrorCode (*f)(SNES, PetscInt, PetscReal, void *), void *mctx, PetscCtxDestroyFn *monitordestroy) 4268d71ae5a4SJacob Faibussowitsch { 42693a40ed3dSBarry Smith PetscFunctionBegin; 42700700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4271453a69bbSBarry Smith for (PetscInt i = 0; i < snes->numbermonitors; i++) { 4272453a69bbSBarry Smith PetscBool identical; 4273453a69bbSBarry Smith 4274453a69bbSBarry Smith PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))(PetscVoidFn *)f, mctx, monitordestroy, (PetscErrorCode (*)(void))(PetscVoidFn *)snes->monitor[i], snes->monitorcontext[i], snes->monitordestroy[i], &identical)); 42753ba16761SJacob Faibussowitsch if (identical) PetscFunctionReturn(PETSC_SUCCESS); 4276649052a6SBarry Smith } 42775f80ce2aSJacob Faibussowitsch PetscCheck(snes->numbermonitors < MAXSNESMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set"); 42786e4dcb14SBarry Smith snes->monitor[snes->numbermonitors] = f; 4279b8a78c4aSBarry Smith snes->monitordestroy[snes->numbermonitors] = monitordestroy; 4280835f2295SStefano Zampini snes->monitorcontext[snes->numbermonitors++] = mctx; 42813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 42829b94acceSBarry Smith } 42839b94acceSBarry Smith 4284a278d85bSSatish Balay /*@ 4285f6dfbefdSBarry Smith SNESMonitorCancel - Clears all the monitor functions for a `SNES` object. 42865cd90555SBarry Smith 4287c3339decSBarry Smith Logically Collective 4288c7afd0dbSLois Curfman McInnes 42892fe279fdSBarry Smith Input Parameter: 4290f6dfbefdSBarry Smith . snes - the `SNES` context 42915cd90555SBarry Smith 42921a480d89SAdministrator Options Database Key: 4293a6570f20SBarry Smith . -snes_monitor_cancel - cancels all monitors that have been hardwired 4294dc4c0fb0SBarry Smith into a code by calls to `SNESMonitorSet()`, but does not cancel those 4295c7afd0dbSLois Curfman McInnes set via the options database 42965cd90555SBarry Smith 4297dc4c0fb0SBarry Smith Level: intermediate 4298dc4c0fb0SBarry Smith 4299f6dfbefdSBarry Smith Note: 4300f6dfbefdSBarry Smith There is no way to clear one specific monitor from a `SNES` object. 43015cd90555SBarry Smith 430256296ac4SStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESMonitorDefault()`, `SNESMonitorSet()` 43035cd90555SBarry Smith @*/ 4304d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorCancel(SNES snes) 4305d71ae5a4SJacob Faibussowitsch { 4306d952e501SBarry Smith PetscInt i; 4307d952e501SBarry Smith 43085cd90555SBarry Smith PetscFunctionBegin; 43090700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4310d952e501SBarry Smith for (i = 0; i < snes->numbermonitors; i++) { 431148a46eb9SPierre Jolivet if (snes->monitordestroy[i]) PetscCall((*snes->monitordestroy[i])(&snes->monitorcontext[i])); 4312d952e501SBarry Smith } 43135cd90555SBarry Smith snes->numbermonitors = 0; 43143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 43155cd90555SBarry Smith } 43165cd90555SBarry Smith 4317bf388a1fSBarry Smith /*MC 4318bf388a1fSBarry Smith SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver 4319bf388a1fSBarry Smith 4320bf388a1fSBarry Smith Synopsis: 4321aaa7dc30SBarry Smith #include <petscsnes.h> 432237fdd005SBarry Smith PetscErrorCode SNESConvergenceTest(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *cctx) 4323bf388a1fSBarry Smith 4324c3339decSBarry Smith Collective 43251843f636SBarry Smith 43261843f636SBarry Smith Input Parameters: 4327f6dfbefdSBarry Smith + snes - the `SNES` context 4328bf388a1fSBarry Smith . it - current iteration (0 is the first and is before any Newton step) 4329bf388a1fSBarry Smith . xnorm - 2-norm of current iterate 4330bf388a1fSBarry Smith . gnorm - 2-norm of current step 43311843f636SBarry Smith . f - 2-norm of function 43321843f636SBarry Smith - cctx - [optional] convergence context 43331843f636SBarry Smith 43341843f636SBarry Smith Output Parameter: 43351843f636SBarry Smith . reason - reason for convergence/divergence, only needs to be set when convergence or divergence is detected 4336bf388a1fSBarry Smith 4337878cb397SSatish Balay Level: intermediate 4338bf388a1fSBarry Smith 4339c948abdaSPierre Jolivet .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()` 4340bf388a1fSBarry Smith M*/ 4341bf388a1fSBarry Smith 43429b94acceSBarry Smith /*@C 43439b94acceSBarry Smith SNESSetConvergenceTest - Sets the function that is to be used 43449b94acceSBarry Smith to test for convergence of the nonlinear iterative solution. 43459b94acceSBarry Smith 4346c3339decSBarry Smith Logically Collective 4347fee21e36SBarry Smith 4348c7afd0dbSLois Curfman McInnes Input Parameters: 4349f6dfbefdSBarry Smith + snes - the `SNES` context 4350e4094ef1SJacob Faibussowitsch . SNESConvergenceTestFunction - routine to test for convergence 4351dc4c0fb0SBarry Smith . cctx - [optional] context for private data for the convergence routine (may be `NULL`) 4352dc4c0fb0SBarry Smith - destroy - [optional] destructor for the context (may be `NULL`; `PETSC_NULL_FUNCTION` in Fortran) 43539b94acceSBarry Smith 435436851e7fSLois Curfman McInnes Level: advanced 435536851e7fSLois Curfman McInnes 43561cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedDefault()`, `SNESConvergedSkip()`, `SNESConvergenceTestFunction` 43579b94acceSBarry Smith @*/ 4358*12651944SBarry Smith PetscErrorCode SNESSetConvergenceTest(SNES snes, PetscErrorCode (*SNESConvergenceTestFunction)(SNES, PetscInt, PetscReal, PetscReal, PetscReal, SNESConvergedReason *, void *), void *cctx, PetscCtxDestroyFn *destroy) 4359d71ae5a4SJacob Faibussowitsch { 43603a40ed3dSBarry Smith PetscFunctionBegin; 43610700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4362e2a6519dSDmitry Karpeev if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip; 4363*12651944SBarry Smith if (snes->ops->convergeddestroy) PetscCall((*snes->ops->convergeddestroy)(&snes->cnvP)); 4364bf388a1fSBarry Smith snes->ops->converged = SNESConvergenceTestFunction; 43657f7931b9SBarry Smith snes->ops->convergeddestroy = destroy; 436685385478SLisandro Dalcin snes->cnvP = cctx; 43673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 43689b94acceSBarry Smith } 43699b94acceSBarry Smith 437052baeb72SSatish Balay /*@ 43710b4b7b1cSBarry Smith SNESGetConvergedReason - Gets the reason the `SNES` iteration was stopped, which may be due to convergence, divergence, or stagnation 4372184914b5SBarry Smith 4373184914b5SBarry Smith Not Collective 4374184914b5SBarry Smith 4375184914b5SBarry Smith Input Parameter: 4376f6dfbefdSBarry Smith . snes - the `SNES` context 4377184914b5SBarry Smith 4378184914b5SBarry Smith Output Parameter: 4379f6dfbefdSBarry Smith . reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` for the individual convergence tests for complete lists 4380184914b5SBarry Smith 4381f6dfbefdSBarry Smith Options Database Key: 43826a4d7782SBarry Smith . -snes_converged_reason - prints the reason to standard out 43836a4d7782SBarry Smith 4384184914b5SBarry Smith Level: intermediate 4385184914b5SBarry Smith 4386f6dfbefdSBarry Smith Note: 4387f6dfbefdSBarry Smith Should only be called after the call the `SNESSolve()` is complete, if it is called earlier it returns the value `SNES__CONVERGED_ITERATING`. 4388184914b5SBarry Smith 43891cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESSetConvergedReason()`, `SNESConvergedReason`, `SNESGetConvergedReasonString()` 4390184914b5SBarry Smith @*/ 4391d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReason(SNES snes, SNESConvergedReason *reason) 4392d71ae5a4SJacob Faibussowitsch { 4393184914b5SBarry Smith PetscFunctionBegin; 43940700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 43954f572ea9SToby Isaac PetscAssertPointer(reason, 2); 4396184914b5SBarry Smith *reason = snes->reason; 43973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4398184914b5SBarry Smith } 4399184914b5SBarry Smith 4400c4421ceaSFande Kong /*@C 4401f6dfbefdSBarry Smith SNESGetConvergedReasonString - Return a human readable string for `SNESConvergedReason` 4402c4421ceaSFande Kong 4403c4421ceaSFande Kong Not Collective 4404c4421ceaSFande Kong 4405c4421ceaSFande Kong Input Parameter: 4406f6dfbefdSBarry Smith . snes - the `SNES` context 4407c4421ceaSFande Kong 4408c4421ceaSFande Kong Output Parameter: 4409dc4c0fb0SBarry Smith . strreason - a human readable string that describes `SNES` converged reason 4410c4421ceaSFande Kong 441199c90e12SSatish Balay Level: beginner 4412c4421ceaSFande Kong 44131cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetConvergedReason()` 4414c4421ceaSFande Kong @*/ 4415d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReasonString(SNES snes, const char **strreason) 4416d71ae5a4SJacob Faibussowitsch { 4417c4421ceaSFande Kong PetscFunctionBegin; 4418c4421ceaSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 44194f572ea9SToby Isaac PetscAssertPointer(strreason, 2); 4420c4421ceaSFande Kong *strreason = SNESConvergedReasons[snes->reason]; 44213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4422c4421ceaSFande Kong } 4423c4421ceaSFande Kong 442433866048SMatthew G. Knepley /*@ 4425f6dfbefdSBarry Smith SNESSetConvergedReason - Sets the reason the `SNES` iteration was stopped. 442633866048SMatthew G. Knepley 442733866048SMatthew G. Knepley Not Collective 442833866048SMatthew G. Knepley 442933866048SMatthew G. Knepley Input Parameters: 4430f6dfbefdSBarry Smith + snes - the `SNES` context 4431f6dfbefdSBarry Smith - reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` or the 443233866048SMatthew G. Knepley manual pages for the individual convergence tests for complete lists 443333866048SMatthew G. Knepley 4434f6dfbefdSBarry Smith Level: developer 4435f6dfbefdSBarry Smith 4436420bcc1bSBarry Smith Developer Note: 4437f6dfbefdSBarry Smith Called inside the various `SNESSolve()` implementations 443833866048SMatthew G. Knepley 44391cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetConvergedReason()`, `SNESSetConvergenceTest()`, `SNESConvergedReason` 444033866048SMatthew G. Knepley @*/ 4441d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergedReason(SNES snes, SNESConvergedReason reason) 4442d71ae5a4SJacob Faibussowitsch { 444333866048SMatthew G. Knepley PetscFunctionBegin; 444433866048SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 44455f3c5e7aSBarry Smith PetscCheck(!snes->errorifnotconverged || reason > 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "SNES code should have previously errored due to negative reason"); 444633866048SMatthew G. Knepley snes->reason = reason; 44473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 444833866048SMatthew G. Knepley } 444933866048SMatthew G. Knepley 4450c9005455SLois Curfman McInnes /*@ 4451420bcc1bSBarry Smith SNESSetConvergenceHistory - Sets the arrays used to hold the convergence history. 4452c9005455SLois Curfman McInnes 4453c3339decSBarry Smith Logically Collective 4454fee21e36SBarry Smith 4455c7afd0dbSLois Curfman McInnes Input Parameters: 4456f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 44578c7482ecSBarry Smith . a - array to hold history, this array will contain the function norms computed at each step 4458cd5578b5SBarry Smith . its - integer array holds the number of linear iterations for each solve. 4459420bcc1bSBarry Smith . na - size of `a` and `its` 4460f6dfbefdSBarry Smith - reset - `PETSC_TRUE` indicates each new nonlinear solve resets the history counter to zero, 4461758f92a0SBarry Smith else it continues storing new values for new nonlinear solves after the old ones 4462c7afd0dbSLois Curfman McInnes 4463dc4c0fb0SBarry Smith Level: intermediate 4464dc4c0fb0SBarry Smith 4465308dcc3eSBarry Smith Notes: 4466ce78bad3SBarry 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 446777e5a1f9SBarry Smith default array of length 1,000 is allocated. 4468308dcc3eSBarry Smith 4469c9005455SLois Curfman McInnes This routine is useful, e.g., when running a code for purposes 4470c9005455SLois Curfman McInnes of accurate performance monitoring, when no I/O should be done 4471c9005455SLois Curfman McInnes during the section of code that is being timed. 4472c9005455SLois Curfman McInnes 4473420bcc1bSBarry Smith If the arrays run out of space after a number of iterations then the later values are not saved in the history 4474420bcc1bSBarry Smith 44751cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetConvergenceHistory()` 4476c9005455SLois Curfman McInnes @*/ 4477d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceHistory(SNES snes, PetscReal a[], PetscInt its[], PetscInt na, PetscBool reset) 4478d71ae5a4SJacob Faibussowitsch { 44793a40ed3dSBarry Smith PetscFunctionBegin; 44800700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 44814f572ea9SToby Isaac if (a) PetscAssertPointer(a, 2); 44824f572ea9SToby Isaac if (its) PetscAssertPointer(its, 3); 44837a1ec6d4SBarry Smith if (!a) { 448477e5a1f9SBarry Smith if (na == PETSC_DECIDE) na = 1000; 44859566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(na, &a, na, &its)); 4486071fcb05SBarry Smith snes->conv_hist_alloc = PETSC_TRUE; 4487308dcc3eSBarry Smith } 4488c9005455SLois Curfman McInnes snes->conv_hist = a; 4489758f92a0SBarry Smith snes->conv_hist_its = its; 4490115dd874SBarry Smith snes->conv_hist_max = (size_t)na; 4491a12bc48fSLisandro Dalcin snes->conv_hist_len = 0; 4492758f92a0SBarry Smith snes->conv_hist_reset = reset; 44933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4494758f92a0SBarry Smith } 4495758f92a0SBarry Smith 4496d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB) 4497c6db04a5SJed Brown #include <engine.h> /* MATLAB include file */ 4498c6db04a5SJed Brown #include <mex.h> /* MATLAB include file */ 449999e0435eSBarry Smith 4500d71ae5a4SJacob Faibussowitsch PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes) 4501d71ae5a4SJacob Faibussowitsch { 4502308dcc3eSBarry Smith mxArray *mat; 4503308dcc3eSBarry Smith PetscInt i; 4504308dcc3eSBarry Smith PetscReal *ar; 4505308dcc3eSBarry Smith 4506308dcc3eSBarry Smith mat = mxCreateDoubleMatrix(snes->conv_hist_len, 1, mxREAL); 4507308dcc3eSBarry Smith ar = (PetscReal *)mxGetData(mat); 4508f5af7f23SKarl Rupp for (i = 0; i < snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i]; 450911cc89d2SBarry Smith return mat; 4510308dcc3eSBarry Smith } 4511308dcc3eSBarry Smith #endif 4512308dcc3eSBarry Smith 45130c4c9dddSBarry Smith /*@C 4514420bcc1bSBarry Smith SNESGetConvergenceHistory - Gets the arrays used to hold the convergence history. 4515758f92a0SBarry Smith 45163f9fe445SBarry Smith Not Collective 4517758f92a0SBarry Smith 4518758f92a0SBarry Smith Input Parameter: 4519f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 4520758f92a0SBarry Smith 4521758f92a0SBarry Smith Output Parameters: 4522f6dfbefdSBarry Smith + a - array to hold history, usually was set with `SNESSetConvergenceHistory()` 4523758f92a0SBarry Smith . its - integer array holds the number of linear iterations (or 4524758f92a0SBarry Smith negative if not converged) for each solve. 452520f4b53cSBarry Smith - na - size of `a` and `its` 4526758f92a0SBarry Smith 4527dc4c0fb0SBarry Smith Level: intermediate 4528dc4c0fb0SBarry Smith 452920f4b53cSBarry Smith Note: 453020f4b53cSBarry Smith This routine is useful, e.g., when running a code for purposes 453120f4b53cSBarry Smith of accurate performance monitoring, when no I/O should be done 453220f4b53cSBarry Smith during the section of code that is being timed. 453320f4b53cSBarry Smith 4534ce78bad3SBarry Smith Fortran Notes: 4535ce78bad3SBarry Smith Return the arrays with ``SNESRestoreConvergenceHistory()` 4536ce78bad3SBarry Smith 4537ce78bad3SBarry Smith Use the arguments 4538dc4c0fb0SBarry Smith .vb 4539ce78bad3SBarry Smith PetscReal, pointer :: a(:) 4540ce78bad3SBarry Smith PetscInt, pointer :: its(:) 4541dc4c0fb0SBarry Smith .ve 4542758f92a0SBarry Smith 45431cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceHistory()` 4544758f92a0SBarry Smith @*/ 4545d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergenceHistory(SNES snes, PetscReal *a[], PetscInt *its[], PetscInt *na) 4546d71ae5a4SJacob Faibussowitsch { 4547758f92a0SBarry Smith PetscFunctionBegin; 45480700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4549758f92a0SBarry Smith if (a) *a = snes->conv_hist; 4550758f92a0SBarry Smith if (its) *its = snes->conv_hist_its; 4551115dd874SBarry Smith if (na) *na = (PetscInt)snes->conv_hist_len; 45523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4553c9005455SLois Curfman McInnes } 4554c9005455SLois Curfman McInnes 4555ac226902SBarry Smith /*@C 455676b2cf59SMatthew Knepley SNESSetUpdate - Sets the general-purpose update function called 4557eec8f646SJed Brown at the beginning of every iteration of the nonlinear solve. Specifically 455853e5d35bSStefano Zampini it is called just before the Jacobian is "evaluated" and after the function 455953e5d35bSStefano Zampini evaluation. 456076b2cf59SMatthew Knepley 4561c3339decSBarry Smith Logically Collective 456276b2cf59SMatthew Knepley 456376b2cf59SMatthew Knepley Input Parameters: 4564a2b725a8SWilliam Gropp + snes - The nonlinear solver context 456553e5d35bSStefano Zampini - func - The update function; for calling sequence see `SNESUpdateFn` 456676b2cf59SMatthew Knepley 4567fe97e370SBarry Smith Level: advanced 4568fe97e370SBarry Smith 4569420bcc1bSBarry Smith Notes: 4570f6dfbefdSBarry 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 4571f6dfbefdSBarry Smith to `SNESSetFunction()`, or `SNESSetPicard()` 457253e5d35bSStefano Zampini This is not used by most users, and it is intended to provide a general hook that is run 457353e5d35bSStefano Zampini right before the direction step is computed. 4574ce78bad3SBarry Smith 457553e5d35bSStefano Zampini Users are free to modify the current residual vector, 457653e5d35bSStefano Zampini the current linearization point, or any other vector associated to the specific solver used. 457753e5d35bSStefano Zampini If such modifications take place, it is the user responsibility to update all the relevant 4578ce78bad3SBarry Smith vectors. For example, if one is adjusting the model parameters at each Newton step their code may look like 4579ce78bad3SBarry Smith .vb 4580ce78bad3SBarry Smith PetscErrorCode update(SNES snes, PetscInt iteration) 4581ce78bad3SBarry Smith { 4582ce78bad3SBarry Smith PetscFunctionBeginUser; 4583ce78bad3SBarry Smith if (iteration > 0) { 4584ce78bad3SBarry Smith // update the model parameters here 4585ce78bad3SBarry Smith Vec x,f; 4586ce78bad3SBarry Smith PetscCall(SNESGetSolution(snes,&x)); 4587ce78bad3SBarry Smith PetcCall(SNESGetFunction(snes,&f,NULL,NULL)); 4588ce78bad3SBarry Smith PetscCall(SNESComputeFunction(snes,x,f)); 4589ce78bad3SBarry Smith } 4590ce78bad3SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 4591ce78bad3SBarry Smith } 4592ce78bad3SBarry Smith .ve 459376b2cf59SMatthew Knepley 4594aaa8cc7dSPierre 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. 45956b7fb656SBarry Smith 4596e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetJacobian()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRSetPostCheck()`, 459753e5d35bSStefano Zampini `SNESMonitorSet()` 459876b2cf59SMatthew Knepley @*/ 459953e5d35bSStefano Zampini PetscErrorCode SNESSetUpdate(SNES snes, SNESUpdateFn *func) 4600d71ae5a4SJacob Faibussowitsch { 460176b2cf59SMatthew Knepley PetscFunctionBegin; 46020700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4603e7788613SBarry Smith snes->ops->update = func; 46043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 460576b2cf59SMatthew Knepley } 460676b2cf59SMatthew Knepley 4607ffeef943SBarry Smith /*@ 4608f6dfbefdSBarry Smith SNESConvergedReasonView - Displays the reason a `SNES` solve converged or diverged to a viewer 46092a359c20SBarry Smith 4610c3339decSBarry Smith Collective 46112a359c20SBarry Smith 4612e4094ef1SJacob Faibussowitsch Input Parameters: 4613f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 46142a359c20SBarry Smith - viewer - the viewer to display the reason 46152a359c20SBarry Smith 46162a359c20SBarry Smith Options Database Keys: 4617ee300463SSatish Balay + -snes_converged_reason - print reason for converged or diverged, also prints number of iterations 4618ee300463SSatish Balay - -snes_converged_reason ::failed - only print reason and number of iterations when diverged 4619eafd5ff0SAlex Lindsay 4620420bcc1bSBarry Smith Level: beginner 4621420bcc1bSBarry Smith 4622f6dfbefdSBarry Smith Note: 4623f6dfbefdSBarry Smith To change the format of the output call `PetscViewerPushFormat`(viewer,format) before this call. Use `PETSC_VIEWER_DEFAULT` for the default, 4624f6dfbefdSBarry Smith use `PETSC_VIEWER_FAILED` to only display a reason if it fails. 46252a359c20SBarry Smith 46261cc06b55SBarry Smith .seealso: [](ch_snes), `SNESConvergedReason`, `PetscViewer`, `SNES`, 4627f6dfbefdSBarry Smith `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, 4628f6dfbefdSBarry Smith `SNESConvergedReasonViewFromOptions()`, 4629db781477SPatrick Sanan `PetscViewerPushFormat()`, `PetscViewerPopFormat()` 46302a359c20SBarry Smith @*/ 4631d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonView(SNES snes, PetscViewer viewer) 4632d71ae5a4SJacob Faibussowitsch { 463375cca76cSMatthew G. Knepley PetscViewerFormat format; 46342a359c20SBarry Smith PetscBool isAscii; 46352a359c20SBarry Smith 46362a359c20SBarry Smith PetscFunctionBegin; 463719a666eeSBarry Smith if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)); 46389566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii)); 46392a359c20SBarry Smith if (isAscii) { 46409566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 464165bf60d2SBarry Smith PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel + 1)); 464275cca76cSMatthew G. Knepley if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 464375cca76cSMatthew G. Knepley DM dm; 464475cca76cSMatthew G. Knepley Vec u; 464575cca76cSMatthew G. Knepley PetscDS prob; 464675cca76cSMatthew G. Knepley PetscInt Nf, f; 464795cbbfd3SMatthew G. Knepley PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *); 464895cbbfd3SMatthew G. Knepley void **exactCtx; 464975cca76cSMatthew G. Knepley PetscReal error; 465075cca76cSMatthew G. Knepley 46519566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 46529566063dSJacob Faibussowitsch PetscCall(SNESGetSolution(snes, &u)); 46539566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob)); 46549566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(prob, &Nf)); 46559566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(Nf, &exactSol, Nf, &exactCtx)); 46569566063dSJacob Faibussowitsch for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f])); 46579566063dSJacob Faibussowitsch PetscCall(DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error)); 46589566063dSJacob Faibussowitsch PetscCall(PetscFree2(exactSol, exactCtx)); 46599566063dSJacob Faibussowitsch if (error < 1.0e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n")); 466063a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", (double)error)); 466175cca76cSMatthew G. Knepley } 4662eafd5ff0SAlex Lindsay if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) { 46632a359c20SBarry Smith if (((PetscObject)snes)->prefix) { 466463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter)); 46652a359c20SBarry Smith } else { 466663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve converged due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter)); 46672a359c20SBarry Smith } 4668eafd5ff0SAlex Lindsay } else if (snes->reason <= 0) { 46692a359c20SBarry Smith if (((PetscObject)snes)->prefix) { 467063a3b9bcSJacob 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)); 46712a359c20SBarry Smith } else { 467263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve did not converge due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter)); 46732a359c20SBarry Smith } 46742a359c20SBarry Smith } 467565bf60d2SBarry Smith PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel + 1)); 46762a359c20SBarry Smith } 46773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 46782a359c20SBarry Smith } 46792a359c20SBarry Smith 4680c4421ceaSFande Kong /*@C 4681c4421ceaSFande Kong SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the 4682aaa8cc7dSPierre Jolivet end of the nonlinear solver to display the convergence reason of the nonlinear solver. 4683c4421ceaSFande Kong 4684c3339decSBarry Smith Logically Collective 4685c4421ceaSFande Kong 4686c4421ceaSFande Kong Input Parameters: 4687f6dfbefdSBarry Smith + snes - the `SNES` context 4688420bcc1bSBarry Smith . f - the `SNESConvergedReason` view function 4689420bcc1bSBarry Smith . vctx - [optional] user-defined context for private data for the `SNESConvergedReason` view function (use `NULL` if no context is desired) 469049abdd8aSBarry Smith - reasonviewdestroy - [optional] routine that frees the context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence 4691420bcc1bSBarry Smith 4692420bcc1bSBarry Smith Calling sequence of `f`: 4693420bcc1bSBarry Smith + snes - the `SNES` context 469449abdd8aSBarry Smith - vctx - [optional] context for private data for the function 4695c4421ceaSFande Kong 4696c4421ceaSFande Kong Options Database Keys: 4697f6dfbefdSBarry Smith + -snes_converged_reason - sets a default `SNESConvergedReasonView()` 4698420bcc1bSBarry Smith - -snes_converged_reason_view_cancel - cancels all converged reason viewers that have been hardwired into a code by 4699420bcc1bSBarry Smith calls to `SNESConvergedReasonViewSet()`, but does not cancel those set via the options database. 4700c4421ceaSFande Kong 4701dc4c0fb0SBarry Smith Level: intermediate 4702dc4c0fb0SBarry Smith 4703f6dfbefdSBarry Smith Note: 4704c4421ceaSFande Kong Several different converged reason view routines may be set by calling 4705f6dfbefdSBarry Smith `SNESConvergedReasonViewSet()` multiple times; all will be called in the 4706c4421ceaSFande Kong order in which they were set. 4707c4421ceaSFande Kong 470849abdd8aSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`, `SNESConvergedReasonViewCancel()`, 470949abdd8aSBarry Smith `PetscCtxDestroyFn` 4710c4421ceaSFande Kong @*/ 471149abdd8aSBarry Smith PetscErrorCode SNESConvergedReasonViewSet(SNES snes, PetscErrorCode (*f)(SNES snes, void *vctx), void *vctx, PetscCtxDestroyFn *reasonviewdestroy) 4712d71ae5a4SJacob Faibussowitsch { 4713c4421ceaSFande Kong PetscFunctionBegin; 4714c4421ceaSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4715453a69bbSBarry Smith for (PetscInt i = 0; i < snes->numberreasonviews; i++) { 4716453a69bbSBarry Smith PetscBool identical; 4717453a69bbSBarry Smith 4718453a69bbSBarry Smith PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))(PetscVoidFn *)f, vctx, reasonviewdestroy, (PetscErrorCode (*)(void))(PetscVoidFn *)snes->reasonview[i], snes->reasonviewcontext[i], snes->reasonviewdestroy[i], &identical)); 47193ba16761SJacob Faibussowitsch if (identical) PetscFunctionReturn(PETSC_SUCCESS); 4720c4421ceaSFande Kong } 47215f80ce2aSJacob Faibussowitsch PetscCheck(snes->numberreasonviews < MAXSNESREASONVIEWS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many SNES reasonview set"); 4722c4421ceaSFande Kong snes->reasonview[snes->numberreasonviews] = f; 4723c4421ceaSFande Kong snes->reasonviewdestroy[snes->numberreasonviews] = reasonviewdestroy; 4724835f2295SStefano Zampini snes->reasonviewcontext[snes->numberreasonviews++] = vctx; 47253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4726c4421ceaSFande Kong } 4727c4421ceaSFande Kong 472891f3e32bSBarry Smith /*@ 4729420bcc1bSBarry Smith SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a `SNESConvergedReason` is to be viewed at the end of `SNESSolve()` 47300b4b7b1cSBarry Smith All the user-provided viewer routines set with `SNESConvergedReasonViewSet()` will be called, if they exist. 47312a359c20SBarry Smith 4732c3339decSBarry Smith Collective 47332a359c20SBarry Smith 47342fe279fdSBarry Smith Input Parameter: 4735f6dfbefdSBarry Smith . snes - the `SNES` object 47362a359c20SBarry Smith 4737f6dfbefdSBarry Smith Level: advanced 47382a359c20SBarry Smith 47391cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESConvergedReasonViewSet()`, `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, 4740f6dfbefdSBarry Smith `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()` 47412a359c20SBarry Smith @*/ 4742d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes) 4743d71ae5a4SJacob Faibussowitsch { 47442a359c20SBarry Smith static PetscBool incall = PETSC_FALSE; 47452a359c20SBarry Smith 47462a359c20SBarry Smith PetscFunctionBegin; 47473ba16761SJacob Faibussowitsch if (incall) PetscFunctionReturn(PETSC_SUCCESS); 47482a359c20SBarry Smith incall = PETSC_TRUE; 4749c4421ceaSFande Kong 4750c4421ceaSFande Kong /* All user-provided viewers are called first, if they exist. */ 475136d43d94SBarry Smith for (PetscInt i = 0; i < snes->numberreasonviews; i++) PetscCall((*snes->reasonview[i])(snes, snes->reasonviewcontext[i])); 4752c4421ceaSFande Kong 4753c4421ceaSFande Kong /* Call PETSc default routine if users ask for it */ 475436d43d94SBarry Smith if (snes->convergedreasonviewer) { 475536d43d94SBarry Smith PetscCall(PetscViewerPushFormat(snes->convergedreasonviewer, snes->convergedreasonformat)); 475636d43d94SBarry Smith PetscCall(SNESConvergedReasonView(snes, snes->convergedreasonviewer)); 475736d43d94SBarry Smith PetscCall(PetscViewerPopFormat(snes->convergedreasonviewer)); 47582a359c20SBarry Smith } 47592a359c20SBarry Smith incall = PETSC_FALSE; 47603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 47612a359c20SBarry Smith } 47622a359c20SBarry Smith 4763487a658cSBarry Smith /*@ 47640b4b7b1cSBarry Smith SNESSolve - Solves a nonlinear system $F(x) = b $ associated with a `SNES` object 47659b94acceSBarry Smith 4766c3339decSBarry Smith Collective 4767c7afd0dbSLois Curfman McInnes 4768b2002411SLois Curfman McInnes Input Parameters: 4769f6dfbefdSBarry Smith + snes - the `SNES` context 47700b4b7b1cSBarry Smith . b - the constant part of the equation $F(x) = b$, or `NULL` to use zero. 477185385478SLisandro Dalcin - x - the solution vector. 47729b94acceSBarry Smith 4773dc4c0fb0SBarry Smith Level: beginner 4774dc4c0fb0SBarry Smith 4775f6dfbefdSBarry Smith Note: 4776420bcc1bSBarry Smith The user should initialize the vector, `x`, with the initial guess 4777a9b45538SStefano Zampini for the nonlinear solve prior to calling `SNESSolve()` . 47788ddd3da0SLois Curfman McInnes 47791cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESSetFunction()`, `SNESSetJacobian()`, `SNESSetGridSequence()`, `SNESGetSolution()`, 4780db781477SPatrick Sanan `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRGetPreCheck()`, `SNESNewtonTRSetPostCheck()`, `SNESNewtonTRGetPostCheck()`, 4781a9b45538SStefano Zampini `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()` 47829b94acceSBarry Smith @*/ 4783d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSolve(SNES snes, Vec b, Vec x) 4784d71ae5a4SJacob Faibussowitsch { 4785ace3abfcSBarry Smith PetscBool flg; 4786efd51863SBarry Smith PetscInt grid; 47870298fd71SBarry Smith Vec xcreated = NULL; 4788caa4e7f2SJed Brown DM dm; 4789052efed2SBarry Smith 47903a40ed3dSBarry Smith PetscFunctionBegin; 47910700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4792a69afd8bSBarry Smith if (x) PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4793a69afd8bSBarry Smith if (x) PetscCheckSameComm(snes, 1, x, 3); 47940700a824SBarry Smith if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 479585385478SLisandro Dalcin if (b) PetscCheckSameComm(snes, 1, b, 2); 479685385478SLisandro Dalcin 479734b4d3a8SMatthew G. Knepley /* High level operations using the nonlinear solver */ 479806fc46c8SMatthew G. Knepley { 479906fc46c8SMatthew G. Knepley PetscViewer viewer; 480006fc46c8SMatthew G. Knepley PetscViewerFormat format; 48017c88af5aSMatthew G. Knepley PetscInt num; 480206fc46c8SMatthew G. Knepley PetscBool flg; 480306fc46c8SMatthew G. Knepley static PetscBool incall = PETSC_FALSE; 480406fc46c8SMatthew G. Knepley 480506fc46c8SMatthew G. Knepley if (!incall) { 480634b4d3a8SMatthew G. Knepley /* Estimate the convergence rate of the discretization */ 4807648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg)); 480806fc46c8SMatthew G. Knepley if (flg) { 480906fc46c8SMatthew G. Knepley PetscConvEst conv; 481046079b62SMatthew G. Knepley DM dm; 481146079b62SMatthew G. Knepley PetscReal *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */ 481246079b62SMatthew G. Knepley PetscInt Nf; 481306fc46c8SMatthew G. Knepley 481406fc46c8SMatthew G. Knepley incall = PETSC_TRUE; 48159566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 48169566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 48179566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(Nf, &alpha)); 48189566063dSJacob Faibussowitsch PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)snes), &conv)); 48199566063dSJacob Faibussowitsch PetscCall(PetscConvEstSetSolver(conv, (PetscObject)snes)); 48209566063dSJacob Faibussowitsch PetscCall(PetscConvEstSetFromOptions(conv)); 48219566063dSJacob Faibussowitsch PetscCall(PetscConvEstSetUp(conv)); 48229566063dSJacob Faibussowitsch PetscCall(PetscConvEstGetConvRate(conv, alpha)); 48239566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(viewer, format)); 48249566063dSJacob Faibussowitsch PetscCall(PetscConvEstRateView(conv, alpha, viewer)); 48259566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer)); 4826648c30bcSBarry Smith PetscCall(PetscViewerDestroy(&viewer)); 48279566063dSJacob Faibussowitsch PetscCall(PetscConvEstDestroy(&conv)); 48289566063dSJacob Faibussowitsch PetscCall(PetscFree(alpha)); 482906fc46c8SMatthew G. Knepley incall = PETSC_FALSE; 483006fc46c8SMatthew G. Knepley } 483134b4d3a8SMatthew G. Knepley /* Adaptively refine the initial grid */ 4832b2588ea6SMatthew G. Knepley num = 1; 48339566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_initial", &num, &flg)); 483434b4d3a8SMatthew G. Knepley if (flg) { 483534b4d3a8SMatthew G. Knepley DMAdaptor adaptor; 483634b4d3a8SMatthew G. Knepley 483734b4d3a8SMatthew G. Knepley incall = PETSC_TRUE; 48389566063dSJacob Faibussowitsch PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor)); 48399566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSolver(adaptor, snes)); 48409566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSequenceLength(adaptor, num)); 48419566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetFromOptions(adaptor)); 48429566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetUp(adaptor)); 48439566063dSJacob Faibussowitsch PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x)); 48449566063dSJacob Faibussowitsch PetscCall(DMAdaptorDestroy(&adaptor)); 484534b4d3a8SMatthew G. Knepley incall = PETSC_FALSE; 484634b4d3a8SMatthew G. Knepley } 48477c88af5aSMatthew G. Knepley /* Use grid sequencing to adapt */ 48487c88af5aSMatthew G. Knepley num = 0; 48499566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_sequence", &num, NULL)); 48507c88af5aSMatthew G. Knepley if (num) { 48517c88af5aSMatthew G. Knepley DMAdaptor adaptor; 4852e03fd340SMatthew G. Knepley const char *prefix; 48537c88af5aSMatthew G. Knepley 48547c88af5aSMatthew G. Knepley incall = PETSC_TRUE; 48559566063dSJacob Faibussowitsch PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor)); 4856e03fd340SMatthew G. Knepley PetscCall(SNESGetOptionsPrefix(snes, &prefix)); 4857e03fd340SMatthew G. Knepley PetscCall(DMAdaptorSetOptionsPrefix(adaptor, prefix)); 48589566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSolver(adaptor, snes)); 48599566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSequenceLength(adaptor, num)); 48609566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetFromOptions(adaptor)); 48619566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetUp(adaptor)); 4862e5148a0bSMatthew G. Knepley PetscCall(PetscObjectViewFromOptions((PetscObject)adaptor, NULL, "-snes_adapt_view")); 48639566063dSJacob Faibussowitsch PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x)); 48649566063dSJacob Faibussowitsch PetscCall(DMAdaptorDestroy(&adaptor)); 48657c88af5aSMatthew G. Knepley incall = PETSC_FALSE; 48667c88af5aSMatthew G. Knepley } 486706fc46c8SMatthew G. Knepley } 486806fc46c8SMatthew G. Knepley } 4869ad540459SPierre Jolivet if (!x) x = snes->vec_sol; 4870caa4e7f2SJed Brown if (!x) { 48719566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 48729566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dm, &xcreated)); 4873a69afd8bSBarry Smith x = xcreated; 4874a69afd8bSBarry Smith } 48759566063dSJacob Faibussowitsch PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view_pre")); 4876f05ece33SBarry Smith 48779566063dSJacob Faibussowitsch for (grid = 0; grid < snes->gridsequence; grid++) PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)))); 4878efd51863SBarry Smith for (grid = 0; grid < snes->gridsequence + 1; grid++) { 487985385478SLisandro Dalcin /* set solution vector */ 48809566063dSJacob Faibussowitsch if (!grid) PetscCall(PetscObjectReference((PetscObject)x)); 48819566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol)); 488285385478SLisandro Dalcin snes->vec_sol = x; 48839566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 4884caa4e7f2SJed Brown 4885caa4e7f2SJed Brown /* set affine vector if provided */ 48869566063dSJacob Faibussowitsch if (b) PetscCall(PetscObjectReference((PetscObject)b)); 48879566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_rhs)); 488885385478SLisandro Dalcin snes->vec_rhs = b; 488985385478SLisandro Dalcin 48905f80ce2aSJacob 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"); 48915f80ce2aSJacob Faibussowitsch PetscCheck(snes->vec_func != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be function vector"); 4892dd8e379bSPierre Jolivet PetscCheck(snes->vec_rhs != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be right-hand side vector"); 4893aa624791SPierre Jolivet if (!snes->vec_sol_update /* && snes->vec_sol */) PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_sol_update)); 48949566063dSJacob Faibussowitsch PetscCall(DMShellSetGlobalVector(dm, snes->vec_sol)); 48959566063dSJacob Faibussowitsch PetscCall(SNESSetUp(snes)); 48963f149594SLisandro Dalcin 48977eee914bSBarry Smith if (!grid) { 48989927e4dfSBarry Smith if (snes->ops->computeinitialguess) PetscCallBack("SNES callback compute initial guess", (*snes->ops->computeinitialguess)(snes, snes->vec_sol, snes->initialguessP)); 4899dd568438SSatish Balay } 4900d25893d9SBarry Smith 4901abc0a331SBarry Smith if (snes->conv_hist_reset) snes->conv_hist_len = 0; 490212b1dd1aSStefano Zampini PetscCall(SNESResetCounters(snes)); 49032d157150SStefano Zampini snes->reason = SNES_CONVERGED_ITERATING; 49049566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_Solve, snes, 0, 0, 0)); 4905dbbe0bcdSBarry Smith PetscUseTypeMethod(snes, solve); 49069566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_Solve, snes, 0, 0, 0)); 49072d157150SStefano Zampini PetscCheck(snes->reason, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error, solver %s returned without setting converged reason", ((PetscObject)snes)->type_name); 4908422a814eSBarry Smith snes->domainerror = PETSC_FALSE; /* clear the flag if it has been set */ 49093f149594SLisandro Dalcin 491037ec4e1aSPeter Brune if (snes->lagjac_persist) snes->jac_iter += snes->iter; 491137ec4e1aSPeter Brune if (snes->lagpre_persist) snes->pre_iter += snes->iter; 491237ec4e1aSPeter Brune 4913648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_test_local_min", NULL, NULL, &flg)); 49149566063dSJacob Faibussowitsch if (flg && !PetscPreLoadingOn) PetscCall(SNESTestLocalMin(snes)); 4915c4421ceaSFande Kong /* Call converged reason views. This may involve user-provided viewers as well */ 49169566063dSJacob Faibussowitsch PetscCall(SNESConvergedReasonViewFromOptions(snes)); 49175968eb51SBarry Smith 49181b3000acSStefano Zampini if (snes->errorifnotconverged) { 49191b3000acSStefano Zampini if (snes->reason < 0) PetscCall(SNESMonitorCancel(snes)); 49201b3000acSStefano Zampini PetscCheck(snes->reason >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_NOT_CONVERGED, "SNESSolve has not converged"); 49211b3000acSStefano Zampini } 49229c8e83a9SBarry Smith if (snes->reason < 0) break; 4923efd51863SBarry Smith if (grid < snes->gridsequence) { 4924efd51863SBarry Smith DM fine; 4925efd51863SBarry Smith Vec xnew; 4926efd51863SBarry Smith Mat interp; 4927efd51863SBarry Smith 49289566063dSJacob Faibussowitsch PetscCall(DMRefine(snes->dm, PetscObjectComm((PetscObject)snes), &fine)); 49295f80ce2aSJacob Faibussowitsch PetscCheck(fine, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_INCOMP, "DMRefine() did not perform any refinement, cannot continue grid sequencing"); 49302eace19aSMatthew G. Knepley PetscCall(DMGetCoordinatesLocalSetUp(fine)); 49319566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(snes->dm, fine, &interp, NULL)); 49329566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(fine, &xnew)); 49339566063dSJacob Faibussowitsch PetscCall(MatInterpolate(interp, x, xnew)); 49349566063dSJacob Faibussowitsch PetscCall(DMInterpolate(snes->dm, interp, fine)); 49359566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interp)); 4936efd51863SBarry Smith x = xnew; 4937efd51863SBarry Smith 49389566063dSJacob Faibussowitsch PetscCall(SNESReset(snes)); 49399566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes, fine)); 49409566063dSJacob Faibussowitsch PetscCall(SNESResetFromOptions(snes)); 49419566063dSJacob Faibussowitsch PetscCall(DMDestroy(&fine)); 49429566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)))); 4943efd51863SBarry Smith } 4944efd51863SBarry Smith } 49459566063dSJacob Faibussowitsch PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view")); 49469566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(snes->vec_sol, (PetscObject)snes, "-snes_view_solution")); 49479566063dSJacob Faibussowitsch PetscCall(DMMonitor(snes->dm)); 49489566063dSJacob Faibussowitsch PetscCall(SNESMonitorPauseFinal_Internal(snes)); 49493f7e2da0SPeter Brune 49509566063dSJacob Faibussowitsch PetscCall(VecDestroy(&xcreated)); 49519566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsBlock((PetscObject)snes)); 49523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49539b94acceSBarry Smith } 49549b94acceSBarry Smith 49559b94acceSBarry Smith /* --------- Internal routines for SNES Package --------- */ 49569b94acceSBarry Smith 4957cc4c1da9SBarry Smith /*@ 49580b4b7b1cSBarry Smith SNESSetType - Sets the algorithm/method to be used to solve the nonlinear system with the given `SNES` 49599b94acceSBarry Smith 4960c3339decSBarry Smith Collective 4961fee21e36SBarry Smith 4962c7afd0dbSLois Curfman McInnes Input Parameters: 4963f6dfbefdSBarry Smith + snes - the `SNES` context 4964454a90a3SBarry Smith - type - a known method 4965c7afd0dbSLois Curfman McInnes 4966c7afd0dbSLois Curfman McInnes Options Database Key: 4967454a90a3SBarry Smith . -snes_type <type> - Sets the method; use -help for a list 496804d7464bSBarry Smith of available methods (for instance, newtonls or newtontr) 4969ae12b187SLois Curfman McInnes 4970dc4c0fb0SBarry Smith Level: intermediate 4971dc4c0fb0SBarry Smith 49729b94acceSBarry Smith Notes: 49730b4b7b1cSBarry Smith See `SNESType` for available methods (for instance) 4974f6dfbefdSBarry Smith + `SNESNEWTONLS` - Newton's method with line search 4975c7afd0dbSLois Curfman McInnes (systems of nonlinear equations) 49764a221d59SStefano Zampini - `SNESNEWTONTR` - Newton's method with trust region 4977c7afd0dbSLois Curfman McInnes (systems of nonlinear equations) 49789b94acceSBarry Smith 4979f6dfbefdSBarry Smith Normally, it is best to use the `SNESSetFromOptions()` command and then 4980f6dfbefdSBarry Smith set the `SNES` solver type from the options database rather than by using 4981ae12b187SLois Curfman McInnes this routine. Using the options database provides the user with 4982ae12b187SLois Curfman McInnes maximum flexibility in evaluating the many nonlinear solvers. 4983f6dfbefdSBarry Smith The `SNESSetType()` routine is provided for those situations where it 4984ae12b187SLois Curfman McInnes is necessary to set the nonlinear solver independently of the command 4985ae12b187SLois Curfman McInnes line or options database. This might be the case, for example, when 4986ae12b187SLois Curfman McInnes the choice of solver changes during the execution of the program, 4987ae12b187SLois Curfman McInnes and the user's application is taking responsibility for choosing the 4988b0a32e0cSBarry Smith appropriate method. 498936851e7fSLois Curfman McInnes 4990420bcc1bSBarry Smith Developer Note: 4991f6dfbefdSBarry Smith `SNESRegister()` adds a constructor for a new `SNESType` to `SNESList`, `SNESSetType()` locates 4992f6dfbefdSBarry Smith the constructor in that list and calls it to create the specific object. 49938f6c3df8SBarry Smith 49941cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESType`, `SNESCreate()`, `SNESDestroy()`, `SNESGetType()`, `SNESSetFromOptions()` 49959b94acceSBarry Smith @*/ 4996d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetType(SNES snes, SNESType type) 4997d71ae5a4SJacob Faibussowitsch { 4998ace3abfcSBarry Smith PetscBool match; 49995f80ce2aSJacob Faibussowitsch PetscErrorCode (*r)(SNES); 50003a40ed3dSBarry Smith 50013a40ed3dSBarry Smith PetscFunctionBegin; 50020700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 50034f572ea9SToby Isaac PetscAssertPointer(type, 2); 500482bf6240SBarry Smith 50059566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes, type, &match)); 50063ba16761SJacob Faibussowitsch if (match) PetscFunctionReturn(PETSC_SUCCESS); 500792ff6ae8SBarry Smith 50089566063dSJacob Faibussowitsch PetscCall(PetscFunctionListFind(SNESList, type, &r)); 50096adde796SStefano Zampini PetscCheck(r, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested SNES type %s", type); 501075396ef9SLisandro Dalcin /* Destroy the previous private SNES context */ 5011dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, destroy); 501243547594SStefano Zampini /* Reinitialize type-specific function pointers in SNESOps structure */ 501343547594SStefano Zampini snes->ops->reset = NULL; 50149e5d0892SLisandro Dalcin snes->ops->setup = NULL; 50159e5d0892SLisandro Dalcin snes->ops->solve = NULL; 50169e5d0892SLisandro Dalcin snes->ops->view = NULL; 50179e5d0892SLisandro Dalcin snes->ops->setfromoptions = NULL; 50189e5d0892SLisandro Dalcin snes->ops->destroy = NULL; 50197fe760d5SStefano Zampini 50207fe760d5SStefano Zampini /* It may happen the user has customized the line search before calling SNESSetType */ 50219566063dSJacob Faibussowitsch if (((PetscObject)snes)->type_name) PetscCall(SNESLineSearchDestroy(&snes->linesearch)); 50227fe760d5SStefano Zampini 502375396ef9SLisandro Dalcin /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */ 502475396ef9SLisandro Dalcin snes->setupcalled = PETSC_FALSE; 5025f5af7f23SKarl Rupp 50269566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)snes, type)); 50279566063dSJacob Faibussowitsch PetscCall((*r)(snes)); 50283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50299b94acceSBarry Smith } 50309b94acceSBarry Smith 5031cc4c1da9SBarry Smith /*@ 5032f6dfbefdSBarry Smith SNESGetType - Gets the `SNES` method type and name (as a string). 50339b94acceSBarry Smith 5034c7afd0dbSLois Curfman McInnes Not Collective 5035c7afd0dbSLois Curfman McInnes 50369b94acceSBarry Smith Input Parameter: 50374b0e389bSBarry Smith . snes - nonlinear solver context 50389b94acceSBarry Smith 50399b94acceSBarry Smith Output Parameter: 5040f6dfbefdSBarry Smith . type - `SNES` method (a character string) 50419b94acceSBarry Smith 504236851e7fSLois Curfman McInnes Level: intermediate 504336851e7fSLois Curfman McInnes 50441cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetType()`, `SNESType`, `SNESSetFromOptions()`, `SNES` 50459b94acceSBarry Smith @*/ 5046d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetType(SNES snes, SNESType *type) 5047d71ae5a4SJacob Faibussowitsch { 50483a40ed3dSBarry Smith PetscFunctionBegin; 50490700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 50504f572ea9SToby Isaac PetscAssertPointer(type, 2); 50517adad957SLisandro Dalcin *type = ((PetscObject)snes)->type_name; 50523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50539b94acceSBarry Smith } 50549b94acceSBarry Smith 50553cd8a7caSMatthew G. Knepley /*@ 5056f6dfbefdSBarry Smith SNESSetSolution - Sets the solution vector for use by the `SNES` routines. 50573cd8a7caSMatthew G. Knepley 5058c3339decSBarry Smith Logically Collective 50593cd8a7caSMatthew G. Knepley 50603cd8a7caSMatthew G. Knepley Input Parameters: 5061f6dfbefdSBarry Smith + snes - the `SNES` context obtained from `SNESCreate()` 50623cd8a7caSMatthew G. Knepley - u - the solution vector 50633cd8a7caSMatthew G. Knepley 50643cd8a7caSMatthew G. Knepley Level: beginner 50653cd8a7caSMatthew G. Knepley 50661cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetSolution()`, `Vec` 50673cd8a7caSMatthew G. Knepley @*/ 5068d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetSolution(SNES snes, Vec u) 5069d71ae5a4SJacob Faibussowitsch { 50703cd8a7caSMatthew G. Knepley DM dm; 50713cd8a7caSMatthew G. Knepley 50723cd8a7caSMatthew G. Knepley PetscFunctionBegin; 50733cd8a7caSMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 50743cd8a7caSMatthew G. Knepley PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 50759566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)u)); 50769566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol)); 50773cd8a7caSMatthew G. Knepley 50783cd8a7caSMatthew G. Knepley snes->vec_sol = u; 50793cd8a7caSMatthew G. Knepley 50809566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 50819566063dSJacob Faibussowitsch PetscCall(DMShellSetGlobalVector(dm, u)); 50823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50833cd8a7caSMatthew G. Knepley } 50843cd8a7caSMatthew G. Knepley 508552baeb72SSatish Balay /*@ 50869b94acceSBarry Smith SNESGetSolution - Returns the vector where the approximate solution is 5087f6dfbefdSBarry Smith stored. This is the fine grid solution when using `SNESSetGridSequence()`. 50889b94acceSBarry Smith 5089420bcc1bSBarry Smith Not Collective, but `x` is parallel if `snes` is parallel 5090c7afd0dbSLois Curfman McInnes 50919b94acceSBarry Smith Input Parameter: 5092f6dfbefdSBarry Smith . snes - the `SNES` context 50939b94acceSBarry Smith 50949b94acceSBarry Smith Output Parameter: 50959b94acceSBarry Smith . x - the solution 50969b94acceSBarry Smith 509770e92668SMatthew Knepley Level: intermediate 509836851e7fSLois Curfman McInnes 50991cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetSolution()`, `SNESSolve()`, `SNES`, `SNESGetSolutionUpdate()`, `SNESGetFunction()` 51009b94acceSBarry Smith @*/ 5101d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolution(SNES snes, Vec *x) 5102d71ae5a4SJacob Faibussowitsch { 51033a40ed3dSBarry Smith PetscFunctionBegin; 51040700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 51054f572ea9SToby Isaac PetscAssertPointer(x, 2); 510685385478SLisandro Dalcin *x = snes->vec_sol; 51073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 510870e92668SMatthew Knepley } 510970e92668SMatthew Knepley 511052baeb72SSatish Balay /*@ 51119b94acceSBarry Smith SNESGetSolutionUpdate - Returns the vector where the solution update is 51129b94acceSBarry Smith stored. 51139b94acceSBarry Smith 5114420bcc1bSBarry Smith Not Collective, but `x` is parallel if `snes` is parallel 5115c7afd0dbSLois Curfman McInnes 51169b94acceSBarry Smith Input Parameter: 5117f6dfbefdSBarry Smith . snes - the `SNES` context 51189b94acceSBarry Smith 51199b94acceSBarry Smith Output Parameter: 51209b94acceSBarry Smith . x - the solution update 51219b94acceSBarry Smith 512236851e7fSLois Curfman McInnes Level: advanced 512336851e7fSLois Curfman McInnes 51241cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()` 51259b94acceSBarry Smith @*/ 5126d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionUpdate(SNES snes, Vec *x) 5127d71ae5a4SJacob Faibussowitsch { 51283a40ed3dSBarry Smith PetscFunctionBegin; 51290700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 51304f572ea9SToby Isaac PetscAssertPointer(x, 2); 513185385478SLisandro Dalcin *x = snes->vec_sol_update; 51323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 51339b94acceSBarry Smith } 51349b94acceSBarry Smith 51359b94acceSBarry Smith /*@C 5136f6dfbefdSBarry Smith SNESGetFunction - Returns the function that defines the nonlinear system set with `SNESSetFunction()` 51379b94acceSBarry Smith 5138420bcc1bSBarry Smith Not Collective, but `r` is parallel if `snes` is parallel. Collective if `r` is requested, but has not been created yet. 5139c7afd0dbSLois Curfman McInnes 51409b94acceSBarry Smith Input Parameter: 5141f6dfbefdSBarry Smith . snes - the `SNES` context 51429b94acceSBarry Smith 5143d8d19677SJose E. Roman Output Parameters: 5144dc4c0fb0SBarry Smith + r - the vector that is used to store residuals (or `NULL` if you don't want it) 51458434afd1SBarry Smith . f - the function (or `NULL` if you don't want it); for calling sequence see `SNESFunctionFn` 5146dc4c0fb0SBarry Smith - ctx - the function context (or `NULL` if you don't want it) 51479b94acceSBarry Smith 514836851e7fSLois Curfman McInnes Level: advanced 514936851e7fSLois Curfman McInnes 5150f6dfbefdSBarry Smith Note: 5151dc4c0fb0SBarry Smith The vector `r` DOES NOT, in general, contain the current value of the `SNES` nonlinear function 515204edfde5SBarry Smith 51538434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetSolution()`, `SNESFunctionFn` 51549b94acceSBarry Smith @*/ 51558434afd1SBarry Smith PetscErrorCode SNESGetFunction(SNES snes, Vec *r, SNESFunctionFn **f, void **ctx) 5156d71ae5a4SJacob Faibussowitsch { 51576cab3a1bSJed Brown DM dm; 5158a63bb30eSJed Brown 51593a40ed3dSBarry Smith PetscFunctionBegin; 51600700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5161a63bb30eSJed Brown if (r) { 5162a63bb30eSJed Brown if (!snes->vec_func) { 5163a63bb30eSJed Brown if (snes->vec_rhs) { 51649566063dSJacob Faibussowitsch PetscCall(VecDuplicate(snes->vec_rhs, &snes->vec_func)); 5165a63bb30eSJed Brown } else if (snes->vec_sol) { 51669566063dSJacob Faibussowitsch PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_func)); 5167a63bb30eSJed Brown } else if (snes->dm) { 51689566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(snes->dm, &snes->vec_func)); 5169a63bb30eSJed Brown } 5170a63bb30eSJed Brown } 5171a63bb30eSJed Brown *r = snes->vec_func; 5172a63bb30eSJed Brown } 51739566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 51749566063dSJacob Faibussowitsch PetscCall(DMSNESGetFunction(dm, f, ctx)); 51753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 51769b94acceSBarry Smith } 51779b94acceSBarry Smith 5178c79ef259SPeter Brune /*@C 517937fdd005SBarry Smith SNESGetNGS - Returns the function and context set with `SNESSetNGS()` 5180c79ef259SPeter Brune 5181c79ef259SPeter Brune Input Parameter: 5182f6dfbefdSBarry Smith . snes - the `SNES` context 5183c79ef259SPeter Brune 5184d8d19677SJose E. Roman Output Parameters: 51858434afd1SBarry Smith + f - the function (or `NULL`) see `SNESNGSFn` for calling sequence 5186dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`) 5187c79ef259SPeter Brune 5188c79ef259SPeter Brune Level: advanced 5189c79ef259SPeter Brune 51908434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetNGS()`, `SNESGetFunction()`, `SNESNGSFn` 5191c79ef259SPeter Brune @*/ 51928434afd1SBarry Smith PetscErrorCode SNESGetNGS(SNES snes, SNESNGSFn **f, void **ctx) 5193d71ae5a4SJacob Faibussowitsch { 51946cab3a1bSJed Brown DM dm; 51956cab3a1bSJed Brown 5196646217ecSPeter Brune PetscFunctionBegin; 5197646217ecSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 51989566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 51999566063dSJacob Faibussowitsch PetscCall(DMSNESGetNGS(dm, f, ctx)); 52003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5201646217ecSPeter Brune } 5202646217ecSPeter Brune 5203cc4c1da9SBarry Smith /*@ 52043c7409f5SSatish Balay SNESSetOptionsPrefix - Sets the prefix used for searching for all 5205f6dfbefdSBarry Smith `SNES` options in the database. 52063c7409f5SSatish Balay 5207c3339decSBarry Smith Logically Collective 5208fee21e36SBarry Smith 5209d8d19677SJose E. Roman Input Parameters: 5210f6dfbefdSBarry Smith + snes - the `SNES` context 5211c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names 5212c7afd0dbSLois Curfman McInnes 5213dc4c0fb0SBarry Smith Level: advanced 5214dc4c0fb0SBarry Smith 5215f6dfbefdSBarry Smith Note: 5216a83b1b31SSatish Balay A hyphen (-) must NOT be given at the beginning of the prefix name. 5217c7afd0dbSLois Curfman McInnes The first character of all runtime options is AUTOMATICALLY the hyphen. 5218d850072dSLois Curfman McInnes 52191cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESAppendOptionsPrefix()` 52203c7409f5SSatish Balay @*/ 5221d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetOptionsPrefix(SNES snes, const char prefix[]) 5222d71ae5a4SJacob Faibussowitsch { 52233a40ed3dSBarry Smith PetscFunctionBegin; 52240700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 52259566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes, prefix)); 52269566063dSJacob Faibussowitsch if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 522735f5d045SPeter Brune if (snes->linesearch) { 52289566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 52299566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch, prefix)); 523035f5d045SPeter Brune } 52319566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(snes->ksp, prefix)); 52323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 52333c7409f5SSatish Balay } 52343c7409f5SSatish Balay 5235cc4c1da9SBarry Smith /*@ 5236f525115eSLois Curfman McInnes SNESAppendOptionsPrefix - Appends to the prefix used for searching for all 5237f6dfbefdSBarry Smith `SNES` options in the database. 52383c7409f5SSatish Balay 5239c3339decSBarry Smith Logically Collective 5240fee21e36SBarry Smith 5241c7afd0dbSLois Curfman McInnes Input Parameters: 5242f6dfbefdSBarry Smith + snes - the `SNES` context 5243c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names 5244c7afd0dbSLois Curfman McInnes 5245dc4c0fb0SBarry Smith Level: advanced 5246dc4c0fb0SBarry Smith 5247f6dfbefdSBarry Smith Note: 5248a83b1b31SSatish Balay A hyphen (-) must NOT be given at the beginning of the prefix name. 5249c7afd0dbSLois Curfman McInnes The first character of all runtime options is AUTOMATICALLY the hyphen. 5250d850072dSLois Curfman McInnes 52511cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetOptionsPrefix()`, `SNESSetOptionsPrefix()` 52523c7409f5SSatish Balay @*/ 5253d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESAppendOptionsPrefix(SNES snes, const char prefix[]) 5254d71ae5a4SJacob Faibussowitsch { 52553a40ed3dSBarry Smith PetscFunctionBegin; 52560700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 52579566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes, prefix)); 52589566063dSJacob Faibussowitsch if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 525935f5d045SPeter Brune if (snes->linesearch) { 52609566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 52619566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch, prefix)); 526235f5d045SPeter Brune } 52639566063dSJacob Faibussowitsch PetscCall(KSPAppendOptionsPrefix(snes->ksp, prefix)); 52643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 52653c7409f5SSatish Balay } 52663c7409f5SSatish Balay 5267cc4c1da9SBarry Smith /*@ 5268f6dfbefdSBarry Smith SNESGetOptionsPrefix - Gets the prefix used for searching for all 5269f6dfbefdSBarry Smith `SNES` options in the database. 52703c7409f5SSatish Balay 5271c7afd0dbSLois Curfman McInnes Not Collective 5272c7afd0dbSLois Curfman McInnes 52733c7409f5SSatish Balay Input Parameter: 5274f6dfbefdSBarry Smith . snes - the `SNES` context 52753c7409f5SSatish Balay 52763c7409f5SSatish Balay Output Parameter: 52773c7409f5SSatish Balay . prefix - pointer to the prefix string used 52783c7409f5SSatish Balay 527936851e7fSLois Curfman McInnes Level: advanced 528036851e7fSLois Curfman McInnes 52811cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetOptionsPrefix()`, `SNESAppendOptionsPrefix()` 52823c7409f5SSatish Balay @*/ 5283d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetOptionsPrefix(SNES snes, const char *prefix[]) 5284d71ae5a4SJacob Faibussowitsch { 52853a40ed3dSBarry Smith PetscFunctionBegin; 52860700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 52879566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)snes, prefix)); 52883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 52893c7409f5SSatish Balay } 52903c7409f5SSatish Balay 52913cea93caSBarry Smith /*@C 52921c84c290SBarry Smith SNESRegister - Adds a method to the nonlinear solver package. 52931c84c290SBarry Smith 529420f4b53cSBarry Smith Not Collective 52951c84c290SBarry Smith 52961c84c290SBarry Smith Input Parameters: 529720f4b53cSBarry Smith + sname - name of a new user-defined solver 529820f4b53cSBarry Smith - function - routine to create method context 52991c84c290SBarry Smith 5300dc4c0fb0SBarry Smith Level: advanced 5301dc4c0fb0SBarry Smith 5302f6dfbefdSBarry Smith Note: 5303f6dfbefdSBarry Smith `SNESRegister()` may be called multiple times to add several user-defined solvers. 53041c84c290SBarry Smith 5305e4094ef1SJacob Faibussowitsch Example Usage: 53061c84c290SBarry Smith .vb 5307bdf89e91SBarry Smith SNESRegister("my_solver", MySolverCreate); 53081c84c290SBarry Smith .ve 53091c84c290SBarry Smith 53101c84c290SBarry Smith Then, your solver can be chosen with the procedural interface via 5311b44f4de4SBarry Smith .vb 5312b44f4de4SBarry Smith SNESSetType(snes, "my_solver") 5313b44f4de4SBarry Smith .ve 53141c84c290SBarry Smith or at runtime via the option 5315b44f4de4SBarry Smith .vb 5316b44f4de4SBarry Smith -snes_type my_solver 5317b44f4de4SBarry Smith .ve 53181c84c290SBarry Smith 53191cc06b55SBarry Smith .seealso: [](ch_snes), `SNESRegisterAll()`, `SNESRegisterDestroy()` 53203cea93caSBarry Smith @*/ 5321d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESRegister(const char sname[], PetscErrorCode (*function)(SNES)) 5322d71ae5a4SJacob Faibussowitsch { 5323b2002411SLois Curfman McInnes PetscFunctionBegin; 53249566063dSJacob Faibussowitsch PetscCall(SNESInitializePackage()); 53259566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&SNESList, sname, function)); 53263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5327b2002411SLois Curfman McInnes } 5328da9b6338SBarry Smith 5329d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestLocalMin(SNES snes) 5330d71ae5a4SJacob Faibussowitsch { 533177431f27SBarry Smith PetscInt N, i, j; 5332da9b6338SBarry Smith Vec u, uh, fh; 5333da9b6338SBarry Smith PetscScalar value; 5334da9b6338SBarry Smith PetscReal norm; 5335da9b6338SBarry Smith 5336da9b6338SBarry Smith PetscFunctionBegin; 53379566063dSJacob Faibussowitsch PetscCall(SNESGetSolution(snes, &u)); 53389566063dSJacob Faibussowitsch PetscCall(VecDuplicate(u, &uh)); 53399566063dSJacob Faibussowitsch PetscCall(VecDuplicate(u, &fh)); 5340da9b6338SBarry Smith 5341da9b6338SBarry Smith /* currently only works for sequential */ 53429566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Testing FormFunction() for local min\n")); 53439566063dSJacob Faibussowitsch PetscCall(VecGetSize(u, &N)); 5344da9b6338SBarry Smith for (i = 0; i < N; i++) { 53459566063dSJacob Faibussowitsch PetscCall(VecCopy(u, uh)); 534663a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "i = %" PetscInt_FMT "\n", i)); 5347da9b6338SBarry Smith for (j = -10; j < 11; j++) { 53488b49ba18SBarry Smith value = PetscSign(j) * PetscExpReal(PetscAbs(j) - 10.0); 53499566063dSJacob Faibussowitsch PetscCall(VecSetValue(uh, i, value, ADD_VALUES)); 53509566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, uh, fh)); 53519566063dSJacob Faibussowitsch PetscCall(VecNorm(fh, NORM_2, &norm)); 535263a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), " j norm %" PetscInt_FMT " %18.16e\n", j, (double)norm)); 5353da9b6338SBarry Smith value = -value; 53549566063dSJacob Faibussowitsch PetscCall(VecSetValue(uh, i, value, ADD_VALUES)); 5355da9b6338SBarry Smith } 5356da9b6338SBarry Smith } 53579566063dSJacob Faibussowitsch PetscCall(VecDestroy(&uh)); 53589566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fh)); 53593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5360da9b6338SBarry Smith } 536171f87433Sdalcinl 536271f87433Sdalcinl /*@ 5363f6dfbefdSBarry Smith SNESKSPSetUseEW - Sets `SNES` to the use Eisenstat-Walker method for 536471f87433Sdalcinl computing relative tolerance for linear solvers within an inexact 536571f87433Sdalcinl Newton method. 536671f87433Sdalcinl 5367c3339decSBarry Smith Logically Collective 536871f87433Sdalcinl 536971f87433Sdalcinl Input Parameters: 5370f6dfbefdSBarry Smith + snes - `SNES` context 5371f6dfbefdSBarry Smith - flag - `PETSC_TRUE` or `PETSC_FALSE` 537271f87433Sdalcinl 5373f6dfbefdSBarry Smith Options Database Keys: 537464ba62caSBarry Smith + -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence 537564ba62caSBarry Smith . -snes_ksp_ew_version ver - version of Eisenstat-Walker method 537664ba62caSBarry Smith . -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0 537764ba62caSBarry Smith . -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax 537864ba62caSBarry Smith . -snes_ksp_ew_gamma <gamma> - Sets gamma 537964ba62caSBarry Smith . -snes_ksp_ew_alpha <alpha> - Sets alpha 538064ba62caSBarry Smith . -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2 538164ba62caSBarry Smith - -snes_ksp_ew_threshold <threshold> - Sets threshold 538264ba62caSBarry Smith 5383dc4c0fb0SBarry Smith Level: advanced 5384dc4c0fb0SBarry Smith 5385f6dfbefdSBarry Smith Note: 5386f6dfbefdSBarry Smith The default is to use a constant relative tolerance for 538771f87433Sdalcinl the inner linear solvers. Alternatively, one can use the 53881d27aa22SBarry Smith Eisenstat-Walker method {cite}`ew96`, where the relative convergence tolerance 538971f87433Sdalcinl is reset at each Newton iteration according progress of the nonlinear 539071f87433Sdalcinl solver. 539171f87433Sdalcinl 53921cc06b55SBarry Smith .seealso: [](ch_snes), `KSP`, `SNES`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()` 539371f87433Sdalcinl @*/ 5394d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetUseEW(SNES snes, PetscBool flag) 5395d71ae5a4SJacob Faibussowitsch { 539671f87433Sdalcinl PetscFunctionBegin; 53970700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5398acfcf0e5SJed Brown PetscValidLogicalCollectiveBool(snes, flag, 2); 539971f87433Sdalcinl snes->ksp_ewconv = flag; 54003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 540171f87433Sdalcinl } 540271f87433Sdalcinl 540371f87433Sdalcinl /*@ 5404f6dfbefdSBarry Smith SNESKSPGetUseEW - Gets if `SNES` is using Eisenstat-Walker method 540571f87433Sdalcinl for computing relative tolerance for linear solvers within an 540671f87433Sdalcinl inexact Newton method. 540771f87433Sdalcinl 540871f87433Sdalcinl Not Collective 540971f87433Sdalcinl 541071f87433Sdalcinl Input Parameter: 5411f6dfbefdSBarry Smith . snes - `SNES` context 541271f87433Sdalcinl 541371f87433Sdalcinl Output Parameter: 5414f6dfbefdSBarry Smith . flag - `PETSC_TRUE` or `PETSC_FALSE` 541571f87433Sdalcinl 541671f87433Sdalcinl Level: advanced 541771f87433Sdalcinl 54181cc06b55SBarry Smith .seealso: [](ch_snes), `SNESKSPSetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()` 541971f87433Sdalcinl @*/ 5420d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag) 5421d71ae5a4SJacob Faibussowitsch { 542271f87433Sdalcinl PetscFunctionBegin; 54230700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 54244f572ea9SToby Isaac PetscAssertPointer(flag, 2); 542571f87433Sdalcinl *flag = snes->ksp_ewconv; 54263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 542771f87433Sdalcinl } 542871f87433Sdalcinl 542971f87433Sdalcinl /*@ 5430fa9f3622SBarry Smith SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker 543171f87433Sdalcinl convergence criteria for the linear solvers within an inexact 543271f87433Sdalcinl Newton method. 543371f87433Sdalcinl 5434c3339decSBarry Smith Logically Collective 543571f87433Sdalcinl 543671f87433Sdalcinl Input Parameters: 5437f6dfbefdSBarry Smith + snes - `SNES` context 54380f0abf79SStefano Zampini . version - version 1, 2 (default is 2), 3 or 4 543971f87433Sdalcinl . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 544071f87433Sdalcinl . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 544171f87433Sdalcinl . gamma - multiplicative factor for version 2 rtol computation 544271f87433Sdalcinl (0 <= gamma2 <= 1) 544371f87433Sdalcinl . alpha - power for version 2 rtol computation (1 < alpha <= 2) 544471f87433Sdalcinl . alpha2 - power for safeguard 544571f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1) 544671f87433Sdalcinl 5447dc4c0fb0SBarry Smith Level: advanced 5448dc4c0fb0SBarry Smith 5449f6dfbefdSBarry Smith Notes: 545071f87433Sdalcinl Version 3 was contributed by Luis Chacon, June 2006. 545171f87433Sdalcinl 545277e5a1f9SBarry Smith Use `PETSC_CURRENT` to retain the default for any of the parameters. 545371f87433Sdalcinl 54541cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()` 545571f87433Sdalcinl @*/ 5456d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetParametersEW(SNES snes, PetscInt version, PetscReal rtol_0, PetscReal rtol_max, PetscReal gamma, PetscReal alpha, PetscReal alpha2, PetscReal threshold) 5457d71ae5a4SJacob Faibussowitsch { 5458fa9f3622SBarry Smith SNESKSPEW *kctx; 54595fd66863SKarl Rupp 546071f87433Sdalcinl PetscFunctionBegin; 54610700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5462fa9f3622SBarry Smith kctx = (SNESKSPEW *)snes->kspconvctx; 54635f80ce2aSJacob Faibussowitsch PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing"); 5464c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, version, 2); 5465c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, rtol_0, 3); 5466c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, rtol_max, 4); 5467c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, gamma, 5); 5468c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, alpha, 6); 5469c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, alpha2, 7); 5470c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, threshold, 8); 547171f87433Sdalcinl 547277e5a1f9SBarry Smith if (version != PETSC_CURRENT) kctx->version = version; 547377e5a1f9SBarry Smith if (rtol_0 != (PetscReal)PETSC_CURRENT) kctx->rtol_0 = rtol_0; 547477e5a1f9SBarry Smith if (rtol_max != (PetscReal)PETSC_CURRENT) kctx->rtol_max = rtol_max; 547577e5a1f9SBarry Smith if (gamma != (PetscReal)PETSC_CURRENT) kctx->gamma = gamma; 547677e5a1f9SBarry Smith if (alpha != (PetscReal)PETSC_CURRENT) kctx->alpha = alpha; 547777e5a1f9SBarry Smith if (alpha2 != (PetscReal)PETSC_CURRENT) kctx->alpha2 = alpha2; 547877e5a1f9SBarry Smith if (threshold != (PetscReal)PETSC_CURRENT) kctx->threshold = threshold; 547971f87433Sdalcinl 54800f0abf79SStefano 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); 54810b121fc5SBarry 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); 54820b121fc5SBarry 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); 54830b121fc5SBarry 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); 54840b121fc5SBarry 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); 54850b121fc5SBarry 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); 54863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 548771f87433Sdalcinl } 548871f87433Sdalcinl 548971f87433Sdalcinl /*@ 5490fa9f3622SBarry Smith SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker 549171f87433Sdalcinl convergence criteria for the linear solvers within an inexact 549271f87433Sdalcinl Newton method. 549371f87433Sdalcinl 549471f87433Sdalcinl Not Collective 549571f87433Sdalcinl 549697bb3fdcSJose E. Roman Input Parameter: 5497f6dfbefdSBarry Smith . snes - `SNES` context 549871f87433Sdalcinl 549971f87433Sdalcinl Output Parameters: 55000f0abf79SStefano Zampini + version - version 1, 2 (default is 2), 3 or 4 550171f87433Sdalcinl . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 550271f87433Sdalcinl . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 5503bf388a1fSBarry Smith . gamma - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1) 550471f87433Sdalcinl . alpha - power for version 2 rtol computation (1 < alpha <= 2) 550571f87433Sdalcinl . alpha2 - power for safeguard 550671f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1) 550771f87433Sdalcinl 550871f87433Sdalcinl Level: advanced 550971f87433Sdalcinl 55101cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPSetParametersEW()` 551171f87433Sdalcinl @*/ 5512d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetParametersEW(SNES snes, PetscInt *version, PetscReal *rtol_0, PetscReal *rtol_max, PetscReal *gamma, PetscReal *alpha, PetscReal *alpha2, PetscReal *threshold) 5513d71ae5a4SJacob Faibussowitsch { 5514fa9f3622SBarry Smith SNESKSPEW *kctx; 55155fd66863SKarl Rupp 551671f87433Sdalcinl PetscFunctionBegin; 55170700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5518fa9f3622SBarry Smith kctx = (SNESKSPEW *)snes->kspconvctx; 55195f80ce2aSJacob Faibussowitsch PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing"); 552071f87433Sdalcinl if (version) *version = kctx->version; 552171f87433Sdalcinl if (rtol_0) *rtol_0 = kctx->rtol_0; 552271f87433Sdalcinl if (rtol_max) *rtol_max = kctx->rtol_max; 552371f87433Sdalcinl if (gamma) *gamma = kctx->gamma; 552471f87433Sdalcinl if (alpha) *alpha = kctx->alpha; 552571f87433Sdalcinl if (alpha2) *alpha2 = kctx->alpha2; 552671f87433Sdalcinl if (threshold) *threshold = kctx->threshold; 55273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 552871f87433Sdalcinl } 552971f87433Sdalcinl 55305c0db29aSPierre Jolivet PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx) 5531d71ae5a4SJacob Faibussowitsch { 55325c0db29aSPierre Jolivet SNES snes = (SNES)ctx; 5533fa9f3622SBarry Smith SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx; 553477e5a1f9SBarry Smith PetscReal rtol = PETSC_CURRENT, stol; 553571f87433Sdalcinl 553671f87433Sdalcinl PetscFunctionBegin; 55373ba16761SJacob Faibussowitsch if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS); 553830058271SDmitry Karpeev if (!snes->iter) { 553930058271SDmitry Karpeev rtol = kctx->rtol_0; /* first time in, so use the original user rtol */ 55409566063dSJacob Faibussowitsch PetscCall(VecNorm(snes->vec_func, NORM_2, &kctx->norm_first)); 55410f0abf79SStefano Zampini } else { 55420fdf79fbSJacob 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); 554371f87433Sdalcinl if (kctx->version == 1) { 55440f0abf79SStefano Zampini rtol = PetscAbsReal(snes->norm - kctx->lresid_last) / kctx->norm_last; 554585ec1a3cSBarry Smith stol = PetscPowReal(kctx->rtol_last, kctx->alpha2); 554671f87433Sdalcinl if (stol > kctx->threshold) rtol = PetscMax(rtol, stol); 554771f87433Sdalcinl } else if (kctx->version == 2) { 554885ec1a3cSBarry Smith rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha); 554985ec1a3cSBarry Smith stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha); 555071f87433Sdalcinl if (stol > kctx->threshold) rtol = PetscMax(rtol, stol); 555171f87433Sdalcinl } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */ 555285ec1a3cSBarry Smith rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha); 555371f87433Sdalcinl /* safeguard: avoid sharp decrease of rtol */ 555485ec1a3cSBarry Smith stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha); 555571f87433Sdalcinl stol = PetscMax(rtol, stol); 555671f87433Sdalcinl rtol = PetscMin(kctx->rtol_0, stol); 555771f87433Sdalcinl /* safeguard: avoid oversolving */ 555830058271SDmitry Karpeev stol = kctx->gamma * (kctx->norm_first * snes->rtol) / snes->norm; 555971f87433Sdalcinl stol = PetscMax(rtol, stol); 556071f87433Sdalcinl rtol = PetscMin(kctx->rtol_0, stol); 55610fdf79fbSJacob Faibussowitsch } else /* if (kctx->version == 4) */ { 55620fdf79fbSJacob Faibussowitsch /* H.-B. An et al. Journal of Computational and Applied Mathematics 200 (2007) 47-60 */ 55630f0abf79SStefano Zampini PetscReal ared = PetscAbsReal(kctx->norm_last - snes->norm); 55640f0abf79SStefano Zampini PetscReal pred = PetscAbsReal(kctx->norm_last - kctx->lresid_last); 55650f0abf79SStefano Zampini PetscReal rk = ared / pred; 55660f0abf79SStefano Zampini if (rk < kctx->v4_p1) rtol = 1. - 2. * kctx->v4_p1; 55670f0abf79SStefano Zampini else if (rk < kctx->v4_p2) rtol = kctx->rtol_last; 55680f0abf79SStefano Zampini else if (rk < kctx->v4_p3) rtol = kctx->v4_m1 * kctx->rtol_last; 55690f0abf79SStefano Zampini else rtol = kctx->v4_m2 * kctx->rtol_last; 55700f0abf79SStefano Zampini 5571a4598233SStefano 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; 55720f0abf79SStefano Zampini kctx->rtol_last_2 = kctx->rtol_last; 55730f0abf79SStefano Zampini kctx->rk_last_2 = kctx->rk_last; 55740f0abf79SStefano Zampini kctx->rk_last = rk; 55750fdf79fbSJacob Faibussowitsch } 55760f0abf79SStefano Zampini } 55770f0abf79SStefano Zampini /* safeguard: avoid rtol greater than rtol_max */ 557871f87433Sdalcinl rtol = PetscMin(rtol, kctx->rtol_max); 557977e5a1f9SBarry Smith PetscCall(KSPSetTolerances(ksp, rtol, PETSC_CURRENT, PETSC_CURRENT, PETSC_CURRENT)); 558063a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "iter %" PetscInt_FMT ", Eisenstat-Walker (version %" PetscInt_FMT ") KSP rtol=%g\n", snes->iter, kctx->version, (double)rtol)); 55813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 558271f87433Sdalcinl } 558371f87433Sdalcinl 55845c0db29aSPierre Jolivet PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx) 5585d71ae5a4SJacob Faibussowitsch { 55865c0db29aSPierre Jolivet SNES snes = (SNES)ctx; 5587fa9f3622SBarry Smith SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx; 558871f87433Sdalcinl PCSide pcside; 558971f87433Sdalcinl Vec lres; 559071f87433Sdalcinl 559171f87433Sdalcinl PetscFunctionBegin; 55923ba16761SJacob Faibussowitsch if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS); 55939566063dSJacob Faibussowitsch PetscCall(KSPGetTolerances(ksp, &kctx->rtol_last, NULL, NULL, NULL)); 559471dbe336SPeter Brune kctx->norm_last = snes->norm; 55950f0abf79SStefano Zampini if (kctx->version == 1 || kctx->version == 4) { 55964f00ce20SMatthew G. Knepley PC pc; 55970f0abf79SStefano Zampini PetscBool getRes; 55984f00ce20SMatthew G. Knepley 55999566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksp, &pc)); 56000f0abf79SStefano Zampini PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &getRes)); 56010f0abf79SStefano Zampini if (!getRes) { 56020f0abf79SStefano Zampini KSPNormType normtype; 56030f0abf79SStefano Zampini 56040f0abf79SStefano Zampini PetscCall(KSPGetNormType(ksp, &normtype)); 56050f0abf79SStefano Zampini getRes = (PetscBool)(normtype == KSP_NORM_UNPRECONDITIONED); 56060f0abf79SStefano Zampini } 56079566063dSJacob Faibussowitsch PetscCall(KSPGetPCSide(ksp, &pcside)); 56080f0abf79SStefano Zampini if (pcside == PC_RIGHT || getRes) { /* KSP residual is true linear residual */ 56099566063dSJacob Faibussowitsch PetscCall(KSPGetResidualNorm(ksp, &kctx->lresid_last)); 561071f87433Sdalcinl } else { 561171f87433Sdalcinl /* KSP residual is preconditioned residual */ 561271f87433Sdalcinl /* compute true linear residual norm */ 56130f0abf79SStefano Zampini Mat J; 56140f0abf79SStefano Zampini PetscCall(KSPGetOperators(ksp, &J, NULL)); 56159566063dSJacob Faibussowitsch PetscCall(VecDuplicate(b, &lres)); 56160f0abf79SStefano Zampini PetscCall(MatMult(J, x, lres)); 56179566063dSJacob Faibussowitsch PetscCall(VecAYPX(lres, -1.0, b)); 56189566063dSJacob Faibussowitsch PetscCall(VecNorm(lres, NORM_2, &kctx->lresid_last)); 56199566063dSJacob Faibussowitsch PetscCall(VecDestroy(&lres)); 562071f87433Sdalcinl } 562171f87433Sdalcinl } 56223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 562371f87433Sdalcinl } 562471f87433Sdalcinl 5625d4211eb9SBarry Smith /*@ 5626f6dfbefdSBarry Smith SNESGetKSP - Returns the `KSP` context for a `SNES` solver. 5627d4211eb9SBarry Smith 5628420bcc1bSBarry Smith Not Collective, but if `snes` is parallel, then `ksp` is parallel 5629d4211eb9SBarry Smith 5630d4211eb9SBarry Smith Input Parameter: 5631f6dfbefdSBarry Smith . snes - the `SNES` context 5632d4211eb9SBarry Smith 5633d4211eb9SBarry Smith Output Parameter: 5634f6dfbefdSBarry Smith . ksp - the `KSP` context 5635d4211eb9SBarry Smith 5636dc4c0fb0SBarry Smith Level: beginner 5637dc4c0fb0SBarry Smith 5638d4211eb9SBarry Smith Notes: 5639f6dfbefdSBarry Smith The user can then directly manipulate the `KSP` context to set various 5640d4211eb9SBarry Smith options, etc. Likewise, the user can then extract and manipulate the 5641f6dfbefdSBarry Smith `PC` contexts as well. 5642f6dfbefdSBarry Smith 56430b4b7b1cSBarry 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. 5644d4211eb9SBarry Smith 56451cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSP`, `PC`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()` 5646d4211eb9SBarry Smith @*/ 5647d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetKSP(SNES snes, KSP *ksp) 5648d71ae5a4SJacob Faibussowitsch { 564971f87433Sdalcinl PetscFunctionBegin; 5650d4211eb9SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 56514f572ea9SToby Isaac PetscAssertPointer(ksp, 2); 5652d4211eb9SBarry Smith 5653d4211eb9SBarry Smith if (!snes->ksp) { 56549566063dSJacob Faibussowitsch PetscCall(KSPCreate(PetscObjectComm((PetscObject)snes), &snes->ksp)); 56559566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->ksp, (PetscObject)snes, 1)); 5656d4211eb9SBarry Smith 56575c0db29aSPierre Jolivet PetscCall(KSPSetPreSolve(snes->ksp, KSPPreSolve_SNESEW, snes)); 56585c0db29aSPierre Jolivet PetscCall(KSPSetPostSolve(snes->ksp, KSPPostSolve_SNESEW, snes)); 5659a5c2985bSBarry Smith 56609566063dSJacob Faibussowitsch PetscCall(KSPMonitorSetFromOptions(snes->ksp, "-snes_monitor_ksp", "snes_preconditioned_residual", snes)); 56619566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptions((PetscObject)snes->ksp, ((PetscObject)snes)->options)); 5662d4211eb9SBarry Smith } 5663d4211eb9SBarry Smith *ksp = snes->ksp; 56643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 566571f87433Sdalcinl } 56666c699258SBarry Smith 5667af0996ceSBarry Smith #include <petsc/private/dmimpl.h> 56686c699258SBarry Smith /*@ 56690b4b7b1cSBarry Smith SNESSetDM - Sets the `DM` that may be used by some `SNES` nonlinear solvers or their underlying preconditioners 56706c699258SBarry Smith 5671c3339decSBarry Smith Logically Collective 56726c699258SBarry Smith 56736c699258SBarry Smith Input Parameters: 56742a808120SBarry Smith + snes - the nonlinear solver context 5675420bcc1bSBarry Smith - dm - the `DM`, cannot be `NULL` 5676dc4c0fb0SBarry Smith 5677dc4c0fb0SBarry Smith Level: intermediate 56786c699258SBarry Smith 5679f6dfbefdSBarry Smith Note: 5680f6dfbefdSBarry Smith A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`, 5681f6dfbefdSBarry Smith even when not using interfaces like `DMSNESSetFunction()`. Use `DMClone()` to get a distinct `DM` when solving different 5682e03a659cSJed Brown problems using the same function space. 5683e03a659cSJed Brown 5684420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()` 56856c699258SBarry Smith @*/ 5686d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDM(SNES snes, DM dm) 5687d71ae5a4SJacob Faibussowitsch { 5688345fed2cSBarry Smith KSP ksp; 5689942e3340SBarry Smith DMSNES sdm; 56906c699258SBarry Smith 56916c699258SBarry Smith PetscFunctionBegin; 56920700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 56932a808120SBarry Smith PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 56949566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 5695942e3340SBarry Smith if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */ 569651f4b3c7SToby Isaac if (snes->dm->dmsnes && !dm->dmsnes) { 56979566063dSJacob Faibussowitsch PetscCall(DMCopyDMSNES(snes->dm, dm)); 56989566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(snes->dm, &sdm)); 5699f5af7f23SKarl Rupp if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */ 57006cab3a1bSJed Brown } 57019566063dSJacob Faibussowitsch PetscCall(DMCoarsenHookRemove(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes)); 57029566063dSJacob Faibussowitsch PetscCall(DMDestroy(&snes->dm)); 57036cab3a1bSJed Brown } 57046c699258SBarry Smith snes->dm = dm; 5705116d1032SJed Brown snes->dmAuto = PETSC_FALSE; 5706f5af7f23SKarl Rupp 57079566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 57089566063dSJacob Faibussowitsch PetscCall(KSPSetDM(ksp, dm)); 57099566063dSJacob Faibussowitsch PetscCall(KSPSetDMActive(ksp, PETSC_FALSE)); 5710efd4aadfSBarry Smith if (snes->npc) { 57119566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes->npc, snes->dm)); 57129566063dSJacob Faibussowitsch PetscCall(SNESSetNPCSide(snes, snes->npcside)); 57132c155ee1SBarry Smith } 57143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 57156c699258SBarry Smith } 57166c699258SBarry Smith 57176c699258SBarry Smith /*@ 57180b4b7b1cSBarry Smith SNESGetDM - Gets the `DM` that may be used by some `SNES` nonlinear solvers/preconditioners 57196c699258SBarry Smith 57200b4b7b1cSBarry Smith Not Collective but `dm` obtained is parallel on `snes` 57216c699258SBarry Smith 57226c699258SBarry Smith Input Parameter: 5723420bcc1bSBarry Smith . snes - the `SNES` context 57246c699258SBarry Smith 57256c699258SBarry Smith Output Parameter: 5726420bcc1bSBarry Smith . dm - the `DM` 57276c699258SBarry Smith 57286c699258SBarry Smith Level: intermediate 57296c699258SBarry Smith 5730420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESSetDM()`, `KSPSetDM()`, `KSPGetDM()` 57316c699258SBarry Smith @*/ 5732d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDM(SNES snes, DM *dm) 5733d71ae5a4SJacob Faibussowitsch { 57346c699258SBarry Smith PetscFunctionBegin; 57350700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 57366cab3a1bSJed Brown if (!snes->dm) { 57379566063dSJacob Faibussowitsch PetscCall(DMShellCreate(PetscObjectComm((PetscObject)snes), &snes->dm)); 5738116d1032SJed Brown snes->dmAuto = PETSC_TRUE; 57396cab3a1bSJed Brown } 57406c699258SBarry Smith *dm = snes->dm; 57413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 57426c699258SBarry Smith } 57430807856dSBarry Smith 574431823bd8SMatthew G Knepley /*@ 5745be95d8f1SBarry Smith SNESSetNPC - Sets the nonlinear preconditioner to be used. 574631823bd8SMatthew G Knepley 5747c3339decSBarry Smith Collective 574831823bd8SMatthew G Knepley 574931823bd8SMatthew G Knepley Input Parameters: 5750f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 575162842358SBarry Smith - npc - the `SNES` nonlinear preconditioner object 575262842358SBarry Smith 575362842358SBarry Smith Options Database Key: 575462842358SBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner 575531823bd8SMatthew G Knepley 5756dc4c0fb0SBarry Smith Level: developer 5757dc4c0fb0SBarry Smith 575831823bd8SMatthew G Knepley Notes: 575962842358SBarry Smith This is rarely used, rather use `SNESGetNPC()` to retrieve the preconditioner and configure it using the API. 576031823bd8SMatthew G Knepley 5761f6dfbefdSBarry Smith Only some `SNESType` can use a nonlinear preconditioner 5762f6dfbefdSBarry Smith 5763420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNGS`, `SNESFAS`, `SNESGetNPC()`, `SNESHasNPC()` 576431823bd8SMatthew G Knepley @*/ 5765d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPC(SNES snes, SNES npc) 5766d71ae5a4SJacob Faibussowitsch { 576731823bd8SMatthew G Knepley PetscFunctionBegin; 576831823bd8SMatthew G Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5769f6dfbefdSBarry Smith PetscValidHeaderSpecific(npc, SNES_CLASSID, 2); 5770f6dfbefdSBarry Smith PetscCheckSameComm(snes, 1, npc, 2); 5771f6dfbefdSBarry Smith PetscCall(PetscObjectReference((PetscObject)npc)); 57729566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&snes->npc)); 5773f6dfbefdSBarry Smith snes->npc = npc; 57743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 577531823bd8SMatthew G Knepley } 577631823bd8SMatthew G Knepley 577731823bd8SMatthew G Knepley /*@ 5778f6dfbefdSBarry Smith SNESGetNPC - Gets a nonlinear preconditioning solver SNES` to be used to precondition the original nonlinear solver. 577931823bd8SMatthew G Knepley 57800b4b7b1cSBarry Smith Not Collective; but any changes to the obtained the `pc` object must be applied collectively 578131823bd8SMatthew G Knepley 578231823bd8SMatthew G Knepley Input Parameter: 5783f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 578431823bd8SMatthew G Knepley 578531823bd8SMatthew G Knepley Output Parameter: 578662842358SBarry Smith . pc - the `SNES` preconditioner context 578731823bd8SMatthew G Knepley 5788f6dfbefdSBarry Smith Options Database Key: 5789f6dfbefdSBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner 5790b5badacbSBarry Smith 57910b4b7b1cSBarry Smith Level: advanced 5792dc4c0fb0SBarry Smith 579395452b02SPatrick Sanan Notes: 57940b4b7b1cSBarry Smith If a `SNES` was previously set with `SNESSetNPC()` then that value is returned, otherwise a new `SNES` object is created that will 57950b4b7b1cSBarry Smith be used as the nonlinear preconditioner for the current `SNES`. 5796be95d8f1SBarry Smith 5797f6dfbefdSBarry Smith The (preconditioner) `SNES` returned automatically inherits the same nonlinear function and Jacobian supplied to the original 579862842358SBarry Smith `SNES`. These may be overwritten if needed. 579962842358SBarry Smith 580062842358SBarry Smith Use the options database prefixes `-npc_snes`, `-npc_ksp`, etc., to control the configuration of the nonlinear preconditioner 5801951fe5abSBarry Smith 58021cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESHasNPC()`, `SNES`, `SNESCreate()` 580331823bd8SMatthew G Knepley @*/ 5804d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPC(SNES snes, SNES *pc) 5805d71ae5a4SJacob Faibussowitsch { 5806a64e098fSPeter Brune const char *optionsprefix; 580731823bd8SMatthew G Knepley 580831823bd8SMatthew G Knepley PetscFunctionBegin; 580931823bd8SMatthew G Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 58104f572ea9SToby Isaac PetscAssertPointer(pc, 2); 5811efd4aadfSBarry Smith if (!snes->npc) { 5812ec785e5bSStefano Zampini void *ctx; 5813ec785e5bSStefano Zampini 58149566063dSJacob Faibussowitsch PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &snes->npc)); 58159566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->npc, (PetscObject)snes, 1)); 58169566063dSJacob Faibussowitsch PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 58179566063dSJacob Faibussowitsch PetscCall(SNESSetOptionsPrefix(snes->npc, optionsprefix)); 58189566063dSJacob Faibussowitsch PetscCall(SNESAppendOptionsPrefix(snes->npc, "npc_")); 5819fb87a551SStefano Zampini if (snes->ops->usercompute) { 582049abdd8aSBarry Smith PetscCall(SNESSetComputeApplicationContext(snes, snes->ops->usercompute, snes->ops->ctxdestroy)); 5821fb87a551SStefano Zampini } else { 5822ec785e5bSStefano Zampini PetscCall(SNESGetApplicationContext(snes, &ctx)); 5823ec785e5bSStefano Zampini PetscCall(SNESSetApplicationContext(snes->npc, ctx)); 5824fb87a551SStefano Zampini } 58259566063dSJacob Faibussowitsch PetscCall(SNESSetCountersReset(snes->npc, PETSC_FALSE)); 582631823bd8SMatthew G Knepley } 5827efd4aadfSBarry Smith *pc = snes->npc; 58283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 582931823bd8SMatthew G Knepley } 583031823bd8SMatthew G Knepley 58313ad1a0b9SPatrick Farrell /*@ 58320b4b7b1cSBarry Smith SNESHasNPC - Returns whether a nonlinear preconditioner is associated with the given `SNES` 58333ad1a0b9SPatrick Farrell 58343ad1a0b9SPatrick Farrell Not Collective 58353ad1a0b9SPatrick Farrell 58363ad1a0b9SPatrick Farrell Input Parameter: 5837f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 58383ad1a0b9SPatrick Farrell 58393ad1a0b9SPatrick Farrell Output Parameter: 5840420bcc1bSBarry Smith . has_npc - whether the `SNES` has a nonlinear preconditioner or not 58413ad1a0b9SPatrick Farrell 58423ad1a0b9SPatrick Farrell Level: developer 58433ad1a0b9SPatrick Farrell 58441cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESGetNPC()` 58453ad1a0b9SPatrick Farrell @*/ 5846d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc) 5847d71ae5a4SJacob Faibussowitsch { 58483ad1a0b9SPatrick Farrell PetscFunctionBegin; 58493ad1a0b9SPatrick Farrell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5850835f2295SStefano Zampini PetscAssertPointer(has_npc, 2); 5851835f2295SStefano Zampini *has_npc = snes->npc ? PETSC_TRUE : PETSC_FALSE; 58523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 58533ad1a0b9SPatrick Farrell } 58543ad1a0b9SPatrick Farrell 5855c40d0f55SPeter Brune /*@ 585662842358SBarry Smith SNESSetNPCSide - Sets the nonlinear preconditioning side used by the nonlinear preconditioner inside `SNES`. 5857c40d0f55SPeter Brune 5858c3339decSBarry Smith Logically Collective 5859c40d0f55SPeter Brune 5860c40d0f55SPeter Brune Input Parameter: 5861f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 5862c40d0f55SPeter Brune 5863c40d0f55SPeter Brune Output Parameter: 5864c40d0f55SPeter Brune . side - the preconditioning side, where side is one of 5865c40d0f55SPeter Brune .vb 58662d547940SBarry Smith PC_LEFT - left preconditioning 58672d547940SBarry Smith PC_RIGHT - right preconditioning (default for most nonlinear solvers) 5868c40d0f55SPeter Brune .ve 5869c40d0f55SPeter Brune 5870f6dfbefdSBarry Smith Options Database Key: 587167b8a455SSatish Balay . -snes_npc_side <right,left> - nonlinear preconditioner side 5872c40d0f55SPeter Brune 5873dc4c0fb0SBarry Smith Level: intermediate 5874dc4c0fb0SBarry Smith 5875f6dfbefdSBarry Smith Note: 5876f6dfbefdSBarry Smith `SNESNRICHARDSON` and `SNESNCG` only support left preconditioning. 58772d547940SBarry Smith 587862842358SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNPC()`, `SNESNRICHARDSON`, `SNESNCG`, `SNESType`, `SNESGetNPCSide()`, `KSPSetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide` 5879c40d0f55SPeter Brune @*/ 5880d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPCSide(SNES snes, PCSide side) 5881d71ae5a4SJacob Faibussowitsch { 5882c40d0f55SPeter Brune PetscFunctionBegin; 5883c40d0f55SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5884c40d0f55SPeter Brune PetscValidLogicalCollectiveEnum(snes, side, 2); 5885b552625fSStefano Zampini if (side == PC_SIDE_DEFAULT) side = PC_RIGHT; 588654c59aa7SJacob Faibussowitsch PetscCheck((side == PC_LEFT) || (side == PC_RIGHT), PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Only PC_LEFT and PC_RIGHT are supported"); 5887efd4aadfSBarry Smith snes->npcside = side; 58883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5889c40d0f55SPeter Brune } 5890c40d0f55SPeter Brune 5891c40d0f55SPeter Brune /*@ 589262842358SBarry Smith SNESGetNPCSide - Gets the preconditioning side used by the nonlinear preconditioner inside `SNES`. 5893c40d0f55SPeter Brune 5894c40d0f55SPeter Brune Not Collective 5895c40d0f55SPeter Brune 5896c40d0f55SPeter Brune Input Parameter: 5897f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 5898c40d0f55SPeter Brune 5899c40d0f55SPeter Brune Output Parameter: 5900c40d0f55SPeter Brune . side - the preconditioning side, where side is one of 5901c40d0f55SPeter Brune .vb 5902f6dfbefdSBarry Smith `PC_LEFT` - left preconditioning 5903f6dfbefdSBarry Smith `PC_RIGHT` - right preconditioning (default for most nonlinear solvers) 5904c40d0f55SPeter Brune .ve 5905c40d0f55SPeter Brune 5906c40d0f55SPeter Brune Level: intermediate 5907c40d0f55SPeter Brune 590862842358SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNPC()`, `SNESSetNPCSide()`, `KSPGetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide` 5909c40d0f55SPeter Brune @*/ 5910d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPCSide(SNES snes, PCSide *side) 5911d71ae5a4SJacob Faibussowitsch { 5912c40d0f55SPeter Brune PetscFunctionBegin; 5913c40d0f55SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 59144f572ea9SToby Isaac PetscAssertPointer(side, 2); 5915efd4aadfSBarry Smith *side = snes->npcside; 59163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5917c40d0f55SPeter Brune } 5918c40d0f55SPeter Brune 59199e764e56SPeter Brune /*@ 59200b4b7b1cSBarry Smith SNESSetLineSearch - Sets the `SNESLineSearch` to be used for a given `SNES` 59219e764e56SPeter Brune 5922c3339decSBarry Smith Collective 59239e764e56SPeter Brune 59249e764e56SPeter Brune Input Parameters: 5925f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 59269e764e56SPeter Brune - linesearch - the linesearch object 59279e764e56SPeter Brune 5928dc4c0fb0SBarry Smith Level: developer 5929dc4c0fb0SBarry Smith 5930f6dfbefdSBarry Smith Note: 5931420bcc1bSBarry Smith This is almost never used, rather one uses `SNESGetLineSearch()` to retrieve the line search and set options on it 59329e764e56SPeter Brune to configure it using the API). 59339e764e56SPeter Brune 5934420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()` 59359e764e56SPeter Brune @*/ 5936d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch) 5937d71ae5a4SJacob Faibussowitsch { 59389e764e56SPeter Brune PetscFunctionBegin; 59399e764e56SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5940f1c6b773SPeter Brune PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 2); 59419e764e56SPeter Brune PetscCheckSameComm(snes, 1, linesearch, 2); 59429566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)linesearch)); 59439566063dSJacob Faibussowitsch PetscCall(SNESLineSearchDestroy(&snes->linesearch)); 5944f5af7f23SKarl Rupp 59459e764e56SPeter Brune snes->linesearch = linesearch; 59463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 59479e764e56SPeter Brune } 59489e764e56SPeter Brune 5949a34ceb2aSJed Brown /*@ 595062842358SBarry Smith SNESGetLineSearch - Returns the line search associated with the `SNES`. 59519e764e56SPeter Brune 59529e764e56SPeter Brune Not Collective 59539e764e56SPeter Brune 59549e764e56SPeter Brune Input Parameter: 5955f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 59569e764e56SPeter Brune 59579e764e56SPeter Brune Output Parameter: 59589e764e56SPeter Brune . linesearch - linesearch context 59599e764e56SPeter Brune 5960162e0bf5SPeter Brune Level: beginner 59619e764e56SPeter Brune 596262842358SBarry Smith Notes: 596362842358SBarry Smith It creates a default line search instance which can be configured as needed in case it has not been already set with `SNESSetLineSearch()`. 596462842358SBarry Smith 596562842358SBarry Smith You can also use the options database keys `-snes_linesearch_*` to configure the line search. See `SNESLineSearchSetFromOptions()` for the possible options. 596662842358SBarry Smith 596762842358SBarry Smith .seealso: [](ch_snes), `SNESLineSearch`, `SNESSetLineSearch()`, `SNESLineSearchCreate()`, `SNESLineSearchSetFromOptions()` 59689e764e56SPeter Brune @*/ 5969d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch) 5970d71ae5a4SJacob Faibussowitsch { 59719e764e56SPeter Brune const char *optionsprefix; 59729e764e56SPeter Brune 59739e764e56SPeter Brune PetscFunctionBegin; 59749e764e56SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 59754f572ea9SToby Isaac PetscAssertPointer(linesearch, 2); 59769e764e56SPeter Brune if (!snes->linesearch) { 59779566063dSJacob Faibussowitsch PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 59789566063dSJacob Faibussowitsch PetscCall(SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch)); 59799566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetSNES(snes->linesearch, snes)); 59809566063dSJacob Faibussowitsch PetscCall(SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix)); 59819566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->linesearch, (PetscObject)snes, 1)); 59829e764e56SPeter Brune } 59839e764e56SPeter Brune *linesearch = snes->linesearch; 59843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 59859e764e56SPeter Brune } 5986