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); 1505f80ce2aSJacob Faibussowitsch PetscCheck(!snes->errorifnotconverged, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "User code indicates input vector is not in the function domain"); 1514936397dSBarry Smith snes->domainerror = PETSC_TRUE; 1523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1534936397dSBarry Smith } 1544936397dSBarry Smith 1556a388c36SPeter Brune /*@ 156f6dfbefdSBarry Smith SNESSetJacobianDomainError - tells `SNES` that the function you provided to `SNESSetJacobian()` at the proposed step. For example there is a negative element transformation. 15707b62357SFande Kong 158c3339decSBarry Smith Logically Collective 15907b62357SFande Kong 1602fe279fdSBarry Smith Input Parameter: 161f6dfbefdSBarry Smith . snes - the `SNES` context 16207b62357SFande Kong 16307b62357SFande Kong Level: advanced 16407b62357SFande Kong 165ced0f3aeSBarry Smith Notes: 166ced0f3aeSBarry Smith If this is called the `SNESSolve()` stops iterating and returns with a `SNESConvergedReason` of `SNES_DIVERGED_FUNCTION_DOMAIN` 167ced0f3aeSBarry Smith 168ced0f3aeSBarry Smith You should always call `SNESGetConvergedReason()` after each `SNESSolve()` and verify if the iteration converged (positive result) or diverged (negative result). 169ced0f3aeSBarry Smith 170f0b84518SBarry Smith You can direct `SNES` to avoid certain steps by using `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()` or 171f0b84518SBarry Smith `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()` 172f0b84518SBarry Smith 1738434afd1SBarry Smith .seealso: [](ch_snes), `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetFunctionDomainError()`, `SNESVISetVariableBounds()`, 174ced0f3aeSBarry Smith `SNESVISetComputeVariableBounds()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESConvergedReason`, `SNESGetConvergedReason()` 17507b62357SFande Kong @*/ 176d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetJacobianDomainError(SNES snes) 177d71ae5a4SJacob Faibussowitsch { 17807b62357SFande Kong PetscFunctionBegin; 17907b62357SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1805f80ce2aSJacob Faibussowitsch PetscCheck(!snes->errorifnotconverged, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "User code indicates computeJacobian does not make sense"); 18107b62357SFande Kong snes->jacobiandomainerror = PETSC_TRUE; 1823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18307b62357SFande Kong } 18407b62357SFande Kong 18507b62357SFande Kong /*@ 186f6dfbefdSBarry Smith SNESSetCheckJacobianDomainError - tells `SNESSolve()` whether to check if the user called `SNESSetJacobianDomainError()` Jacobian domain error after 187420bcc1bSBarry 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. 188b351a90bSFande Kong 189c3339decSBarry Smith Logically Collective 190b351a90bSFande Kong 191b351a90bSFande Kong Input Parameters: 19220f4b53cSBarry Smith + snes - the `SNES` context 193f6dfbefdSBarry Smith - flg - indicates if or not to check Jacobian domain error after each Jacobian evaluation 194b351a90bSFande Kong 195b351a90bSFande Kong Level: advanced 196b351a90bSFande Kong 197f6dfbefdSBarry Smith Note: 198f6dfbefdSBarry Smith Checks require one extra parallel synchronization for each Jacobian evaluation 199f6dfbefdSBarry Smith 2008434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetFunctionDomainError()`, `SNESGetCheckJacobianDomainError()` 201b351a90bSFande Kong @*/ 202d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCheckJacobianDomainError(SNES snes, PetscBool flg) 203d71ae5a4SJacob Faibussowitsch { 204b351a90bSFande Kong PetscFunctionBegin; 205b351a90bSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 206b351a90bSFande Kong snes->checkjacdomainerror = flg; 2073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 208b351a90bSFande Kong } 209b351a90bSFande Kong 210b351a90bSFande Kong /*@ 211420bcc1bSBarry Smith SNESGetCheckJacobianDomainError - Get an indicator whether or not `SNES` is checking Jacobian domain errors after each Jacobian evaluation. 2128383d7d7SFande Kong 213c3339decSBarry Smith Logically Collective 2148383d7d7SFande Kong 2152fe279fdSBarry Smith Input Parameter: 216f6dfbefdSBarry Smith . snes - the `SNES` context 2178383d7d7SFande Kong 2182fe279fdSBarry Smith Output Parameter: 219420bcc1bSBarry Smith . flg - `PETSC_FALSE` indicates that it is not checking Jacobian domain errors after each Jacobian evaluation 2208383d7d7SFande Kong 2218383d7d7SFande Kong Level: advanced 2228383d7d7SFande Kong 2238434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetFunctionDomainError()`, `SNESSetCheckJacobianDomainError()` 2248383d7d7SFande Kong @*/ 225d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetCheckJacobianDomainError(SNES snes, PetscBool *flg) 226d71ae5a4SJacob Faibussowitsch { 2278383d7d7SFande Kong PetscFunctionBegin; 2288383d7d7SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2294f572ea9SToby Isaac PetscAssertPointer(flg, 2); 2308383d7d7SFande Kong *flg = snes->checkjacdomainerror; 2313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2328383d7d7SFande Kong } 2338383d7d7SFande Kong 2348383d7d7SFande Kong /*@ 235420bcc1bSBarry Smith SNESGetFunctionDomainError - Gets the status of the domain error after a call to `SNESComputeFunction()` 2366a388c36SPeter Brune 2376b1535e8SBarry Smith Not Collective, different MPI processes may return different values 2386a388c36SPeter Brune 2392fe279fdSBarry Smith Input Parameter: 240f6dfbefdSBarry Smith . snes - the `SNES` context 2416a388c36SPeter Brune 2422fe279fdSBarry Smith Output Parameter: 243f6dfbefdSBarry Smith . domainerror - Set to `PETSC_TRUE` if there's a domain error; `PETSC_FALSE` otherwise. 2446a388c36SPeter Brune 245f6dfbefdSBarry Smith Level: developer 2466a388c36SPeter Brune 2476b1535e8SBarry Smith Notes: 2486b1535e8SBarry Smith The value will only be true on those MPI processes that called `SNESSetFunctionDomainError()` 2496b1535e8SBarry Smith 2506b1535e8SBarry Smith The value is reset to `PETSC_FALSE` when `SNESCheckFunctionNorm()` is called. 2516b1535e8SBarry Smith 2521cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunctionDomainError()`, `SNESComputeFunction()` 2536a388c36SPeter Brune @*/ 254d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionDomainError(SNES snes, PetscBool *domainerror) 255d71ae5a4SJacob Faibussowitsch { 2566a388c36SPeter Brune PetscFunctionBegin; 2576a388c36SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2584f572ea9SToby Isaac PetscAssertPointer(domainerror, 2); 2596a388c36SPeter Brune *domainerror = snes->domainerror; 2603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2616a388c36SPeter Brune } 2626a388c36SPeter Brune 26307b62357SFande Kong /*@ 264420bcc1bSBarry Smith SNESGetJacobianDomainError - Gets the status of the Jacobian domain error after a call to `SNESComputeJacobian()` 26507b62357SFande Kong 2666b1535e8SBarry Smith Not Collective, different MPI processes may return different values 26707b62357SFande Kong 2682fe279fdSBarry Smith Input Parameter: 269f6dfbefdSBarry Smith . snes - the `SNES` context 27007b62357SFande Kong 2712fe279fdSBarry Smith Output Parameter: 272f6dfbefdSBarry Smith . domainerror - Set to `PETSC_TRUE` if there's a Jacobian domain error; `PETSC_FALSE` otherwise. 27307b62357SFande Kong 27407b62357SFande Kong Level: advanced 27507b62357SFande Kong 2766b1535e8SBarry Smith Notes: 2776b1535e8SBarry Smith The value will only be true on those MPI processes that called `SNESSetJacobianDomainError()` 2786b1535e8SBarry Smith 2796b1535e8SBarry Smith The value is reset to `PETSC_FALSE` when `SNESCheckJacobianDomainerror()` is called but only `SNESSetCheckJacobianDomainError()` was called 2806b1535e8SBarry Smith 2811cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunctionDomainError()`, `SNESComputeFunction()`, `SNESGetFunctionDomainError()` 28207b62357SFande Kong @*/ 283d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetJacobianDomainError(SNES snes, PetscBool *domainerror) 284d71ae5a4SJacob Faibussowitsch { 28507b62357SFande Kong PetscFunctionBegin; 28607b62357SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2874f572ea9SToby Isaac PetscAssertPointer(domainerror, 2); 28807b62357SFande Kong *domainerror = snes->jacobiandomainerror; 2893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 29007b62357SFande Kong } 29107b62357SFande Kong 292ffeef943SBarry Smith /*@ 293f6dfbefdSBarry Smith SNESLoad - Loads a `SNES` that has been stored in `PETSCVIEWERBINARY` with `SNESView()`. 29455849f57SBarry Smith 295c3339decSBarry Smith Collective 29655849f57SBarry Smith 29755849f57SBarry Smith Input Parameters: 298e4094ef1SJacob Faibussowitsch + snes - the newly loaded `SNES`, this needs to have been created with `SNESCreate()` or 299f6dfbefdSBarry Smith some related function before a call to `SNESLoad()`. 300f6dfbefdSBarry Smith - viewer - binary file viewer, obtained from `PetscViewerBinaryOpen()` 30155849f57SBarry Smith 30255849f57SBarry Smith Level: intermediate 30355849f57SBarry Smith 304f6dfbefdSBarry Smith Note: 305420bcc1bSBarry Smith The `SNESType` is determined by the data in the file, any type set into the `SNES` before this call is ignored. 30655849f57SBarry Smith 3071cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `PetscViewer`, `SNESCreate()`, `SNESType`, `PetscViewerBinaryOpen()`, `SNESView()`, `MatLoad()`, `VecLoad()` 30855849f57SBarry Smith @*/ 309d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESLoad(SNES snes, PetscViewer viewer) 310d71ae5a4SJacob Faibussowitsch { 31155849f57SBarry Smith PetscBool isbinary; 312060da220SMatthew G. Knepley PetscInt classid; 31355849f57SBarry Smith char type[256]; 31455849f57SBarry Smith KSP ksp; 3152d53ad75SBarry Smith DM dm; 3162d53ad75SBarry Smith DMSNES dmsnes; 31755849f57SBarry Smith 31855849f57SBarry Smith PetscFunctionBegin; 3192d53ad75SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 32055849f57SBarry Smith PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 3219566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 3225f80ce2aSJacob Faibussowitsch PetscCheck(isbinary, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerBinaryOpen()"); 32355849f57SBarry Smith 3249566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer, &classid, 1, NULL, PETSC_INT)); 3255f80ce2aSJacob Faibussowitsch PetscCheck(classid == SNES_FILE_CLASSID, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Not SNES next in file"); 3269566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer, type, 256, NULL, PETSC_CHAR)); 3279566063dSJacob Faibussowitsch PetscCall(SNESSetType(snes, type)); 328dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, load, viewer); 3299566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 3309566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &dmsnes)); 3319566063dSJacob Faibussowitsch PetscCall(DMSNESLoad(dmsnes, viewer)); 3329566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 3339566063dSJacob Faibussowitsch PetscCall(KSPLoad(ksp, viewer)); 3343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 33555849f57SBarry Smith } 3366a388c36SPeter Brune 3379804daf3SBarry Smith #include <petscdraw.h> 338e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS) 339e04113cfSBarry Smith #include <petscviewersaws.h> 340bfb97211SBarry Smith #endif 3418404b7f3SBarry Smith 342ffeef943SBarry Smith /*@ 343dc4c0fb0SBarry Smith SNESViewFromOptions - View a `SNES` based on values in the options database 344fe2efc57SMark 345c3339decSBarry Smith Collective 346fe2efc57SMark 347fe2efc57SMark Input Parameters: 348f6dfbefdSBarry Smith + A - the `SNES` context 349dc4c0fb0SBarry Smith . obj - Optional object that provides the options prefix for the checks 350736c3998SJose E. Roman - name - command line option 351fe2efc57SMark 352fe2efc57SMark Level: intermediate 353f6dfbefdSBarry Smith 3541cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESView`, `PetscObjectViewFromOptions()`, `SNESCreate()` 355fe2efc57SMark @*/ 356d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESViewFromOptions(SNES A, PetscObject obj, const char name[]) 357d71ae5a4SJacob Faibussowitsch { 358fe2efc57SMark PetscFunctionBegin; 359fe2efc57SMark PetscValidHeaderSpecific(A, SNES_CLASSID, 1); 3609566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 3613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 362fe2efc57SMark } 363fe2efc57SMark 364789d8953SBarry Smith PETSC_EXTERN PetscErrorCode SNESComputeJacobian_DMDA(SNES, Vec, Mat, Mat, void *); 365789d8953SBarry Smith 366ffeef943SBarry Smith /*@ 367dc4c0fb0SBarry Smith SNESView - Prints or visualizes the `SNES` data structure. 3689b94acceSBarry Smith 369c3339decSBarry Smith Collective 370fee21e36SBarry Smith 371c7afd0dbSLois Curfman McInnes Input Parameters: 372f6dfbefdSBarry Smith + snes - the `SNES` context 373f6dfbefdSBarry Smith - viewer - the `PetscViewer` 374c7afd0dbSLois Curfman McInnes 3759b94acceSBarry Smith Options Database Key: 376f6dfbefdSBarry Smith . -snes_view - Calls `SNESView()` at end of `SNESSolve()` 3779b94acceSBarry Smith 378dc4c0fb0SBarry Smith Level: beginner 379dc4c0fb0SBarry Smith 3809b94acceSBarry Smith Notes: 3819b94acceSBarry Smith The available visualization contexts include 382f6dfbefdSBarry Smith + `PETSC_VIEWER_STDOUT_SELF` - standard output (default) 383f6dfbefdSBarry Smith - `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard 384c8a8ba5cSLois Curfman McInnes output where only the first processor opens 385c8a8ba5cSLois Curfman McInnes the file. All other processors send their 386c8a8ba5cSLois Curfman McInnes data to the first processor to print. 3879b94acceSBarry Smith 388052bf0daSPierre Jolivet The available formats include 389f6dfbefdSBarry Smith + `PETSC_VIEWER_DEFAULT` - standard output (default) 390f6dfbefdSBarry Smith - `PETSC_VIEWER_ASCII_INFO_DETAIL` - more verbose output for `SNESNASM` 391052bf0daSPierre Jolivet 3923e081fefSLois Curfman McInnes The user can open an alternative visualization context with 393f6dfbefdSBarry Smith `PetscViewerASCIIOpen()` - output to a specified file. 3949b94acceSBarry Smith 395f6dfbefdSBarry Smith In the debugger you can do "call `SNESView`(snes,0)" to display the `SNES` solver. (The same holds for any PETSc object viewer). 396595c91d4SBarry Smith 3971cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESLoad()`, `SNESCreate()`, `PetscViewerASCIIOpen()` 3989b94acceSBarry Smith @*/ 399d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESView(SNES snes, PetscViewer viewer) 400d71ae5a4SJacob Faibussowitsch { 401fa9f3622SBarry Smith SNESKSPEW *kctx; 40294b7f48cSBarry Smith KSP ksp; 4037f1410a3SPeter Brune SNESLineSearch linesearch; 4049f196a02SMartin Diehl PetscBool isascii, isstring, isbinary, isdraw; 4052d53ad75SBarry Smith DMSNES dmsnes; 406e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS) 407536b137fSBarry Smith PetscBool issaws; 408bfb97211SBarry Smith #endif 4099b94acceSBarry Smith 4103a40ed3dSBarry Smith PetscFunctionBegin; 4110700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 41248a46eb9SPierre Jolivet if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &viewer)); 4130700a824SBarry Smith PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 414c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, viewer, 2); 41574679c65SBarry Smith 4169f196a02SMartin Diehl PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 4179566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 4189566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 4199566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 420e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS) 4219566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 422bfb97211SBarry Smith #endif 4239f196a02SMartin Diehl if (isascii) { 424dc0571f2SMatthew G. Knepley SNESNormSchedule normschedule; 4258404b7f3SBarry Smith DM dm; 4268434afd1SBarry Smith SNESJacobianFn *cJ; 4278404b7f3SBarry Smith void *ctx; 428789d8953SBarry Smith const char *pre = ""; 429dc0571f2SMatthew G. Knepley 4309566063dSJacob Faibussowitsch PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)snes, viewer)); 43148a46eb9SPierre Jolivet if (!snes->setupcalled) PetscCall(PetscViewerASCIIPrintf(viewer, " SNES has not been set up so information may be incomplete\n")); 432e7788613SBarry Smith if (snes->ops->view) { 4339566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 434dbbe0bcdSBarry Smith PetscUseTypeMethod(snes, view, viewer); 4359566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 4360ef38995SBarry Smith } 43777e5a1f9SBarry Smith if (snes->max_funcs == PETSC_UNLIMITED) { 43877e5a1f9SBarry Smith PetscCall(PetscViewerASCIIPrintf(viewer, " maximum iterations=%" PetscInt_FMT ", maximum function evaluations=unlimited\n", snes->max_its)); 43977e5a1f9SBarry Smith } else { 44063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " maximum iterations=%" PetscInt_FMT ", maximum function evaluations=%" PetscInt_FMT "\n", snes->max_its, snes->max_funcs)); 44177e5a1f9SBarry Smith } 4429566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " tolerances: relative=%g, absolute=%g, solution=%g\n", (double)snes->rtol, (double)snes->abstol, (double)snes->stol)); 44348a46eb9SPierre Jolivet if (snes->usesksp) PetscCall(PetscViewerASCIIPrintf(viewer, " total number of linear solver iterations=%" PetscInt_FMT "\n", snes->linear_its)); 44463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " total number of function evaluations=%" PetscInt_FMT "\n", snes->nfuncs)); 4459566063dSJacob Faibussowitsch PetscCall(SNESGetNormSchedule(snes, &normschedule)); 4469566063dSJacob Faibussowitsch if (normschedule > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " norm schedule %s\n", SNESNormSchedules[normschedule])); 44748a46eb9SPierre Jolivet if (snes->gridsequence) PetscCall(PetscViewerASCIIPrintf(viewer, " total number of grid sequence refinements=%" PetscInt_FMT "\n", snes->gridsequence)); 4489b94acceSBarry Smith if (snes->ksp_ewconv) { 449fa9f3622SBarry Smith kctx = (SNESKSPEW *)snes->kspconvctx; 4509b94acceSBarry Smith if (kctx) { 45163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Eisenstat-Walker computation of KSP relative tolerance (version %" PetscInt_FMT ")\n", kctx->version)); 4529566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " rtol_0=%g, rtol_max=%g, threshold=%g\n", (double)kctx->rtol_0, (double)kctx->rtol_max, (double)kctx->threshold)); 4539566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " gamma=%g, alpha=%g, alpha2=%g\n", (double)kctx->gamma, (double)kctx->alpha, (double)kctx->alpha2)); 4549b94acceSBarry Smith } 4559b94acceSBarry Smith } 456eb1f6c34SBarry Smith if (snes->lagpreconditioner == -1) { 4579566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Preconditioned is never rebuilt\n")); 458eb1f6c34SBarry Smith } else if (snes->lagpreconditioner > 1) { 45963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Preconditioned is rebuilt every %" PetscInt_FMT " new Jacobians\n", snes->lagpreconditioner)); 460eb1f6c34SBarry Smith } 461eb1f6c34SBarry Smith if (snes->lagjacobian == -1) { 4629566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Jacobian is never rebuilt\n")); 463eb1f6c34SBarry Smith } else if (snes->lagjacobian > 1) { 46463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Jacobian is rebuilt every %" PetscInt_FMT " SNES iterations\n", snes->lagjacobian)); 465eb1f6c34SBarry Smith } 4669566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 4679566063dSJacob Faibussowitsch PetscCall(DMSNESGetJacobian(dm, &cJ, &ctx)); 468789d8953SBarry Smith if (snes->mf_operator) { 4699566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Jacobian is applied matrix-free with differencing\n")); 470789d8953SBarry Smith pre = "Preconditioning "; 471789d8953SBarry Smith } 4728404b7f3SBarry Smith if (cJ == SNESComputeJacobianDefault) { 4739566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %sJacobian is built using finite differences one column at a time\n", pre)); 4748404b7f3SBarry Smith } else if (cJ == SNESComputeJacobianDefaultColor) { 4759566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %sJacobian is built using finite differences with coloring\n", pre)); 476789d8953SBarry Smith /* it slightly breaks data encapsulation for access the DMDA information directly */ 477789d8953SBarry Smith } else if (cJ == SNESComputeJacobian_DMDA) { 478789d8953SBarry Smith MatFDColoring fdcoloring; 4799566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)dm, "DMDASNES_FDCOLORING", (PetscObject *)&fdcoloring)); 480789d8953SBarry Smith if (fdcoloring) { 4819566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %sJacobian is built using colored finite differences on a DMDA\n", pre)); 482789d8953SBarry Smith } else { 4839566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %sJacobian is built using a DMDA local Jacobian\n", pre)); 484789d8953SBarry Smith } 485996e1cbcSBarry Smith } else if (snes->mf && !snes->mf_operator) { 4869566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Jacobian is applied matrix-free with differencing, no explicit Jacobian\n")); 4878404b7f3SBarry Smith } 4880f5bd95cSBarry Smith } else if (isstring) { 489317d6ea6SBarry Smith const char *type; 4909566063dSJacob Faibussowitsch PetscCall(SNESGetType(snes, &type)); 4919566063dSJacob Faibussowitsch PetscCall(PetscViewerStringSPrintf(viewer, " SNESType: %-7.7s", type)); 492dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, view, viewer); 49355849f57SBarry Smith } else if (isbinary) { 49455849f57SBarry Smith PetscInt classid = SNES_FILE_CLASSID; 49555849f57SBarry Smith MPI_Comm comm; 49655849f57SBarry Smith PetscMPIInt rank; 49755849f57SBarry Smith char type[256]; 49855849f57SBarry Smith 4999566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 5009566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 501dd400576SPatrick Sanan if (rank == 0) { 5029566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryWrite(viewer, &classid, 1, PETSC_INT)); 5039566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(type, ((PetscObject)snes)->type_name, sizeof(type))); 5049566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryWrite(viewer, type, sizeof(type), PETSC_CHAR)); 50555849f57SBarry Smith } 506dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, view, viewer); 50772a02f06SBarry Smith } else if (isdraw) { 50872a02f06SBarry Smith PetscDraw draw; 50972a02f06SBarry Smith char str[36]; 51089fd9fafSBarry Smith PetscReal x, y, bottom, h; 51172a02f06SBarry Smith 5129566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 5139566063dSJacob Faibussowitsch PetscCall(PetscDrawGetCurrentPoint(draw, &x, &y)); 5149566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(str, "SNES: ", sizeof(str))); 5159566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(str, ((PetscObject)snes)->type_name, sizeof(str))); 5169566063dSJacob Faibussowitsch PetscCall(PetscDrawStringBoxed(draw, x, y, PETSC_DRAW_BLUE, PETSC_DRAW_BLACK, str, NULL, &h)); 51789fd9fafSBarry Smith bottom = y - h; 5189566063dSJacob Faibussowitsch PetscCall(PetscDrawPushCurrentPoint(draw, x, bottom)); 519dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, view, viewer); 520e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS) 521536b137fSBarry Smith } else if (issaws) { 522d45a07a7SBarry Smith PetscMPIInt rank; 5232657e9d9SBarry Smith const char *name; 524d45a07a7SBarry Smith 5259566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)snes, &name)); 5269566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 527dd400576SPatrick Sanan if (!((PetscObject)snes)->amsmem && rank == 0) { 528d45a07a7SBarry Smith char dir[1024]; 529d45a07a7SBarry Smith 5309566063dSJacob Faibussowitsch PetscCall(PetscObjectViewSAWs((PetscObject)snes, viewer)); 5319566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/its", name)); 532792fecdfSBarry Smith PetscCallSAWs(SAWs_Register, (dir, &snes->iter, 1, SAWs_READ, SAWs_INT)); 53348a46eb9SPierre Jolivet if (!snes->conv_hist) PetscCall(SNESSetConvergenceHistory(snes, NULL, NULL, PETSC_DECIDE, PETSC_TRUE)); 5349566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/conv_hist", name)); 535792fecdfSBarry Smith PetscCallSAWs(SAWs_Register, (dir, snes->conv_hist, 10, SAWs_READ, SAWs_DOUBLE)); 536f05ece33SBarry Smith } 537bfb97211SBarry Smith #endif 53872a02f06SBarry Smith } 53972a02f06SBarry Smith if (snes->linesearch) { 5409566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &linesearch)); 5419566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 5429566063dSJacob Faibussowitsch PetscCall(SNESLineSearchView(linesearch, viewer)); 5439566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 54419bcc07fSBarry Smith } 545efd4aadfSBarry Smith if (snes->npc && snes->usesnpc) { 5469566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 5479566063dSJacob Faibussowitsch PetscCall(SNESView(snes->npc, viewer)); 5489566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 5494a0c5b0cSMatthew G Knepley } 5509566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 5519566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(snes->dm, &dmsnes)); 5529566063dSJacob Faibussowitsch PetscCall(DMSNESView(dmsnes, viewer)); 5539566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 5542c155ee1SBarry Smith if (snes->usesksp) { 5559566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 5569566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 5579566063dSJacob Faibussowitsch PetscCall(KSPView(ksp, viewer)); 5589566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 5592c155ee1SBarry Smith } 56072a02f06SBarry Smith if (isdraw) { 56172a02f06SBarry Smith PetscDraw draw; 5629566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 5639566063dSJacob Faibussowitsch PetscCall(PetscDrawPopCurrentPoint(draw)); 5647f1410a3SPeter Brune } 5653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5669b94acceSBarry Smith } 5679b94acceSBarry Smith 56876b2cf59SMatthew Knepley /* 56976b2cf59SMatthew Knepley We retain a list of functions that also take SNES command 57076b2cf59SMatthew Knepley line options. These are called at the end SNESSetFromOptions() 57176b2cf59SMatthew Knepley */ 57276b2cf59SMatthew Knepley #define MAXSETFROMOPTIONS 5 573a7cc72afSBarry Smith static PetscInt numberofsetfromoptions; 5746849ba73SBarry Smith static PetscErrorCode (*othersetfromoptions[MAXSETFROMOPTIONS])(SNES); 57576b2cf59SMatthew Knepley 576ac226902SBarry Smith /*@C 577f6dfbefdSBarry Smith SNESAddOptionsChecker - Adds an additional function to check for `SNES` options. 57876b2cf59SMatthew Knepley 57976b2cf59SMatthew Knepley Not Collective 58076b2cf59SMatthew Knepley 58176b2cf59SMatthew Knepley Input Parameter: 58276b2cf59SMatthew Knepley . snescheck - function that checks for options 58376b2cf59SMatthew Knepley 584420bcc1bSBarry Smith Calling sequence of `snescheck`: 585420bcc1bSBarry Smith . snes - the `SNES` object for which it is checking options 586420bcc1bSBarry Smith 58776b2cf59SMatthew Knepley Level: developer 58876b2cf59SMatthew Knepley 5891cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()` 59076b2cf59SMatthew Knepley @*/ 591420bcc1bSBarry Smith PetscErrorCode SNESAddOptionsChecker(PetscErrorCode (*snescheck)(SNES snes)) 592d71ae5a4SJacob Faibussowitsch { 59376b2cf59SMatthew Knepley PetscFunctionBegin; 59463a3b9bcSJacob Faibussowitsch PetscCheck(numberofsetfromoptions < MAXSETFROMOPTIONS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many options checkers, only %d allowed", MAXSETFROMOPTIONS); 59576b2cf59SMatthew Knepley othersetfromoptions[numberofsetfromoptions++] = snescheck; 5963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 59776b2cf59SMatthew Knepley } 59876b2cf59SMatthew Knepley 599d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetUpMatrixFree_Private(SNES snes, PetscBool hasOperator, PetscInt version) 600d71ae5a4SJacob Faibussowitsch { 601aa3661deSLisandro Dalcin Mat J; 602895c21f2SBarry Smith MatNullSpace nullsp; 603aa3661deSLisandro Dalcin 604aa3661deSLisandro Dalcin PetscFunctionBegin; 6050700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 606aa3661deSLisandro Dalcin 60798613b67SLisandro Dalcin if (!snes->vec_func && (snes->jacobian || snes->jacobian_pre)) { 60898613b67SLisandro Dalcin Mat A = snes->jacobian, B = snes->jacobian_pre; 6099566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A ? A : B, NULL, &snes->vec_func)); 61098613b67SLisandro Dalcin } 61198613b67SLisandro Dalcin 6120fdf79fbSJacob Faibussowitsch PetscCheck(version == 1 || version == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "matrix-free operator routines, only version 1 and 2"); 613aa3661deSLisandro Dalcin if (version == 1) { 6149566063dSJacob Faibussowitsch PetscCall(MatCreateSNESMF(snes, &J)); 6159566063dSJacob Faibussowitsch PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix)); 6169566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(J)); 6171e2ae407SBarry Smith /* TODO: the version 2 code should be merged into the MatCreateSNESMF() and MatCreateMFFD() infrastructure and then removed */ 6180fdf79fbSJacob Faibussowitsch } else /* if (version == 2) */ { 6195f80ce2aSJacob Faibussowitsch PetscCheck(snes->vec_func, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "SNESSetFunction() must be called first"); 620570b7f6dSBarry Smith #if !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_REAL_SINGLE) && !defined(PETSC_USE_REAL___FLOAT128) && !defined(PETSC_USE_REAL___FP16) 621f6dfbefdSBarry Smith PetscCall(MatCreateSNESMFMore(snes, snes->vec_func, &J)); 622aa3661deSLisandro Dalcin #else 6232479783cSJose E. Roman SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "matrix-free operator routines (version 2)"); 624aa3661deSLisandro Dalcin #endif 6250fdf79fbSJacob Faibussowitsch } 626aa3661deSLisandro Dalcin 62701c1178eSBarry Smith /* attach any user provided null space that was on Amat to the newly created matrix-free matrix */ 628895c21f2SBarry Smith if (snes->jacobian) { 6299566063dSJacob Faibussowitsch PetscCall(MatGetNullSpace(snes->jacobian, &nullsp)); 6301baa6e33SBarry Smith if (nullsp) PetscCall(MatSetNullSpace(J, nullsp)); 631895c21f2SBarry Smith } 632895c21f2SBarry Smith 63363a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Setting default matrix-free operator routines (version %" PetscInt_FMT ")\n", version)); 634d3462f78SMatthew Knepley if (hasOperator) { 635aa3661deSLisandro Dalcin /* This version replaces the user provided Jacobian matrix with a 6367addb90fSBarry Smith matrix-free version but still employs the user-provided matrix used for computing the preconditioner. */ 6379566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL)); 638aa3661deSLisandro Dalcin } else { 639aa3661deSLisandro Dalcin /* This version replaces both the user-provided Jacobian and the user- 64001c1178eSBarry Smith provided preconditioner Jacobian with the default matrix-free version. */ 641b552625fSStefano Zampini if (snes->npcside == PC_LEFT && snes->npc) { 6429566063dSJacob Faibussowitsch if (!snes->jacobian) PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL)); 643172a4300SPeter Brune } else { 644789d8953SBarry Smith KSP ksp; 645789d8953SBarry Smith PC pc; 646789d8953SBarry Smith PetscBool match; 647789d8953SBarry Smith 6489566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J, J, MatMFFDComputeJacobian, NULL)); 649aa3661deSLisandro Dalcin /* Force no preconditioner */ 6509566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 6519566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksp, &pc)); 6522698c518SLisandro Dalcin PetscCall(PetscObjectTypeCompareAny((PetscObject)pc, &match, PCSHELL, PCH2OPUS, "")); 653aa3661deSLisandro Dalcin if (!match) { 6549566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Setting default matrix-free preconditioner routines\nThat is no preconditioner is being used\n")); 6559566063dSJacob Faibussowitsch PetscCall(PCSetType(pc, PCNONE)); 656aa3661deSLisandro Dalcin } 657aa3661deSLisandro Dalcin } 658789d8953SBarry Smith } 6599566063dSJacob Faibussowitsch PetscCall(MatDestroy(&J)); 6603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 661aa3661deSLisandro Dalcin } 662aa3661deSLisandro Dalcin 663d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMRestrictHook_SNESVecSol(DM dmfine, Mat Restrict, Vec Rscale, Mat Inject, DM dmcoarse, void *ctx) 664d71ae5a4SJacob Faibussowitsch { 665dfe15315SJed Brown SNES snes = (SNES)ctx; 6660298fd71SBarry Smith Vec Xfine, Xfine_named = NULL, Xcoarse; 667dfe15315SJed Brown 668dfe15315SJed Brown PetscFunctionBegin; 66916ebb321SJed Brown if (PetscLogPrintInfo) { 67016ebb321SJed Brown PetscInt finelevel, coarselevel, fineclevel, coarseclevel; 6719566063dSJacob Faibussowitsch PetscCall(DMGetRefineLevel(dmfine, &finelevel)); 6729566063dSJacob Faibussowitsch PetscCall(DMGetCoarsenLevel(dmfine, &fineclevel)); 6739566063dSJacob Faibussowitsch PetscCall(DMGetRefineLevel(dmcoarse, &coarselevel)); 6749566063dSJacob Faibussowitsch PetscCall(DMGetCoarsenLevel(dmcoarse, &coarseclevel)); 67563a3b9bcSJacob 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)); 67616ebb321SJed Brown } 677dfe15315SJed Brown if (dmfine == snes->dm) Xfine = snes->vec_sol; 678dfe15315SJed Brown else { 6799566063dSJacob Faibussowitsch PetscCall(DMGetNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named)); 680dfe15315SJed Brown Xfine = Xfine_named; 681dfe15315SJed Brown } 6829566063dSJacob Faibussowitsch PetscCall(DMGetNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse)); 683907f5c5aSLawrence Mitchell if (Inject) { 6849566063dSJacob Faibussowitsch PetscCall(MatRestrict(Inject, Xfine, Xcoarse)); 685907f5c5aSLawrence Mitchell } else { 6869566063dSJacob Faibussowitsch PetscCall(MatRestrict(Restrict, Xfine, Xcoarse)); 6879566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(Xcoarse, Xcoarse, Rscale)); 688907f5c5aSLawrence Mitchell } 6899566063dSJacob Faibussowitsch PetscCall(DMRestoreNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse)); 6909566063dSJacob Faibussowitsch if (Xfine_named) PetscCall(DMRestoreNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named)); 6913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 692dfe15315SJed Brown } 693dfe15315SJed Brown 694d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCoarsenHook_SNESVecSol(DM dm, DM dmc, void *ctx) 695d71ae5a4SJacob Faibussowitsch { 69616ebb321SJed Brown PetscFunctionBegin; 6979566063dSJacob Faibussowitsch PetscCall(DMCoarsenHookAdd(dmc, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, ctx)); 6983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 69916ebb321SJed Brown } 70016ebb321SJed Brown 701a6950cb2SJed Brown /* This may be called to rediscretize the operator on levels of linear multigrid. The DM shuffle is so the user can 702a6950cb2SJed Brown * safely call SNESGetDM() in their residual evaluation routine. */ 703d71ae5a4SJacob Faibussowitsch static PetscErrorCode KSPComputeOperators_SNES(KSP ksp, Mat A, Mat B, void *ctx) 704d71ae5a4SJacob Faibussowitsch { 705caa4e7f2SJed Brown SNES snes = (SNES)ctx; 70697d931d1SStefano Zampini DMSNES sdm; 7070298fd71SBarry Smith Vec X, Xnamed = NULL; 708dfe15315SJed Brown DM dmsave; 7094e269d77SPeter Brune void *ctxsave; 7108434afd1SBarry Smith SNESJacobianFn *jac = NULL; 711caa4e7f2SJed Brown 712caa4e7f2SJed Brown PetscFunctionBegin; 713dfe15315SJed Brown dmsave = snes->dm; 7149566063dSJacob Faibussowitsch PetscCall(KSPGetDM(ksp, &snes->dm)); 715dfe15315SJed Brown if (dmsave == snes->dm) X = snes->vec_sol; /* We are on the finest level */ 71697d931d1SStefano Zampini else { 717309d62e6SStefano Zampini PetscBool has; 718309d62e6SStefano Zampini 71997d931d1SStefano Zampini /* We are on a coarser level, this vec was initialized using a DM restrict hook */ 720309d62e6SStefano Zampini PetscCall(DMHasNamedGlobalVector(snes->dm, "SNESVecSol", &has)); 721309d62e6SStefano Zampini PetscCheck(has, PetscObjectComm((PetscObject)snes->dm), PETSC_ERR_PLIB, "Missing SNESVecSol"); 72297d931d1SStefano Zampini PetscCall(DMGetNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed)); 723dfe15315SJed Brown X = Xnamed; 7249566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, NULL, NULL, &jac, &ctxsave)); 7254e269d77SPeter Brune /* If the DM's don't match up, the MatFDColoring context needed for the jacobian won't match up either -- fixit. */ 72648a46eb9SPierre Jolivet if (jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, SNESComputeJacobianDefaultColor, NULL)); 7274e269d77SPeter Brune } 7284e269d77SPeter Brune 7292b93b426SMatthew G. Knepley /* Compute the operators */ 73097d931d1SStefano Zampini PetscCall(DMGetDMSNES(snes->dm, &sdm)); 73197d931d1SStefano Zampini if (Xnamed && sdm->ops->computefunction) { 73297d931d1SStefano Zampini /* The SNES contract with the user is that ComputeFunction is always called before ComputeJacobian. 73397d931d1SStefano Zampini We make sure of this here. Disable affine shift since it is for the finest level */ 73497d931d1SStefano Zampini Vec F, saverhs = snes->vec_rhs; 73597d931d1SStefano Zampini 73697d931d1SStefano Zampini snes->vec_rhs = NULL; 73797d931d1SStefano Zampini PetscCall(DMGetGlobalVector(snes->dm, &F)); 73897d931d1SStefano Zampini PetscCall(SNESComputeFunction(snes, X, F)); 73997d931d1SStefano Zampini PetscCall(DMRestoreGlobalVector(snes->dm, &F)); 74097d931d1SStefano Zampini snes->vec_rhs = saverhs; 74197d931d1SStefano Zampini snes->nfuncs--; /* Do not log coarser level evaluations */ 74297d931d1SStefano Zampini } 74397d931d1SStefano Zampini /* Make sure KSP DM has the Jacobian computation routine */ 74497d931d1SStefano Zampini if (!sdm->ops->computejacobian) PetscCall(DMCopyDMSNES(dmsave, snes->dm)); 7459566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobian(snes, X, A, B)); 74697d931d1SStefano Zampini 7472b93b426SMatthew G. Knepley /* Put the previous context back */ 74848a46eb9SPierre Jolivet if (snes->dm != dmsave && jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, jac, ctxsave)); 7494e269d77SPeter Brune 7509566063dSJacob Faibussowitsch if (Xnamed) PetscCall(DMRestoreNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed)); 751dfe15315SJed Brown snes->dm = dmsave; 7523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 753caa4e7f2SJed Brown } 754caa4e7f2SJed Brown 7556cab3a1bSJed Brown /*@ 756dc4c0fb0SBarry Smith SNESSetUpMatrices - ensures that matrices are available for `SNES` Newton-like methods, this is called by `SNESSetUp_XXX()` 7576cab3a1bSJed Brown 7586cab3a1bSJed Brown Collective 7596cab3a1bSJed Brown 7604165533cSJose E. Roman Input Parameter: 76120f4b53cSBarry Smith . snes - `SNES` object to configure 7626cab3a1bSJed Brown 7636cab3a1bSJed Brown Level: developer 7646cab3a1bSJed Brown 765dc4c0fb0SBarry Smith Note: 766dc4c0fb0SBarry 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` 767dc4c0fb0SBarry Smith 76873a84a35SBarry Smith Developer Note: 76973a84a35SBarry Smith The functionality of this routine overlaps in a confusing way with the functionality of `SNESSetUpMatrixFree_Private()` which is called by 77073a84a35SBarry Smith `SNESSetUp()` but sometimes `SNESSetUpMatrices()` is called without `SNESSetUp()` being called. A refactorization to simplify the 77173a84a35SBarry Smith logic that handles the matrix-free case is desirable. 77273a84a35SBarry Smith 7731cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUp()` 7746cab3a1bSJed Brown @*/ 775d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUpMatrices(SNES snes) 776d71ae5a4SJacob Faibussowitsch { 7776cab3a1bSJed Brown DM dm; 778942e3340SBarry Smith DMSNES sdm; 7796cab3a1bSJed Brown 7806cab3a1bSJed Brown PetscFunctionBegin; 7819566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 7829566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 78373a84a35SBarry Smith if (!snes->jacobian && snes->mf && !snes->mf_operator && !snes->jacobian_pre) { 7846cab3a1bSJed Brown Mat J; 7856cab3a1bSJed Brown void *functx; 7869566063dSJacob Faibussowitsch PetscCall(MatCreateSNESMF(snes, &J)); 7879566063dSJacob Faibussowitsch PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix)); 7889566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(J)); 7899566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, NULL, &functx)); 7909566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J, J, NULL, NULL)); 7919566063dSJacob Faibussowitsch PetscCall(MatDestroy(&J)); 792caa4e7f2SJed Brown } else if (snes->mf_operator && !snes->jacobian_pre && !snes->jacobian) { 7936cab3a1bSJed Brown Mat J, B; 7949566063dSJacob Faibussowitsch PetscCall(MatCreateSNESMF(snes, &J)); 7959566063dSJacob Faibussowitsch PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix)); 7969566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(J)); 7979566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(snes->dm, &B)); 79806f20277SJed Brown /* sdm->computejacobian was already set to reach here */ 7999566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J, B, NULL, NULL)); 8009566063dSJacob Faibussowitsch PetscCall(MatDestroy(&J)); 8019566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 802caa4e7f2SJed Brown } else if (!snes->jacobian_pre) { 8031ba9b98eSMatthew G. Knepley PetscDS prob; 8046cab3a1bSJed Brown Mat J, B; 8051ba9b98eSMatthew G. Knepley PetscBool hasPrec = PETSC_FALSE; 8061ba9b98eSMatthew G. Knepley 8076cab3a1bSJed Brown J = snes->jacobian; 8089566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob)); 8099566063dSJacob Faibussowitsch if (prob) PetscCall(PetscDSHasJacobianPreconditioner(prob, &hasPrec)); 8109566063dSJacob Faibussowitsch if (J) PetscCall(PetscObjectReference((PetscObject)J)); 8119566063dSJacob Faibussowitsch else if (hasPrec) PetscCall(DMCreateMatrix(snes->dm, &J)); 8129566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(snes->dm, &B)); 8139566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J ? J : B, B, NULL, NULL)); 8149566063dSJacob Faibussowitsch PetscCall(MatDestroy(&J)); 8159566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 8166cab3a1bSJed Brown } 817caa4e7f2SJed Brown { 818caa4e7f2SJed Brown KSP ksp; 8199566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 8209566063dSJacob Faibussowitsch PetscCall(KSPSetComputeOperators(ksp, KSPComputeOperators_SNES, snes)); 8219566063dSJacob Faibussowitsch PetscCall(DMCoarsenHookAdd(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes)); 822caa4e7f2SJed Brown } 8233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8246cab3a1bSJed Brown } 8256cab3a1bSJed Brown 826d6acfc2dSPierre Jolivet PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode PetscMonitorPauseFinal_Internal(PetscInt, void *); 827ce78bad3SBarry Smith 828d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESMonitorPauseFinal_Internal(SNES snes) 829d71ae5a4SJacob Faibussowitsch { 8305e7c47f3SMatthew G. Knepley PetscFunctionBegin; 8313ba16761SJacob Faibussowitsch if (!snes->pauseFinal) PetscFunctionReturn(PETSC_SUCCESS); 832ce78bad3SBarry Smith PetscCall(PetscMonitorPauseFinal_Internal(snes->numbermonitors, snes->monitorcontext)); 8333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8345e7c47f3SMatthew G. Knepley } 8355e7c47f3SMatthew G. Knepley 836fde5950dSBarry Smith /*@C 837fde5950dSBarry Smith SNESMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user 838fde5950dSBarry Smith 839c3339decSBarry Smith Collective 840fde5950dSBarry Smith 841fde5950dSBarry Smith Input Parameters: 842dc4c0fb0SBarry Smith + snes - `SNES` object you wish to monitor 843fde5950dSBarry Smith . name - the monitor type one is seeking 844fde5950dSBarry Smith . help - message indicating what monitoring is done 845fde5950dSBarry Smith . manual - manual page for the monitor 84649abdd8aSBarry Smith . monitor - the monitor function, this must use a `PetscViewerFormat` as its context 847f6dfbefdSBarry 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 848fde5950dSBarry Smith 849420bcc1bSBarry Smith Calling sequence of `monitor`: 850420bcc1bSBarry Smith + snes - the nonlinear solver context 851420bcc1bSBarry Smith . it - the current iteration 852420bcc1bSBarry Smith . r - the current function norm 853420bcc1bSBarry Smith - vf - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use 854420bcc1bSBarry Smith 855420bcc1bSBarry Smith Calling sequence of `monitorsetup`: 856420bcc1bSBarry Smith + snes - the nonlinear solver context 857420bcc1bSBarry Smith - vf - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use 858420bcc1bSBarry Smith 859f6dfbefdSBarry Smith Options Database Key: 860f6dfbefdSBarry Smith . -name - trigger the use of this monitor in `SNESSetFromOptions()` 861f6dfbefdSBarry Smith 862f6dfbefdSBarry Smith Level: advanced 863fde5950dSBarry Smith 864648c30bcSBarry Smith .seealso: [](ch_snes), `PetscOptionsCreateViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, 865db781477SPatrick Sanan `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()` 866e4094ef1SJacob Faibussowitsch `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, 867db781477SPatrick Sanan `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`, 868c2e3fba1SPatrick Sanan `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`, 869db781477SPatrick Sanan `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`, 870db781477SPatrick Sanan `PetscOptionsFList()`, `PetscOptionsEList()` 871fde5950dSBarry Smith @*/ 872420bcc1bSBarry 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)) 873d71ae5a4SJacob Faibussowitsch { 874fde5950dSBarry Smith PetscViewer viewer; 875fde5950dSBarry Smith PetscViewerFormat format; 876fde5950dSBarry Smith PetscBool flg; 877fde5950dSBarry Smith 878fde5950dSBarry Smith PetscFunctionBegin; 879648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, name, &viewer, &format, &flg)); 880fde5950dSBarry Smith if (flg) { 881d43b4f6eSBarry Smith PetscViewerAndFormat *vf; 8829566063dSJacob Faibussowitsch PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf)); 883648c30bcSBarry Smith PetscCall(PetscViewerDestroy(&viewer)); 8841baa6e33SBarry Smith if (monitorsetup) PetscCall((*monitorsetup)(snes, vf)); 88549abdd8aSBarry Smith PetscCall(SNESMonitorSet(snes, (PetscErrorCode (*)(SNES, PetscInt, PetscReal, void *))monitor, vf, (PetscCtxDestroyFn *)PetscViewerAndFormatDestroy)); 886fde5950dSBarry Smith } 8873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 888fde5950dSBarry Smith } 889fde5950dSBarry Smith 890a4598233SStefano Zampini PetscErrorCode SNESEWSetFromOptions_Private(SNESKSPEW *kctx, PetscBool print_api, MPI_Comm comm, const char *prefix) 891d71ae5a4SJacob Faibussowitsch { 892a4598233SStefano Zampini const char *api = print_api ? "SNESKSPSetParametersEW" : NULL; 893a4598233SStefano Zampini 8940f0abf79SStefano Zampini PetscFunctionBegin; 8950f0abf79SStefano Zampini PetscOptionsBegin(comm, prefix, "Eisenstat and Walker type forcing options", "KSP"); 896a4598233SStefano Zampini PetscCall(PetscOptionsInt("-ksp_ew_version", "Version 1, 2 or 3", api, kctx->version, &kctx->version, NULL)); 897a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_rtol0", "0 <= rtol0 < 1", api, kctx->rtol_0, &kctx->rtol_0, NULL)); 898a4598233SStefano Zampini kctx->rtol_max = PetscMax(kctx->rtol_0, kctx->rtol_max); 899a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_rtolmax", "0 <= rtolmax < 1", api, kctx->rtol_max, &kctx->rtol_max, NULL)); 900a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_gamma", "0 <= gamma <= 1", api, kctx->gamma, &kctx->gamma, NULL)); 901a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_alpha", "1 < alpha <= 2", api, kctx->alpha, &kctx->alpha, NULL)); 9020f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_alpha2", "alpha2", NULL, kctx->alpha2, &kctx->alpha2, NULL)); 903a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_threshold", "0 < threshold < 1", api, kctx->threshold, &kctx->threshold, NULL)); 9040f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_p1", "p1", NULL, kctx->v4_p1, &kctx->v4_p1, NULL)); 9050f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_p2", "p2", NULL, kctx->v4_p2, &kctx->v4_p2, NULL)); 9060f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_p3", "p3", NULL, kctx->v4_p3, &kctx->v4_p3, NULL)); 9070f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_m1", "Scaling when rk-1 in [p2,p3)", NULL, kctx->v4_m1, &kctx->v4_m1, NULL)); 9080f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_m2", "Scaling when rk-1 in [p3,+infty)", NULL, kctx->v4_m2, &kctx->v4_m2, NULL)); 9090f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_m3", "Threshold for successive rtol (0.1 in Eq.7)", NULL, kctx->v4_m3, &kctx->v4_m3, NULL)); 9100f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_m4", "Adaptation scaling (0.5 in Eq.7)", NULL, kctx->v4_m4, &kctx->v4_m4, NULL)); 9110f0abf79SStefano Zampini PetscOptionsEnd(); 9123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9130f0abf79SStefano Zampini } 9140f0abf79SStefano Zampini 9159b94acceSBarry Smith /*@ 916f6dfbefdSBarry Smith SNESSetFromOptions - Sets various `SNES` and `KSP` parameters from user options. 9179b94acceSBarry Smith 918c3339decSBarry Smith Collective 919c7afd0dbSLois Curfman McInnes 9209b94acceSBarry Smith Input Parameter: 921f6dfbefdSBarry Smith . snes - the `SNES` context 9229b94acceSBarry Smith 92336851e7fSLois Curfman McInnes Options Database Keys: 924f6dfbefdSBarry Smith + -snes_type <type> - newtonls, newtontr, ngmres, ncg, nrichardson, qn, vi, fas, `SNESType` for complete list 925b39c3a46SLois Curfman McInnes . -snes_rtol <rtol> - relative decrease in tolerance norm from initial 92677e5a1f9SBarry Smith . -snes_atol <abstol> - absolute tolerance of residual norm 92777e5a1f9SBarry Smith . -snes_stol <stol> - convergence tolerance in terms of the norm of the change in the solution between steps 928e4d06f11SPatrick Farrell . -snes_divergence_tolerance <divtol> - if the residual goes above divtol*rnorm0, exit with divergence 929b39c3a46SLois Curfman McInnes . -snes_max_it <max_it> - maximum number of iterations 930b39c3a46SLois Curfman McInnes . -snes_max_funcs <max_funcs> - maximum number of function evaluations 93177e5a1f9SBarry Smith . -snes_force_iteration <force> - force `SNESSolve()` to take at least one iteration 9324839bfe8SBarry Smith . -snes_max_fail <max_fail> - maximum number of line search failures allowed before stopping, default is none 933ddf469c8SBarry Smith . -snes_max_linear_solve_fail - number of linear solver failures before SNESSolve() stops 934a8054027SBarry Smith . -snes_lag_preconditioner <lag> - how often preconditioner is rebuilt (use -1 to never rebuild) 9353d5a8a6aSBarry Smith . -snes_lag_preconditioner_persists <true,false> - retains the -snes_lag_preconditioner information across multiple SNESSolve() 936e35cf81dSBarry Smith . -snes_lag_jacobian <lag> - how often Jacobian is rebuilt (use -1 to never rebuild) 9373d5a8a6aSBarry Smith . -snes_lag_jacobian_persists <true,false> - retains the -snes_lag_jacobian information across multiple SNESSolve() 938ceaaa498SBarry 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. 939fde5950dSBarry Smith . -snes_monitor [ascii][:filename][:viewer format] - prints residual norm at each iteration. if no filename given prints to stdout 940fde5950dSBarry Smith . -snes_monitor_solution [ascii binary draw][:filename][:viewer format] - plots solution at each iteration 941fde5950dSBarry Smith . -snes_monitor_residual [ascii binary draw][:filename][:viewer format] - plots residual (not its norm) at each iteration 942fde5950dSBarry Smith . -snes_monitor_solution_update [ascii binary draw][:filename][:viewer format] - plots update to solution at each iteration 9434619e776SBarry Smith . -snes_monitor_lg_residualnorm - plots residual norm at each iteration 944459f5d12SBarry Smith . -snes_monitor_lg_range - plots residual norm at each iteration 9455e7c47f3SMatthew G. Knepley . -snes_monitor_pause_final - Pauses all monitor drawing after the solver ends 946e24b481bSBarry Smith . -snes_fd - use finite differences to compute Jacobian; very slow, only for testing 947e2e60de9SPeter Brune . -snes_fd_color - use finite differences with coloring to compute Jacobian 948ceaaa498SBarry Smith . -snes_mf_ksp_monitor - if using matrix-free multiply then print h at each `KSP` iteration 949b5badacbSBarry Smith . -snes_converged_reason - print the reason for convergence/divergence after each solve 950ceaaa498SBarry Smith . -npc_snes_type <type> - the `SNES` type to use as a nonlinear preconditioner 951e62ac41dSBarry 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. 952e62ac41dSBarry 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. 95382738288SBarry Smith 954f6dfbefdSBarry Smith Options Database Keys for Eisenstat-Walker method: 955fa9f3622SBarry Smith + -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence 9564b27c08aSLois Curfman McInnes . -snes_ksp_ew_version ver - version of Eisenstat-Walker method 95736851e7fSLois Curfman McInnes . -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0 95836851e7fSLois Curfman McInnes . -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax 95936851e7fSLois Curfman McInnes . -snes_ksp_ew_gamma <gamma> - Sets gamma 96036851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha <alpha> - Sets alpha 96136851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2 96236851e7fSLois Curfman McInnes - -snes_ksp_ew_threshold <threshold> - Sets threshold 96382738288SBarry Smith 964dc4c0fb0SBarry Smith Level: beginner 965dc4c0fb0SBarry Smith 96611ca99fdSLois Curfman McInnes Notes: 967ec5066bdSBarry Smith To see all options, run your program with the -help option or consult the users manual 968ec5066bdSBarry Smith 969420bcc1bSBarry Smith `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`, 970420bcc1bSBarry Smith and computing explicitly with 971f6dfbefdSBarry Smith finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object. 97283e2fdc7SBarry Smith 973420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESType`, `SNESSetOptionsPrefix()`, `SNESResetFromOptions()`, `SNES`, `SNESCreate()`, `MatCreateSNESMF()`, `MatFDColoring` 9749b94acceSBarry Smith @*/ 975d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFromOptions(SNES snes) 976d71ae5a4SJacob Faibussowitsch { 9778afaa268SBarry Smith PetscBool flg, pcset, persist, set; 97877e5a1f9SBarry Smith PetscInt i, indx, lag, grids, max_its, max_funcs; 97904d7464bSBarry Smith const char *deft = SNESNEWTONLS; 980649ef022SMatthew Knepley const char *convtests[] = {"default", "skip", "correct_pressure"}; 98185385478SLisandro Dalcin SNESKSPEW *kctx = NULL; 9820f0abf79SStefano Zampini char type[256], monfilename[PETSC_MAX_PATH_LEN], ewprefix[256]; 983c40d0f55SPeter Brune PCSide pcside; 984a64e098fSPeter Brune const char *optionsprefix; 98577e5a1f9SBarry Smith PetscReal rtol, abstol, stol; 9869b94acceSBarry Smith 9873a40ed3dSBarry Smith PetscFunctionBegin; 9880700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 9899566063dSJacob Faibussowitsch PetscCall(SNESRegisterAll()); 990d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)snes); 991639ff905SBarry Smith if (((PetscObject)snes)->type_name) deft = ((PetscObject)snes)->type_name; 9929566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-snes_type", "Nonlinear solver method", "SNESSetType", SNESList, deft, type, 256, &flg)); 993d64ed03dSBarry Smith if (flg) { 9949566063dSJacob Faibussowitsch PetscCall(SNESSetType(snes, type)); 9957adad957SLisandro Dalcin } else if (!((PetscObject)snes)->type_name) { 9969566063dSJacob Faibussowitsch PetscCall(SNESSetType(snes, deft)); 997d64ed03dSBarry Smith } 998186905e3SBarry Smith 99977e5a1f9SBarry Smith abstol = snes->abstol; 100077e5a1f9SBarry Smith rtol = snes->rtol; 100177e5a1f9SBarry Smith stol = snes->stol; 100277e5a1f9SBarry Smith max_its = snes->max_its; 100377e5a1f9SBarry Smith max_funcs = snes->max_funcs; 100477e5a1f9SBarry Smith PetscCall(PetscOptionsReal("-snes_rtol", "Stop if decrease in function norm less than", "SNESSetTolerances", snes->rtol, &rtol, NULL)); 100577e5a1f9SBarry Smith PetscCall(PetscOptionsReal("-snes_atol", "Stop if function norm less than", "SNESSetTolerances", snes->abstol, &abstol, NULL)); 100677e5a1f9SBarry Smith PetscCall(PetscOptionsReal("-snes_stol", "Stop if step length less than", "SNESSetTolerances", snes->stol, &stol, NULL)); 100777e5a1f9SBarry Smith PetscCall(PetscOptionsInt("-snes_max_it", "Maximum iterations", "SNESSetTolerances", snes->max_its, &max_its, NULL)); 100877e5a1f9SBarry Smith PetscCall(PetscOptionsInt("-snes_max_funcs", "Maximum function evaluations", "SNESSetTolerances", snes->max_funcs, &max_funcs, NULL)); 100977e5a1f9SBarry Smith PetscCall(SNESSetTolerances(snes, abstol, rtol, stol, max_its, max_funcs)); 101077e5a1f9SBarry Smith 101177e5a1f9SBarry Smith PetscCall(PetscOptionsReal("-snes_divergence_tolerance", "Stop if residual norm increases by this factor", "SNESSetDivergenceTolerance", snes->divtol, &snes->divtol, &flg)); 101277e5a1f9SBarry Smith if (flg) PetscCall(SNESSetDivergenceTolerance(snes, snes->divtol)); 101377e5a1f9SBarry Smith 101477e5a1f9SBarry Smith PetscCall(PetscOptionsInt("-snes_max_fail", "Maximum nonlinear step failures", "SNESSetMaxNonlinearStepFailures", snes->maxFailures, &snes->maxFailures, &flg)); 101577e5a1f9SBarry Smith if (flg) PetscCall(SNESSetMaxNonlinearStepFailures(snes, snes->maxFailures)); 101677e5a1f9SBarry Smith 101777e5a1f9SBarry Smith PetscCall(PetscOptionsInt("-snes_max_linear_solve_fail", "Maximum failures in linear solves allowed", "SNESSetMaxLinearSolveFailures", snes->maxLinearSolveFailures, &snes->maxLinearSolveFailures, &flg)); 101877e5a1f9SBarry Smith if (flg) PetscCall(SNESSetMaxLinearSolveFailures(snes, snes->maxLinearSolveFailures)); 101977e5a1f9SBarry Smith 10209566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_error_if_not_converged", "Generate error if solver does not converge", "SNESSetErrorIfNotConverged", snes->errorifnotconverged, &snes->errorifnotconverged, NULL)); 10219566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_force_iteration", "Force SNESSolve() to take at least one iteration", "SNESSetForceIteration", snes->forceiteration, &snes->forceiteration, NULL)); 10229566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_check_jacobian_domain_error", "Check Jacobian domain error after Jacobian evaluation", "SNESCheckJacobianDomainError", snes->checkjacdomainerror, &snes->checkjacdomainerror, NULL)); 102385385478SLisandro Dalcin 10249566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_lag_preconditioner", "How often to rebuild preconditioner", "SNESSetLagPreconditioner", snes->lagpreconditioner, &lag, &flg)); 1025a8054027SBarry Smith if (flg) { 10265f80ce2aSJacob 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"); 10279566063dSJacob Faibussowitsch PetscCall(SNESSetLagPreconditioner(snes, lag)); 1028a8054027SBarry Smith } 10299566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_lag_preconditioner_persists", "Preconditioner lagging through multiple SNES solves", "SNESSetLagPreconditionerPersists", snes->lagjac_persist, &persist, &flg)); 10301baa6e33SBarry Smith if (flg) PetscCall(SNESSetLagPreconditionerPersists(snes, persist)); 10319566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_lag_jacobian", "How often to rebuild Jacobian", "SNESSetLagJacobian", snes->lagjacobian, &lag, &flg)); 1032e35cf81dSBarry Smith if (flg) { 10335f80ce2aSJacob 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"); 10349566063dSJacob Faibussowitsch PetscCall(SNESSetLagJacobian(snes, lag)); 1035e35cf81dSBarry Smith } 10369566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_lag_jacobian_persists", "Jacobian lagging through multiple SNES solves", "SNESSetLagJacobianPersists", snes->lagjac_persist, &persist, &flg)); 10371baa6e33SBarry Smith if (flg) PetscCall(SNESSetLagJacobianPersists(snes, persist)); 103837ec4e1aSPeter Brune 10399566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_grid_sequence", "Use grid sequencing to generate initial guess", "SNESSetGridSequence", snes->gridsequence, &grids, &flg)); 10401baa6e33SBarry Smith if (flg) PetscCall(SNESSetGridSequence(snes, grids)); 1041a8054027SBarry Smith 1042400f6f02SBarry Smith PetscCall(PetscOptionsEList("-snes_convergence_test", "Convergence test", "SNESSetConvergenceTest", convtests, PETSC_STATIC_ARRAY_LENGTH(convtests), "default", &indx, &flg)); 104385385478SLisandro Dalcin if (flg) { 104485385478SLisandro Dalcin switch (indx) { 1045d71ae5a4SJacob Faibussowitsch case 0: 1046d71ae5a4SJacob Faibussowitsch PetscCall(SNESSetConvergenceTest(snes, SNESConvergedDefault, NULL, NULL)); 1047d71ae5a4SJacob Faibussowitsch break; 1048d71ae5a4SJacob Faibussowitsch case 1: 1049d71ae5a4SJacob Faibussowitsch PetscCall(SNESSetConvergenceTest(snes, SNESConvergedSkip, NULL, NULL)); 1050d71ae5a4SJacob Faibussowitsch break; 1051d71ae5a4SJacob Faibussowitsch case 2: 1052d71ae5a4SJacob Faibussowitsch PetscCall(SNESSetConvergenceTest(snes, SNESConvergedCorrectPressure, NULL, NULL)); 1053d71ae5a4SJacob Faibussowitsch break; 105485385478SLisandro Dalcin } 105585385478SLisandro Dalcin } 105685385478SLisandro Dalcin 10579566063dSJacob Faibussowitsch PetscCall(PetscOptionsEList("-snes_norm_schedule", "SNES Norm schedule", "SNESSetNormSchedule", SNESNormSchedules, 5, "function", &indx, &flg)); 10589566063dSJacob Faibussowitsch if (flg) PetscCall(SNESSetNormSchedule(snes, (SNESNormSchedule)indx)); 1059fdacfa88SPeter Brune 10609566063dSJacob Faibussowitsch PetscCall(PetscOptionsEList("-snes_function_type", "SNES Norm schedule", "SNESSetFunctionType", SNESFunctionTypes, 2, "unpreconditioned", &indx, &flg)); 10619566063dSJacob Faibussowitsch if (flg) PetscCall(SNESSetFunctionType(snes, (SNESFunctionType)indx)); 1062186905e3SBarry Smith 106385385478SLisandro Dalcin kctx = (SNESKSPEW *)snes->kspconvctx; 106485385478SLisandro Dalcin 10659566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_ksp_ew", "Use Eisentat-Walker linear system convergence test", "SNESKSPSetUseEW", snes->ksp_ewconv, &snes->ksp_ewconv, NULL)); 1066186905e3SBarry Smith 10670f0abf79SStefano Zampini PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 10680f0abf79SStefano Zampini PetscCall(PetscSNPrintf(ewprefix, sizeof(ewprefix), "%s%s", optionsprefix ? optionsprefix : "", "snes_")); 1069a4598233SStefano Zampini PetscCall(SNESEWSetFromOptions_Private(kctx, PETSC_TRUE, PetscObjectComm((PetscObject)snes), ewprefix)); 1070186905e3SBarry Smith 107190d69ab7SBarry Smith flg = PETSC_FALSE; 10729566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_monitor_cancel", "Remove all monitors", "SNESMonitorCancel", flg, &flg, &set)); 10739566063dSJacob Faibussowitsch if (set && flg) PetscCall(SNESMonitorCancel(snes)); 1074eabae89aSBarry Smith 10759566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor", "Monitor norm of function", "SNESMonitorDefault", SNESMonitorDefault, SNESMonitorDefaultSetUp)); 10769566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_short", "Monitor norm of function with fewer digits", "SNESMonitorDefaultShort", SNESMonitorDefaultShort, NULL)); 10779566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_range", "Monitor range of elements of function", "SNESMonitorRange", SNESMonitorRange, NULL)); 1078eabae89aSBarry Smith 10799566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_ratio", "Monitor ratios of the norm of function for consecutive steps", "SNESMonitorRatio", SNESMonitorRatio, SNESMonitorRatioSetUp)); 10809566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_field", "Monitor norm of function (split into fields)", "SNESMonitorDefaultField", SNESMonitorDefaultField, NULL)); 10819566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution", "View solution at each iteration", "SNESMonitorSolution", SNESMonitorSolution, NULL)); 10829566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution_update", "View correction at each iteration", "SNESMonitorSolutionUpdate", SNESMonitorSolutionUpdate, NULL)); 10839566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_residual", "View residual at each iteration", "SNESMonitorResidual", SNESMonitorResidual, NULL)); 10849566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_jacupdate_spectrum", "Print the change in the spectrum of the Jacobian", "SNESMonitorJacUpdateSpectrum", SNESMonitorJacUpdateSpectrum, NULL)); 10859566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_fields", "Monitor norm of function per field", "SNESMonitorSet", SNESMonitorFields, NULL)); 10869566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_monitor_pause_final", "Pauses all draw monitors at the final iterate", "SNESMonitorPauseFinal_Internal", PETSC_FALSE, &snes->pauseFinal, NULL)); 10872db13446SMatthew G. Knepley 10889566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-snes_monitor_python", "Use Python function", "SNESMonitorSet", NULL, monfilename, sizeof(monfilename), &flg)); 10899566063dSJacob Faibussowitsch if (flg) PetscCall(PetscPythonMonitorSet((PetscObject)snes, monfilename)); 10905180491cSLisandro Dalcin 109190d69ab7SBarry Smith flg = PETSC_FALSE; 10929566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_monitor_lg_range", "Plot function range at each iteration", "SNESMonitorLGRange", flg, &flg, NULL)); 1093459f5d12SBarry Smith if (flg) { 1094459f5d12SBarry Smith PetscViewer ctx; 1095e24b481bSBarry Smith 10969566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &ctx)); 109749abdd8aSBarry Smith PetscCall(SNESMonitorSet(snes, SNESMonitorLGRange, ctx, (PetscCtxDestroyFn *)PetscViewerDestroy)); 1098459f5d12SBarry Smith } 10992e7541e6SPeter Brune 1100648c30bcSBarry Smith PetscCall(PetscViewerDestroy(&snes->convergedreasonviewer)); 1101648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_converged_reason", &snes->convergedreasonviewer, &snes->convergedreasonformat, NULL)); 110290d69ab7SBarry Smith flg = PETSC_FALSE; 11039566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_converged_reason_view_cancel", "Remove all converged reason viewers", "SNESConvergedReasonViewCancel", flg, &flg, &set)); 11049566063dSJacob Faibussowitsch if (set && flg) PetscCall(SNESConvergedReasonViewCancel(snes)); 1105c4421ceaSFande Kong 1106c4421ceaSFande Kong flg = PETSC_FALSE; 11079566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_fd", "Use finite differences (slow) to compute Jacobian", "SNESComputeJacobianDefault", flg, &flg, NULL)); 11084b27c08aSLois Curfman McInnes if (flg) { 11096cab3a1bSJed Brown void *functx; 1110b1f624c7SBarry Smith DM dm; 11119566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 1112800f99ffSJeremy L Thompson PetscCall(DMSNESUnsetJacobianContext_Internal(dm)); 11139566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, NULL, &functx)); 11149566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefault, functx)); 11159566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Setting default finite difference Jacobian matrix\n")); 11169b94acceSBarry Smith } 1117639f9d9dSBarry Smith 111844848bc4SPeter Brune flg = PETSC_FALSE; 11199566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_fd_function", "Use finite differences (slow) to compute function from user objective", "SNESObjectiveComputeFunctionDefaultFD", flg, &flg, NULL)); 11201baa6e33SBarry Smith if (flg) PetscCall(SNESSetFunction(snes, NULL, SNESObjectiveComputeFunctionDefaultFD, NULL)); 112197584545SPeter Brune 112297584545SPeter Brune flg = PETSC_FALSE; 11239566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_fd_color", "Use finite differences with coloring to compute Jacobian", "SNESComputeJacobianDefaultColor", flg, &flg, NULL)); 112444848bc4SPeter Brune if (flg) { 1125c52e227fSPeter Brune DM dm; 11269566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 1127800f99ffSJeremy L Thompson PetscCall(DMSNESUnsetJacobianContext_Internal(dm)); 11289566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefaultColor, NULL)); 11299566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Setting default finite difference coloring Jacobian matrix\n")); 113044848bc4SPeter Brune } 113144848bc4SPeter Brune 1132aa3661deSLisandro Dalcin flg = PETSC_FALSE; 11337addb90fSBarry 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)); 1134d8f46077SPeter Brune if (flg && snes->mf_operator) { 1135a8248277SBarry Smith snes->mf_operator = PETSC_TRUE; 1136d8f46077SPeter Brune snes->mf = PETSC_TRUE; 1137a8248277SBarry Smith } 1138aa3661deSLisandro Dalcin flg = PETSC_FALSE; 11397addb90fSBarry Smith PetscCall(PetscOptionsBool("-snes_mf", "Use a Matrix-Free Jacobian with no matrix for computing the preconditioner", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf, &flg)); 1140d8f46077SPeter Brune if (!flg && snes->mf_operator) snes->mf = PETSC_TRUE; 11419566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_mf_version", "Matrix-Free routines version 1 or 2", "None", snes->mf_version, &snes->mf_version, NULL)); 1142d28543b3SPeter Brune 11431dfd7622SMatthew Knepley PetscCall(PetscOptionsName("-snes_test_function", "Compare hand-coded and finite difference functions", "None", &snes->testFunc)); 11441dfd7622SMatthew Knepley PetscCall(PetscOptionsName("-snes_test_jacobian", "Compare hand-coded and finite difference Jacobians", "None", &snes->testJac)); 11451dfd7622SMatthew Knepley 1146c40d0f55SPeter Brune flg = PETSC_FALSE; 11479566063dSJacob Faibussowitsch PetscCall(SNESGetNPCSide(snes, &pcside)); 11489566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-snes_npc_side", "SNES nonlinear preconditioner side", "SNESSetNPCSide", PCSides, (PetscEnum)pcside, (PetscEnum *)&pcside, &flg)); 11499566063dSJacob Faibussowitsch if (flg) PetscCall(SNESSetNPCSide(snes, pcside)); 1150c40d0f55SPeter Brune 1151e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS) 11528a70d858SHong Zhang /* 11538a70d858SHong Zhang Publish convergence information using SAWs 11548a70d858SHong Zhang */ 11558a70d858SHong Zhang flg = PETSC_FALSE; 11569566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_monitor_saws", "Publish SNES progress using SAWs", "SNESMonitorSet", flg, &flg, NULL)); 11578a70d858SHong Zhang if (flg) { 11588a70d858SHong Zhang void *ctx; 11599566063dSJacob Faibussowitsch PetscCall(SNESMonitorSAWsCreate(snes, &ctx)); 11609566063dSJacob Faibussowitsch PetscCall(SNESMonitorSet(snes, SNESMonitorSAWs, ctx, SNESMonitorSAWsDestroy)); 11618a70d858SHong Zhang } 11628a70d858SHong Zhang #endif 11638a70d858SHong Zhang #if defined(PETSC_HAVE_SAWS) 1164b90c6cbeSBarry Smith { 1165b90c6cbeSBarry Smith PetscBool set; 1166b90c6cbeSBarry Smith flg = PETSC_FALSE; 11679566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_saws_block", "Block for SAWs at end of SNESSolve", "PetscObjectSAWsBlock", ((PetscObject)snes)->amspublishblock, &flg, &set)); 11681baa6e33SBarry Smith if (set) PetscCall(PetscObjectSAWsSetBlock((PetscObject)snes, flg)); 1169b90c6cbeSBarry Smith } 1170b90c6cbeSBarry Smith #endif 1171b90c6cbeSBarry Smith 117248a46eb9SPierre Jolivet for (i = 0; i < numberofsetfromoptions; i++) PetscCall((*othersetfromoptions[i])(snes)); 117376b2cf59SMatthew Knepley 1174dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, setfromoptions, PetscOptionsObject); 11755d973c19SBarry Smith 11765d973c19SBarry Smith /* process any options handlers added with PetscObjectAddOptionsHandler() */ 1177dbbe0bcdSBarry Smith PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)snes, PetscOptionsObject)); 1178d0609cedSBarry Smith PetscOptionsEnd(); 11794bbc92c1SBarry Smith 1180d8d34be6SBarry Smith if (snes->linesearch) { 11819566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 11829566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetFromOptions(snes->linesearch)); 1183d8d34be6SBarry Smith } 11849e764e56SPeter Brune 11856aa5e7e9SBarry Smith if (snes->usesksp) { 11869566063dSJacob Faibussowitsch if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 11879566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(snes->ksp, snes->jacobian, snes->jacobian_pre)); 11889566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(snes->ksp)); 11896aa5e7e9SBarry Smith } 11906991f827SBarry Smith 1191b5badacbSBarry Smith /* if user has set the SNES NPC type via options database, create it. */ 11929566063dSJacob Faibussowitsch PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 11939566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)snes)->options, optionsprefix, "-npc_snes_type", &pcset)); 119448a46eb9SPierre Jolivet if (pcset && (!snes->npc)) PetscCall(SNESGetNPC(snes, &snes->npc)); 11951baa6e33SBarry Smith if (snes->npc) PetscCall(SNESSetFromOptions(snes->npc)); 1196b3cd9a81SMatthew G. Knepley snes->setfromoptionscalled++; 11973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1198b3cd9a81SMatthew G. Knepley } 1199b3cd9a81SMatthew G. Knepley 1200b3cd9a81SMatthew G. Knepley /*@ 1201420bcc1bSBarry Smith SNESResetFromOptions - Sets various `SNES` and `KSP` parameters from user options ONLY if the `SNESSetFromOptions()` was previously called 1202b3cd9a81SMatthew G. Knepley 1203c3339decSBarry Smith Collective 1204b3cd9a81SMatthew G. Knepley 1205b3cd9a81SMatthew G. Knepley Input Parameter: 1206f6dfbefdSBarry Smith . snes - the `SNES` context 1207b3cd9a81SMatthew G. Knepley 1208420bcc1bSBarry Smith Level: advanced 1209b3cd9a81SMatthew G. Knepley 12101cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESSetOptionsPrefix()` 1211b3cd9a81SMatthew G. Knepley @*/ 1212d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESResetFromOptions(SNES snes) 1213d71ae5a4SJacob Faibussowitsch { 1214b3cd9a81SMatthew G. Knepley PetscFunctionBegin; 12159566063dSJacob Faibussowitsch if (snes->setfromoptionscalled) PetscCall(SNESSetFromOptions(snes)); 12163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12179b94acceSBarry Smith } 12189b94acceSBarry Smith 1219bb9467b5SJed Brown /*@C 1220d25893d9SBarry Smith SNESSetComputeApplicationContext - Sets an optional function to compute a user-defined context for 1221d25893d9SBarry Smith the nonlinear solvers. 1222d25893d9SBarry Smith 1223dc4c0fb0SBarry Smith Logically Collective; No Fortran Support 1224d25893d9SBarry Smith 1225d25893d9SBarry Smith Input Parameters: 1226f6dfbefdSBarry Smith + snes - the `SNES` context 1227d25893d9SBarry Smith . compute - function to compute the context 122849abdd8aSBarry Smith - destroy - function to destroy the context, see `PetscCtxDestroyFn` for the calling sequence 1229d25893d9SBarry Smith 1230420bcc1bSBarry Smith Calling sequence of `compute`: 1231420bcc1bSBarry Smith + snes - the `SNES` context 1232420bcc1bSBarry Smith - ctx - context to be computed 1233420bcc1bSBarry Smith 1234d25893d9SBarry Smith Level: intermediate 1235d25893d9SBarry Smith 1236f6dfbefdSBarry Smith Note: 1237f6dfbefdSBarry Smith This routine is useful if you are performing grid sequencing or using `SNESFAS` and need the appropriate context generated for each level. 1238f6dfbefdSBarry Smith 1239f6dfbefdSBarry Smith Use `SNESSetApplicationContext()` to see the context immediately 1240f6dfbefdSBarry Smith 124149abdd8aSBarry Smith .seealso: [](ch_snes), `SNESGetApplicationContext()`, `SNESSetApplicationContext()`, `PetscCtxDestroyFn` 1242d25893d9SBarry Smith @*/ 124349abdd8aSBarry Smith PetscErrorCode SNESSetComputeApplicationContext(SNES snes, PetscErrorCode (*compute)(SNES snes, void **ctx), PetscCtxDestroyFn *destroy) 1244d71ae5a4SJacob Faibussowitsch { 1245d25893d9SBarry Smith PetscFunctionBegin; 1246d25893d9SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1247d25893d9SBarry Smith snes->ops->usercompute = compute; 124849abdd8aSBarry Smith snes->ops->ctxdestroy = destroy; 12493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1250d25893d9SBarry Smith } 1251a847f771SSatish Balay 1252b07ff414SBarry Smith /*@ 1253f6dfbefdSBarry Smith SNESSetApplicationContext - Sets the optional user-defined context for the nonlinear solvers. 12549b94acceSBarry Smith 1255c3339decSBarry Smith Logically Collective 1256fee21e36SBarry Smith 1257c7afd0dbSLois Curfman McInnes Input Parameters: 1258f6dfbefdSBarry Smith + snes - the `SNES` context 1259ce78bad3SBarry Smith - ctx - the user context 1260c7afd0dbSLois Curfman McInnes 126136851e7fSLois Curfman McInnes Level: intermediate 126236851e7fSLois Curfman McInnes 1263f6dfbefdSBarry Smith Notes: 1264ce78bad3SBarry Smith Users can provide a context when constructing the `SNES` options and then access it inside their function, Jacobian computation, or other evaluation function 1265f6dfbefdSBarry Smith with `SNESGetApplicationContext()` 1266f6dfbefdSBarry Smith 1267f6dfbefdSBarry Smith To provide a function that computes the context for you use `SNESSetComputeApplicationContext()` 1268f6dfbefdSBarry Smith 1269420bcc1bSBarry Smith Fortran Note: 1270ce78bad3SBarry 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 1271ce78bad3SBarry Smith function that tells the Fortran compiler the derived data type that is passed in as the `ctx` argument. See `SNESGetApplicationContext()` for 1272ce78bad3SBarry Smith an example. 1273daf670e6SBarry Smith 12741cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetComputeApplicationContext()`, `SNESGetApplicationContext()` 12759b94acceSBarry Smith @*/ 127649abdd8aSBarry Smith PetscErrorCode SNESSetApplicationContext(SNES snes, void *ctx) 1277d71ae5a4SJacob Faibussowitsch { 1278b07ff414SBarry Smith KSP ksp; 12791b2093e4SBarry Smith 12803a40ed3dSBarry Smith PetscFunctionBegin; 12810700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 12829566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 128349abdd8aSBarry Smith PetscCall(KSPSetApplicationContext(ksp, ctx)); 128449abdd8aSBarry Smith snes->ctx = ctx; 12853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12869b94acceSBarry Smith } 128774679c65SBarry Smith 1288b07ff414SBarry Smith /*@ 12899b94acceSBarry Smith SNESGetApplicationContext - Gets the user-defined context for the 1290420bcc1bSBarry Smith nonlinear solvers set with `SNESGetApplicationContext()` or `SNESSetComputeApplicationContext()` 12919b94acceSBarry Smith 1292c7afd0dbSLois Curfman McInnes Not Collective 1293c7afd0dbSLois Curfman McInnes 12949b94acceSBarry Smith Input Parameter: 1295f6dfbefdSBarry Smith . snes - `SNES` context 12969b94acceSBarry Smith 12979b94acceSBarry Smith Output Parameter: 129849abdd8aSBarry Smith . ctx - user context 12999b94acceSBarry Smith 130036851e7fSLois Curfman McInnes Level: intermediate 130136851e7fSLois Curfman McInnes 1302ce78bad3SBarry Smith Fortran Notes: 1303ce78bad3SBarry 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 1304ce78bad3SBarry Smith function that tells the Fortran compiler the derived data type that is returned as the `ctx` argument. For example, 1305ce78bad3SBarry Smith .vb 1306ce78bad3SBarry Smith Interface SNESGetApplicationContext 1307ce78bad3SBarry Smith Subroutine SNESGetApplicationContext(snes,ctx,ierr) 1308ce78bad3SBarry Smith #include <petsc/finclude/petscsnes.h> 1309ce78bad3SBarry Smith use petscsnes 1310ce78bad3SBarry Smith SNES snes 1311ce78bad3SBarry Smith type(tUsertype), pointer :: ctx 1312ce78bad3SBarry Smith PetscErrorCode ierr 1313ce78bad3SBarry Smith End Subroutine 1314ce78bad3SBarry Smith End Interface SNESGetApplicationContext 1315ce78bad3SBarry Smith .ve 1316ce78bad3SBarry Smith 1317bfe80ac4SPierre Jolivet The prototype for `ctx` must be 1318ce78bad3SBarry Smith .vb 1319ce78bad3SBarry Smith type(tUsertype), pointer :: ctx 1320ce78bad3SBarry Smith .ve 1321dc4c0fb0SBarry Smith 1322420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESSetApplicationContext()`, `SNESSetComputeApplicationContext()` 13239b94acceSBarry Smith @*/ 1324ce78bad3SBarry Smith PetscErrorCode SNESGetApplicationContext(SNES snes, PeCtx ctx) 1325d71ae5a4SJacob Faibussowitsch { 13263a40ed3dSBarry Smith PetscFunctionBegin; 13270700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 132849abdd8aSBarry Smith *(void **)ctx = snes->ctx; 13293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13309b94acceSBarry Smith } 133174679c65SBarry Smith 13329b94acceSBarry Smith /*@ 1333420bcc1bSBarry Smith SNESSetUseMatrixFree - indicates that `SNES` should use matrix-free finite difference matrix-vector products to apply the Jacobian. 13343565c898SBarry Smith 1335dc4c0fb0SBarry Smith Logically Collective 13363565c898SBarry Smith 13373565c898SBarry Smith Input Parameters: 1338f6dfbefdSBarry Smith + snes - `SNES` context 1339f6dfbefdSBarry Smith . mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used 1340f6dfbefdSBarry 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 1341420bcc1bSBarry Smith this option no matrix-element based preconditioners can be used in the linear solve since the matrix won't be explicitly available 13423565c898SBarry Smith 1343f6dfbefdSBarry Smith Options Database Keys: 134401c1178eSBarry Smith + -snes_mf_operator - use matrix-free only for the mat operator 1345f6dfbefdSBarry Smith . -snes_mf - use matrix-free for both the mat and pmat operator 1346ec5066bdSBarry Smith . -snes_fd_color - compute the Jacobian via coloring and finite differences. 1347ec5066bdSBarry Smith - -snes_fd - compute the Jacobian via finite differences (slow) 13483565c898SBarry Smith 13493565c898SBarry Smith Level: intermediate 13503565c898SBarry Smith 1351f6dfbefdSBarry Smith Note: 1352420bcc1bSBarry Smith `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`, 1353420bcc1bSBarry Smith and computing explicitly with 1354f6dfbefdSBarry Smith finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object. 1355ec5066bdSBarry Smith 1356420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetUseMatrixFree()`, `MatCreateSNESMF()`, `SNESComputeJacobianDefaultColor()`, `MatFDColoring` 13573565c898SBarry Smith @*/ 1358d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUseMatrixFree(SNES snes, PetscBool mf_operator, PetscBool mf) 1359d71ae5a4SJacob Faibussowitsch { 13603565c898SBarry Smith PetscFunctionBegin; 13613565c898SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 136288b4c220SStefano Zampini PetscValidLogicalCollectiveBool(snes, mf_operator, 2); 136388b4c220SStefano Zampini PetscValidLogicalCollectiveBool(snes, mf, 3); 13644ddffce6SLisandro Dalcin snes->mf = mf_operator ? PETSC_TRUE : mf; 13653565c898SBarry Smith snes->mf_operator = mf_operator; 13663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13673565c898SBarry Smith } 13683565c898SBarry Smith 13693565c898SBarry Smith /*@ 1370dc4c0fb0SBarry Smith SNESGetUseMatrixFree - indicates if the `SNES` uses matrix-free finite difference matrix vector products to apply the Jacobian. 13713565c898SBarry Smith 1372420bcc1bSBarry Smith Not Collective, but the resulting flags will be the same on all MPI processes 13733565c898SBarry Smith 13743565c898SBarry Smith Input Parameter: 1375f6dfbefdSBarry Smith . snes - `SNES` context 13763565c898SBarry Smith 13773565c898SBarry Smith Output Parameters: 1378f6dfbefdSBarry Smith + mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used 1379f6dfbefdSBarry 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 13803565c898SBarry Smith 13813565c898SBarry Smith Level: intermediate 13823565c898SBarry Smith 13831cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUseMatrixFree()`, `MatCreateSNESMF()` 13843565c898SBarry Smith @*/ 1385d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUseMatrixFree(SNES snes, PetscBool *mf_operator, PetscBool *mf) 1386d71ae5a4SJacob Faibussowitsch { 13873565c898SBarry Smith PetscFunctionBegin; 13883565c898SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 13893565c898SBarry Smith if (mf) *mf = snes->mf; 13903565c898SBarry Smith if (mf_operator) *mf_operator = snes->mf_operator; 13913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13923565c898SBarry Smith } 13933565c898SBarry Smith 13943565c898SBarry Smith /*@ 1395420bcc1bSBarry Smith SNESGetIterationNumber - Gets the number of nonlinear iterations completed in the current or most recent `SNESSolve()` 13969b94acceSBarry Smith 1397c7afd0dbSLois Curfman McInnes Not Collective 1398c7afd0dbSLois Curfman McInnes 13999b94acceSBarry Smith Input Parameter: 1400f6dfbefdSBarry Smith . snes - `SNES` context 14019b94acceSBarry Smith 14029b94acceSBarry Smith Output Parameter: 14039b94acceSBarry Smith . iter - iteration number 14049b94acceSBarry Smith 1405dc4c0fb0SBarry Smith Level: intermediate 1406dc4c0fb0SBarry Smith 1407c8228a4eSBarry Smith Notes: 1408c8228a4eSBarry Smith For example, during the computation of iteration 2 this would return 1. 1409c8228a4eSBarry Smith 1410c8228a4eSBarry Smith This is useful for using lagged Jacobians (where one does not recompute the 1411f6dfbefdSBarry Smith Jacobian at each `SNES` iteration). For example, the code 141208405cd6SLois Curfman McInnes .vb 141308405cd6SLois Curfman McInnes ierr = SNESGetIterationNumber(snes,&it); 141408405cd6SLois Curfman McInnes if (!(it % 2)) { 141508405cd6SLois Curfman McInnes [compute Jacobian here] 141608405cd6SLois Curfman McInnes } 141708405cd6SLois Curfman McInnes .ve 1418f6dfbefdSBarry Smith can be used in your function that computes the Jacobian to cause the Jacobian to be 1419f6dfbefdSBarry Smith recomputed every second `SNES` iteration. See also `SNESSetLagJacobian()` 1420c8228a4eSBarry Smith 1421f6dfbefdSBarry Smith After the `SNES` solve is complete this will return the number of nonlinear iterations used. 1422c04deec6SBarry Smith 1423420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetLagJacobian()`, `SNESGetLinearSolveIterations()`, `SNESSetMonitor()` 14249b94acceSBarry Smith @*/ 1425d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetIterationNumber(SNES snes, PetscInt *iter) 1426d71ae5a4SJacob Faibussowitsch { 14273a40ed3dSBarry Smith PetscFunctionBegin; 14280700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 14294f572ea9SToby Isaac PetscAssertPointer(iter, 2); 14309b94acceSBarry Smith *iter = snes->iter; 14313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14329b94acceSBarry Smith } 143374679c65SBarry Smith 1434360c497dSPeter Brune /*@ 1435360c497dSPeter Brune SNESSetIterationNumber - Sets the current iteration number. 1436360c497dSPeter Brune 1437360c497dSPeter Brune Not Collective 1438360c497dSPeter Brune 1439d8d19677SJose E. Roman Input Parameters: 1440f6dfbefdSBarry Smith + snes - `SNES` context 1441a2b725a8SWilliam Gropp - iter - iteration number 1442360c497dSPeter Brune 1443360c497dSPeter Brune Level: developer 1444360c497dSPeter Brune 1445420bcc1bSBarry Smith Note: 1446420bcc1bSBarry Smith This should only be called inside a `SNES` nonlinear solver. 1447420bcc1bSBarry Smith 14481cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetLinearSolveIterations()` 1449360c497dSPeter Brune @*/ 1450d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetIterationNumber(SNES snes, PetscInt iter) 1451d71ae5a4SJacob Faibussowitsch { 1452360c497dSPeter Brune PetscFunctionBegin; 1453360c497dSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 14549566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes)); 1455360c497dSPeter Brune snes->iter = iter; 14569566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes)); 14573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1458360c497dSPeter Brune } 1459360c497dSPeter Brune 14609b94acceSBarry Smith /*@ 1461b850b91aSLisandro Dalcin SNESGetNonlinearStepFailures - Gets the number of unsuccessful steps 1462420bcc1bSBarry Smith attempted by the nonlinear solver in the current or most recent `SNESSolve()` . 14639b94acceSBarry Smith 1464c7afd0dbSLois Curfman McInnes Not Collective 1465c7afd0dbSLois Curfman McInnes 14669b94acceSBarry Smith Input Parameter: 1467f6dfbefdSBarry Smith . snes - `SNES` context 14689b94acceSBarry Smith 14699b94acceSBarry Smith Output Parameter: 14709b94acceSBarry Smith . nfails - number of unsuccessful steps attempted 14719b94acceSBarry Smith 1472dc4c0fb0SBarry Smith Level: intermediate 1473dc4c0fb0SBarry Smith 1474f6dfbefdSBarry Smith Note: 1475f6dfbefdSBarry Smith This counter is reset to zero for each successive call to `SNESSolve()`. 1476c96a6f78SLois Curfman McInnes 14771cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, 1478db781477SPatrick Sanan `SNESSetMaxNonlinearStepFailures()`, `SNESGetMaxNonlinearStepFailures()` 14799b94acceSBarry Smith @*/ 1480d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNonlinearStepFailures(SNES snes, PetscInt *nfails) 1481d71ae5a4SJacob Faibussowitsch { 14823a40ed3dSBarry Smith PetscFunctionBegin; 14830700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 14844f572ea9SToby Isaac PetscAssertPointer(nfails, 2); 148550ffb88aSMatthew Knepley *nfails = snes->numFailures; 14863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 148750ffb88aSMatthew Knepley } 148850ffb88aSMatthew Knepley 148950ffb88aSMatthew Knepley /*@ 1490b850b91aSLisandro Dalcin SNESSetMaxNonlinearStepFailures - Sets the maximum number of unsuccessful steps 1491420bcc1bSBarry Smith attempted by the nonlinear solver before it gives up and returns unconverged or generates an error 149250ffb88aSMatthew Knepley 149350ffb88aSMatthew Knepley Not Collective 149450ffb88aSMatthew Knepley 149550ffb88aSMatthew Knepley Input Parameters: 1496f6dfbefdSBarry Smith + snes - `SNES` context 149777e5a1f9SBarry Smith - maxFails - maximum of unsuccessful steps allowed, use `PETSC_UNLIMITED` to have no limit on the number of failures 149850ffb88aSMatthew Knepley 1499420bcc1bSBarry Smith Options Database Key: 1500420bcc1bSBarry Smith . -snes_max_fail <n> - maximum number of unsuccessful steps allowed 1501420bcc1bSBarry Smith 150250ffb88aSMatthew Knepley Level: intermediate 150350ffb88aSMatthew Knepley 1504420bcc1bSBarry Smith Developer Note: 1505420bcc1bSBarry Smith The options database key is wrong for this function name 1506420bcc1bSBarry Smith 15071cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, 1508db781477SPatrick Sanan `SNESGetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()` 150950ffb88aSMatthew Knepley @*/ 1510d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxNonlinearStepFailures(SNES snes, PetscInt maxFails) 1511d71ae5a4SJacob Faibussowitsch { 151250ffb88aSMatthew Knepley PetscFunctionBegin; 15130700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 151477e5a1f9SBarry Smith 151577e5a1f9SBarry Smith if (maxFails == PETSC_UNLIMITED) { 15161690c2aeSBarry Smith snes->maxFailures = PETSC_INT_MAX; 151777e5a1f9SBarry Smith } else { 151877e5a1f9SBarry Smith PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures"); 151950ffb88aSMatthew Knepley snes->maxFailures = maxFails; 152077e5a1f9SBarry Smith } 15213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 152250ffb88aSMatthew Knepley } 152350ffb88aSMatthew Knepley 152450ffb88aSMatthew Knepley /*@ 1525b850b91aSLisandro Dalcin SNESGetMaxNonlinearStepFailures - Gets the maximum number of unsuccessful steps 1526420bcc1bSBarry Smith attempted by the nonlinear solver before it gives up and returns unconverged or generates an error 152750ffb88aSMatthew Knepley 152850ffb88aSMatthew Knepley Not Collective 152950ffb88aSMatthew Knepley 153050ffb88aSMatthew Knepley Input Parameter: 153120f4b53cSBarry Smith . snes - `SNES` context 153250ffb88aSMatthew Knepley 153350ffb88aSMatthew Knepley Output Parameter: 153450ffb88aSMatthew Knepley . maxFails - maximum of unsuccessful steps 153550ffb88aSMatthew Knepley 153650ffb88aSMatthew Knepley Level: intermediate 153750ffb88aSMatthew Knepley 15381cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, 1539db781477SPatrick Sanan `SNESSetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()` 154050ffb88aSMatthew Knepley @*/ 1541d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxNonlinearStepFailures(SNES snes, PetscInt *maxFails) 1542d71ae5a4SJacob Faibussowitsch { 154350ffb88aSMatthew Knepley PetscFunctionBegin; 15440700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 15454f572ea9SToby Isaac PetscAssertPointer(maxFails, 2); 154650ffb88aSMatthew Knepley *maxFails = snes->maxFailures; 15473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15489b94acceSBarry Smith } 1549a847f771SSatish Balay 15502541af92SBarry Smith /*@ 15512541af92SBarry Smith SNESGetNumberFunctionEvals - Gets the number of user provided function evaluations 1552420bcc1bSBarry Smith done by the `SNES` object in the current or most recent `SNESSolve()` 15532541af92SBarry Smith 15542541af92SBarry Smith Not Collective 15552541af92SBarry Smith 15562541af92SBarry Smith Input Parameter: 1557f6dfbefdSBarry Smith . snes - `SNES` context 15582541af92SBarry Smith 15592541af92SBarry Smith Output Parameter: 15602541af92SBarry Smith . nfuncs - number of evaluations 15612541af92SBarry Smith 15622541af92SBarry Smith Level: intermediate 15632541af92SBarry Smith 1564f6dfbefdSBarry Smith Note: 1565f6dfbefdSBarry Smith Reset every time `SNESSolve()` is called unless `SNESSetCountersReset()` is used. 1566971e163fSPeter Brune 15671cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, `SNESSetCountersReset()` 15682541af92SBarry Smith @*/ 1569d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNumberFunctionEvals(SNES snes, PetscInt *nfuncs) 1570d71ae5a4SJacob Faibussowitsch { 15712541af92SBarry Smith PetscFunctionBegin; 15720700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 15734f572ea9SToby Isaac PetscAssertPointer(nfuncs, 2); 15742541af92SBarry Smith *nfuncs = snes->nfuncs; 15753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15762541af92SBarry Smith } 15772541af92SBarry Smith 15783d4c4710SBarry Smith /*@ 15793d4c4710SBarry Smith SNESGetLinearSolveFailures - Gets the number of failed (non-converged) 1580420bcc1bSBarry Smith linear solvers in the current or most recent `SNESSolve()` 15813d4c4710SBarry Smith 15823d4c4710SBarry Smith Not Collective 15833d4c4710SBarry Smith 15843d4c4710SBarry Smith Input Parameter: 1585f6dfbefdSBarry Smith . snes - `SNES` context 15863d4c4710SBarry Smith 15873d4c4710SBarry Smith Output Parameter: 15883d4c4710SBarry Smith . nfails - number of failed solves 15893d4c4710SBarry Smith 1590f6dfbefdSBarry Smith Options Database Key: 15919d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated 15929d85da0cSMatthew G. Knepley 1593f6dfbefdSBarry Smith Level: intermediate 1594f6dfbefdSBarry Smith 1595f6dfbefdSBarry Smith Note: 1596f6dfbefdSBarry Smith This counter is reset to zero for each successive call to `SNESSolve()`. 15973d4c4710SBarry Smith 15981cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()` 15993d4c4710SBarry Smith @*/ 1600d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveFailures(SNES snes, PetscInt *nfails) 1601d71ae5a4SJacob Faibussowitsch { 16023d4c4710SBarry Smith PetscFunctionBegin; 16030700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 16044f572ea9SToby Isaac PetscAssertPointer(nfails, 2); 16053d4c4710SBarry Smith *nfails = snes->numLinearSolveFailures; 16063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16073d4c4710SBarry Smith } 16083d4c4710SBarry Smith 16093d4c4710SBarry Smith /*@ 16103d4c4710SBarry Smith SNESSetMaxLinearSolveFailures - the number of failed linear solve attempts 1611f6dfbefdSBarry Smith allowed before `SNES` returns with a diverged reason of `SNES_DIVERGED_LINEAR_SOLVE` 16123d4c4710SBarry Smith 1613c3339decSBarry Smith Logically Collective 16143d4c4710SBarry Smith 16153d4c4710SBarry Smith Input Parameters: 1616f6dfbefdSBarry Smith + snes - `SNES` context 161777e5a1f9SBarry Smith - maxFails - maximum allowed linear solve failures, use `PETSC_UNLIMITED` to have no limit on the number of failures 16183d4c4710SBarry Smith 1619f6dfbefdSBarry Smith Options Database Key: 16209d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated 16219d85da0cSMatthew G. Knepley 1622dc4c0fb0SBarry Smith Level: intermediate 1623dc4c0fb0SBarry Smith 1624f6dfbefdSBarry Smith Note: 1625f6dfbefdSBarry Smith By default this is 0; that is `SNES` returns on the first failed linear solve 16263d4c4710SBarry Smith 1627420bcc1bSBarry Smith Developer Note: 1628420bcc1bSBarry Smith The options database key is wrong for this function name 1629420bcc1bSBarry Smith 16301cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()` 16313d4c4710SBarry Smith @*/ 1632d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxLinearSolveFailures(SNES snes, PetscInt maxFails) 1633d71ae5a4SJacob Faibussowitsch { 16343d4c4710SBarry Smith PetscFunctionBegin; 16350700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1636c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, maxFails, 2); 163777e5a1f9SBarry Smith 163877e5a1f9SBarry Smith if (maxFails == PETSC_UNLIMITED) { 16391690c2aeSBarry Smith snes->maxLinearSolveFailures = PETSC_INT_MAX; 164077e5a1f9SBarry Smith } else { 164177e5a1f9SBarry Smith PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures"); 16423d4c4710SBarry Smith snes->maxLinearSolveFailures = maxFails; 164377e5a1f9SBarry Smith } 16443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16453d4c4710SBarry Smith } 16463d4c4710SBarry Smith 16473d4c4710SBarry Smith /*@ 16483d4c4710SBarry Smith SNESGetMaxLinearSolveFailures - gets the maximum number of linear solve failures that 1649f6dfbefdSBarry Smith are allowed before `SNES` returns as unsuccessful 16503d4c4710SBarry Smith 16513d4c4710SBarry Smith Not Collective 16523d4c4710SBarry Smith 16533d4c4710SBarry Smith Input Parameter: 1654f6dfbefdSBarry Smith . snes - `SNES` context 16553d4c4710SBarry Smith 16563d4c4710SBarry Smith Output Parameter: 16573d4c4710SBarry Smith . maxFails - maximum of unsuccessful solves allowed 16583d4c4710SBarry Smith 16593d4c4710SBarry Smith Level: intermediate 16603d4c4710SBarry Smith 1661f6dfbefdSBarry Smith Note: 1662f6dfbefdSBarry Smith By default this is 1; that is `SNES` returns on the first failed linear solve 16633d4c4710SBarry Smith 16641cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, 16653d4c4710SBarry Smith @*/ 1666d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxLinearSolveFailures(SNES snes, PetscInt *maxFails) 1667d71ae5a4SJacob Faibussowitsch { 16683d4c4710SBarry Smith PetscFunctionBegin; 16690700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 16704f572ea9SToby Isaac PetscAssertPointer(maxFails, 2); 16713d4c4710SBarry Smith *maxFails = snes->maxLinearSolveFailures; 16723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16733d4c4710SBarry Smith } 16743d4c4710SBarry Smith 1675c96a6f78SLois Curfman McInnes /*@ 1676b850b91aSLisandro Dalcin SNESGetLinearSolveIterations - Gets the total number of linear iterations 1677420bcc1bSBarry Smith used by the nonlinear solver in the most recent `SNESSolve()` 1678c96a6f78SLois Curfman McInnes 1679c7afd0dbSLois Curfman McInnes Not Collective 1680c7afd0dbSLois Curfman McInnes 1681c96a6f78SLois Curfman McInnes Input Parameter: 1682f6dfbefdSBarry Smith . snes - `SNES` context 1683c96a6f78SLois Curfman McInnes 1684c96a6f78SLois Curfman McInnes Output Parameter: 1685c96a6f78SLois Curfman McInnes . lits - number of linear iterations 1686c96a6f78SLois Curfman McInnes 1687dc4c0fb0SBarry Smith Level: intermediate 1688dc4c0fb0SBarry Smith 1689c96a6f78SLois Curfman McInnes Notes: 1690f6dfbefdSBarry Smith This counter is reset to zero for each successive call to `SNESSolve()` unless `SNESSetCountersReset()` is used. 1691c96a6f78SLois Curfman McInnes 1692f6dfbefdSBarry 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 1693f6dfbefdSBarry Smith then call `KSPGetIterationNumber()` after the failed solve. 1694010be392SBarry Smith 16951cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetIterationNumber()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESSetCountersReset()` 1696c96a6f78SLois Curfman McInnes @*/ 1697d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveIterations(SNES snes, PetscInt *lits) 1698d71ae5a4SJacob Faibussowitsch { 16993a40ed3dSBarry Smith PetscFunctionBegin; 17000700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 17014f572ea9SToby Isaac PetscAssertPointer(lits, 2); 1702c96a6f78SLois Curfman McInnes *lits = snes->linear_its; 17033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1704c96a6f78SLois Curfman McInnes } 1705c96a6f78SLois Curfman McInnes 1706971e163fSPeter Brune /*@ 1707971e163fSPeter Brune SNESSetCountersReset - Sets whether or not the counters for linear iterations and function evaluations 1708f6dfbefdSBarry Smith are reset every time `SNESSolve()` is called. 1709971e163fSPeter Brune 1710c3339decSBarry Smith Logically Collective 1711971e163fSPeter Brune 1712d8d19677SJose E. Roman Input Parameters: 1713f6dfbefdSBarry Smith + snes - `SNES` context 1714f6dfbefdSBarry Smith - reset - whether to reset the counters or not, defaults to `PETSC_TRUE` 1715971e163fSPeter Brune 1716971e163fSPeter Brune Level: developer 1717971e163fSPeter Brune 17181cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()` 1719971e163fSPeter Brune @*/ 1720d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCountersReset(SNES snes, PetscBool reset) 1721d71ae5a4SJacob Faibussowitsch { 1722971e163fSPeter Brune PetscFunctionBegin; 1723971e163fSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1724971e163fSPeter Brune PetscValidLogicalCollectiveBool(snes, reset, 2); 1725971e163fSPeter Brune snes->counters_reset = reset; 17263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1727971e163fSPeter Brune } 1728971e163fSPeter Brune 17292999313aSBarry Smith /*@ 173012b1dd1aSStefano Zampini SNESResetCounters - Reset counters for linear iterations and function evaluations. 173112b1dd1aSStefano Zampini 173212b1dd1aSStefano Zampini Logically Collective 173312b1dd1aSStefano Zampini 173412b1dd1aSStefano Zampini Input Parameters: 173512b1dd1aSStefano Zampini . snes - `SNES` context 173612b1dd1aSStefano Zampini 173712b1dd1aSStefano Zampini Level: developer 173812b1dd1aSStefano Zampini 173912b1dd1aSStefano Zampini Note: 174012b1dd1aSStefano Zampini It honors the flag set with `SNESSetCountersReset()` 174112b1dd1aSStefano Zampini 174212b1dd1aSStefano Zampini .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()` 174312b1dd1aSStefano Zampini @*/ 174412b1dd1aSStefano Zampini PetscErrorCode SNESResetCounters(SNES snes) 174512b1dd1aSStefano Zampini { 174612b1dd1aSStefano Zampini PetscFunctionBegin; 174712b1dd1aSStefano Zampini PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 174812b1dd1aSStefano Zampini if (snes->counters_reset) { 174912b1dd1aSStefano Zampini snes->nfuncs = 0; 175012b1dd1aSStefano Zampini snes->linear_its = 0; 175112b1dd1aSStefano Zampini snes->numFailures = 0; 175212b1dd1aSStefano Zampini } 175312b1dd1aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 175412b1dd1aSStefano Zampini } 175512b1dd1aSStefano Zampini 175612b1dd1aSStefano Zampini /*@ 1757f6dfbefdSBarry Smith SNESSetKSP - Sets a `KSP` context for the `SNES` object to use 17582999313aSBarry Smith 1759420bcc1bSBarry Smith Not Collective, but the `SNES` and `KSP` objects must live on the same `MPI_Comm` 17602999313aSBarry Smith 17612999313aSBarry Smith Input Parameters: 1762f6dfbefdSBarry Smith + snes - the `SNES` context 1763f6dfbefdSBarry Smith - ksp - the `KSP` context 17642999313aSBarry Smith 1765dc4c0fb0SBarry Smith Level: developer 1766dc4c0fb0SBarry Smith 17672999313aSBarry Smith Notes: 1768f6dfbefdSBarry Smith The `SNES` object already has its `KSP` object, you can obtain with `SNESGetKSP()` 17692999313aSBarry Smith so this routine is rarely needed. 17702999313aSBarry Smith 1771f6dfbefdSBarry Smith The `KSP` object that is already in the `SNES` object has its reference count 1772420bcc1bSBarry Smith decreased by one when this is called. 17732999313aSBarry Smith 177442747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `KSP`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()` 17752999313aSBarry Smith @*/ 1776d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetKSP(SNES snes, KSP ksp) 1777d71ae5a4SJacob Faibussowitsch { 17782999313aSBarry Smith PetscFunctionBegin; 17790700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 17800700a824SBarry Smith PetscValidHeaderSpecific(ksp, KSP_CLASSID, 2); 17812999313aSBarry Smith PetscCheckSameComm(snes, 1, ksp, 2); 17829566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)ksp)); 17839566063dSJacob Faibussowitsch if (snes->ksp) PetscCall(PetscObjectDereference((PetscObject)snes->ksp)); 17842999313aSBarry Smith snes->ksp = ksp; 17853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17862999313aSBarry Smith } 17872999313aSBarry Smith 178852baeb72SSatish Balay /*@ 178977e5a1f9SBarry Smith SNESParametersInitialize - Sets all the parameters in `snes` to their default value (when `SNESCreate()` was called) if they 179077e5a1f9SBarry Smith currently contain default values 179177e5a1f9SBarry Smith 179277e5a1f9SBarry Smith Collective 179377e5a1f9SBarry Smith 179477e5a1f9SBarry Smith Input Parameter: 179577e5a1f9SBarry Smith . snes - the `SNES` object 179677e5a1f9SBarry Smith 179777e5a1f9SBarry Smith Level: developer 179877e5a1f9SBarry Smith 179977e5a1f9SBarry Smith Developer Note: 180077e5a1f9SBarry Smith This is called by all the `SNESCreate_XXX()` routines. 180177e5a1f9SBarry Smith 180277e5a1f9SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`, 180377e5a1f9SBarry Smith `PetscObjectParameterSetDefault()` 180477e5a1f9SBarry Smith @*/ 180577e5a1f9SBarry Smith PetscErrorCode SNESParametersInitialize(SNES snes) 180677e5a1f9SBarry Smith { 180777e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, max_its, 50); 180877e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, max_funcs, 10000); 180977e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, rtol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8); 181077e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, abstol, PetscDefined(USE_REAL_SINGLE) ? 1.e-25 : 1.e-50); 181177e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, stol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8); 181277e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, divtol, 1.e4); 181377e5a1f9SBarry Smith return PETSC_SUCCESS; 181477e5a1f9SBarry Smith } 181577e5a1f9SBarry Smith 181677e5a1f9SBarry Smith /*@ 1817dc4c0fb0SBarry Smith SNESCreate - Creates a nonlinear solver context used to manage a set of nonlinear solves 18189b94acceSBarry Smith 1819d083f849SBarry Smith Collective 1820c7afd0dbSLois Curfman McInnes 1821f6dfbefdSBarry Smith Input Parameter: 1822906ed7ccSBarry Smith . comm - MPI communicator 18239b94acceSBarry Smith 18249b94acceSBarry Smith Output Parameter: 182520f4b53cSBarry Smith . outsnes - the new `SNES` context 18269b94acceSBarry Smith 1827c7afd0dbSLois Curfman McInnes Options Database Keys: 18287addb90fSBarry Smith + -snes_mf - Activates default matrix-free Jacobian-vector products, and no matrix to construct a preconditioner 18297addb90fSBarry Smith . -snes_mf_operator - Activates default matrix-free Jacobian-vector products, and a user-provided matrix as set by `SNESSetJacobian()` 1830dc4c0fb0SBarry Smith . -snes_fd_coloring - uses a relative fast computation of the Jacobian using finite differences and a graph coloring 1831c7afd0dbSLois Curfman McInnes - -snes_fd - Uses (slow!) finite differences to compute Jacobian 1832c1f60f51SBarry Smith 183336851e7fSLois Curfman McInnes Level: beginner 183436851e7fSLois Curfman McInnes 183595452b02SPatrick Sanan Developer Notes: 1836f6dfbefdSBarry Smith `SNES` always creates a `KSP` object even though many `SNES` methods do not use it. This is 1837efd4aadfSBarry Smith unfortunate and should be fixed at some point. The flag snes->usesksp indicates if the 1838f6dfbefdSBarry Smith particular method does use `KSP` and regulates if the information about the `KSP` is printed 1839f6dfbefdSBarry Smith in `SNESView()`. 1840efd4aadfSBarry Smith 1841f6dfbefdSBarry Smith `TSSetFromOptions()` does call `SNESSetFromOptions()` which can lead to users being confused 1842f6dfbefdSBarry Smith by help messages about meaningless `SNES` options. 1843f6dfbefdSBarry Smith 18447addb90fSBarry Smith `SNES` always creates the `snes->kspconvctx` even though it is used by only one type. This should be fixed. 1845efd4aadfSBarry Smith 1846e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()` 18479b94acceSBarry Smith @*/ 1848d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESCreate(MPI_Comm comm, SNES *outsnes) 1849d71ae5a4SJacob Faibussowitsch { 18509b94acceSBarry Smith SNES snes; 1851fa9f3622SBarry Smith SNESKSPEW *kctx; 185237fcc0dbSBarry Smith 18533a40ed3dSBarry Smith PetscFunctionBegin; 18544f572ea9SToby Isaac PetscAssertPointer(outsnes, 2); 18559566063dSJacob Faibussowitsch PetscCall(SNESInitializePackage()); 18568ba1e511SMatthew Knepley 18579566063dSJacob Faibussowitsch PetscCall(PetscHeaderCreate(snes, SNES_CLASSID, "SNES", "Nonlinear solver", "SNES", comm, SNESDestroy, SNESView)); 18588d359177SBarry Smith snes->ops->converged = SNESConvergedDefault; 18592c155ee1SBarry Smith snes->usesksp = PETSC_TRUE; 18609b94acceSBarry Smith snes->norm = 0.0; 1861c1e67a49SFande Kong snes->xnorm = 0.0; 1862c1e67a49SFande Kong snes->ynorm = 0.0; 1863365a6726SPeter Brune snes->normschedule = SNES_NORM_ALWAYS; 18646c67d002SPeter Brune snes->functype = SNES_FUNCTION_DEFAULT; 1865b4874afaSBarry Smith snes->ttol = 0.0; 186677e5a1f9SBarry Smith 1867e37c518bSBarry Smith snes->rnorm0 = 0; 18689b94acceSBarry Smith snes->nfuncs = 0; 186950ffb88aSMatthew Knepley snes->numFailures = 0; 187050ffb88aSMatthew Knepley snes->maxFailures = 1; 18717a00f4a9SLois Curfman McInnes snes->linear_its = 0; 1872e35cf81dSBarry Smith snes->lagjacobian = 1; 187337ec4e1aSPeter Brune snes->jac_iter = 0; 187437ec4e1aSPeter Brune snes->lagjac_persist = PETSC_FALSE; 1875a8054027SBarry Smith snes->lagpreconditioner = 1; 187637ec4e1aSPeter Brune snes->pre_iter = 0; 187737ec4e1aSPeter Brune snes->lagpre_persist = PETSC_FALSE; 1878639f9d9dSBarry Smith snes->numbermonitors = 0; 1879c4421ceaSFande Kong snes->numberreasonviews = 0; 18809e5d0892SLisandro Dalcin snes->data = NULL; 18814dc4c822SBarry Smith snes->setupcalled = PETSC_FALSE; 1882186905e3SBarry Smith snes->ksp_ewconv = PETSC_FALSE; 18836f24a144SLois Curfman McInnes snes->nwork = 0; 18849e5d0892SLisandro Dalcin snes->work = NULL; 188558c9b817SLisandro Dalcin snes->nvwork = 0; 18869e5d0892SLisandro Dalcin snes->vwork = NULL; 1887758f92a0SBarry Smith snes->conv_hist_len = 0; 1888758f92a0SBarry Smith snes->conv_hist_max = 0; 18890298fd71SBarry Smith snes->conv_hist = NULL; 18900298fd71SBarry Smith snes->conv_hist_its = NULL; 1891758f92a0SBarry Smith snes->conv_hist_reset = PETSC_TRUE; 1892971e163fSPeter Brune snes->counters_reset = PETSC_TRUE; 1893e4ed7901SPeter Brune snes->vec_func_init_set = PETSC_FALSE; 1894184914b5SBarry Smith snes->reason = SNES_CONVERGED_ITERATING; 1895efd4aadfSBarry Smith snes->npcside = PC_RIGHT; 1896b3cd9a81SMatthew G. Knepley snes->setfromoptionscalled = 0; 1897c40d0f55SPeter Brune 1898d8f46077SPeter Brune snes->mf = PETSC_FALSE; 1899d8f46077SPeter Brune snes->mf_operator = PETSC_FALSE; 1900d8f46077SPeter Brune snes->mf_version = 1; 1901d8f46077SPeter Brune 19023d4c4710SBarry Smith snes->numLinearSolveFailures = 0; 19033d4c4710SBarry Smith snes->maxLinearSolveFailures = 1; 19043d4c4710SBarry Smith 1905349187a7SBarry Smith snes->vizerotolerance = 1.e-8; 190676bd3646SJed Brown snes->checkjacdomainerror = PetscDefined(USE_DEBUG) ? PETSC_TRUE : PETSC_FALSE; 1907349187a7SBarry Smith 19084fc747eaSLawrence Mitchell /* Set this to true if the implementation of SNESSolve_XXX does compute the residual at the final solution. */ 19094fc747eaSLawrence Mitchell snes->alwayscomputesfinalresidual = PETSC_FALSE; 19104fc747eaSLawrence Mitchell 19119b94acceSBarry Smith /* Create context to compute Eisenstat-Walker relative tolerance for KSP */ 19124dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&kctx)); 1913f5af7f23SKarl Rupp 1914835f2295SStefano Zampini snes->kspconvctx = kctx; 19159b94acceSBarry Smith kctx->version = 2; 19160f0abf79SStefano Zampini kctx->rtol_0 = 0.3; /* Eisenstat and Walker suggest rtol_0=.5, but 19179b94acceSBarry Smith this was too large for some test cases */ 191875567043SBarry Smith kctx->rtol_last = 0.0; 19190f0abf79SStefano Zampini kctx->rtol_max = 0.9; 19209b94acceSBarry Smith kctx->gamma = 1.0; 19210f0abf79SStefano Zampini kctx->alpha = 0.5 * (1.0 + PetscSqrtReal(5.0)); 192271f87433Sdalcinl kctx->alpha2 = kctx->alpha; 19230f0abf79SStefano Zampini kctx->threshold = 0.1; 192475567043SBarry Smith kctx->lresid_last = 0.0; 192575567043SBarry Smith kctx->norm_last = 0.0; 19269b94acceSBarry Smith 19270f0abf79SStefano Zampini kctx->rk_last = 0.0; 19280f0abf79SStefano Zampini kctx->rk_last_2 = 0.0; 19290f0abf79SStefano Zampini kctx->rtol_last_2 = 0.0; 19300f0abf79SStefano Zampini kctx->v4_p1 = 0.1; 19310f0abf79SStefano Zampini kctx->v4_p2 = 0.4; 19320f0abf79SStefano Zampini kctx->v4_p3 = 0.7; 19330f0abf79SStefano Zampini kctx->v4_m1 = 0.8; 19340f0abf79SStefano Zampini kctx->v4_m2 = 0.5; 19350f0abf79SStefano Zampini kctx->v4_m3 = 0.1; 19360f0abf79SStefano Zampini kctx->v4_m4 = 0.5; 19370f0abf79SStefano Zampini 1938b50c806fSBarry Smith PetscCall(SNESParametersInitialize(snes)); 19399b94acceSBarry Smith *outsnes = snes; 19403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19419b94acceSBarry Smith } 19429b94acceSBarry Smith 19439b94acceSBarry Smith /*@C 19449b94acceSBarry Smith SNESSetFunction - Sets the function evaluation routine and function 1945f6dfbefdSBarry Smith vector for use by the `SNES` routines in solving systems of nonlinear 19469b94acceSBarry Smith equations. 19479b94acceSBarry Smith 1948c3339decSBarry Smith Logically Collective 1949fee21e36SBarry Smith 1950c7afd0dbSLois Curfman McInnes Input Parameters: 1951f6dfbefdSBarry Smith + snes - the `SNES` context 1952dc4c0fb0SBarry Smith . r - vector to store function values, may be `NULL` 19538434afd1SBarry Smith . f - function evaluation routine; for calling sequence see `SNESFunctionFn` 1954c7afd0dbSLois Curfman McInnes - ctx - [optional] user-defined context for private data for the 1955dc4c0fb0SBarry Smith function evaluation routine (may be `NULL`) 19569b94acceSBarry Smith 195736851e7fSLois Curfman McInnes Level: beginner 195836851e7fSLois Curfman McInnes 19598434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetPicard()`, `SNESFunctionFn` 19609b94acceSBarry Smith @*/ 19618434afd1SBarry Smith PetscErrorCode SNESSetFunction(SNES snes, Vec r, SNESFunctionFn *f, void *ctx) 1962d71ae5a4SJacob Faibussowitsch { 19636cab3a1bSJed Brown DM dm; 19646cab3a1bSJed Brown 19653a40ed3dSBarry Smith PetscFunctionBegin; 19660700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1967d2a683ecSLisandro Dalcin if (r) { 1968d2a683ecSLisandro Dalcin PetscValidHeaderSpecific(r, VEC_CLASSID, 2); 1969d2a683ecSLisandro Dalcin PetscCheckSameComm(snes, 1, r, 2); 19709566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)r)); 19719566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_func)); 197285385478SLisandro Dalcin snes->vec_func = r; 1973d2a683ecSLisandro Dalcin } 19749566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 19759566063dSJacob Faibussowitsch PetscCall(DMSNESSetFunction(dm, f, ctx)); 197648a46eb9SPierre Jolivet if (f == SNESPicardComputeFunction) PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx)); 19773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19789b94acceSBarry Smith } 19799b94acceSBarry Smith 1980e4ed7901SPeter Brune /*@C 19810b4db180SJacob Faibussowitsch SNESSetInitialFunction - Set an already computed function evaluation at the initial guess to be reused by `SNESSolve()`. 1982e4ed7901SPeter Brune 1983c3339decSBarry Smith Logically Collective 1984e4ed7901SPeter Brune 1985e4ed7901SPeter Brune Input Parameters: 1986f6dfbefdSBarry Smith + snes - the `SNES` context 1987e4ed7901SPeter Brune - f - vector to store function value 1988e4ed7901SPeter Brune 1989dc4c0fb0SBarry Smith Level: developer 1990dc4c0fb0SBarry Smith 1991e4ed7901SPeter Brune Notes: 1992e4ed7901SPeter Brune This should not be modified during the solution procedure. 1993e4ed7901SPeter Brune 1994f6dfbefdSBarry Smith This is used extensively in the `SNESFAS` hierarchy and in nonlinear preconditioning. 1995e4ed7901SPeter Brune 19961cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetInitialFunctionNorm()` 1997e4ed7901SPeter Brune @*/ 1998d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetInitialFunction(SNES snes, Vec f) 1999d71ae5a4SJacob Faibussowitsch { 2000e4ed7901SPeter Brune Vec vec_func; 2001e4ed7901SPeter Brune 2002e4ed7901SPeter Brune PetscFunctionBegin; 2003e4ed7901SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2004e4ed7901SPeter Brune PetscValidHeaderSpecific(f, VEC_CLASSID, 2); 2005e4ed7901SPeter Brune PetscCheckSameComm(snes, 1, f, 2); 2006efd4aadfSBarry Smith if (snes->npcside == PC_LEFT && snes->functype == SNES_FUNCTION_PRECONDITIONED) { 2007902f982fSPeter Brune snes->vec_func_init_set = PETSC_FALSE; 20083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2009902f982fSPeter Brune } 20109566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &vec_func, NULL, NULL)); 20119566063dSJacob Faibussowitsch PetscCall(VecCopy(f, vec_func)); 2012f5af7f23SKarl Rupp 2013217b9c2eSPeter Brune snes->vec_func_init_set = PETSC_TRUE; 20143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2015e4ed7901SPeter Brune } 2016e4ed7901SPeter Brune 2017534ebe21SPeter Brune /*@ 2018f6dfbefdSBarry Smith SNESSetNormSchedule - Sets the `SNESNormSchedule` used in convergence and monitoring 2019f6dfbefdSBarry Smith of the `SNES` method, when norms are computed in the solving process 2020534ebe21SPeter Brune 2021c3339decSBarry Smith Logically Collective 2022534ebe21SPeter Brune 2023534ebe21SPeter Brune Input Parameters: 2024f6dfbefdSBarry Smith + snes - the `SNES` context 2025365a6726SPeter Brune - normschedule - the frequency of norm computation 2026534ebe21SPeter Brune 2027517f1916SMatthew G. Knepley Options Database Key: 202867b8a455SSatish Balay . -snes_norm_schedule <none, always, initialonly, finalonly, initialfinalonly> - set the schedule 2029517f1916SMatthew G. Knepley 2030dc4c0fb0SBarry Smith Level: advanced 2031dc4c0fb0SBarry Smith 2032534ebe21SPeter Brune Notes: 2033f6dfbefdSBarry Smith Only certain `SNES` methods support certain `SNESNormSchedules`. Most require evaluation 2034534ebe21SPeter Brune of the nonlinear function and the taking of its norm at every iteration to 2035534ebe21SPeter Brune even ensure convergence at all. However, methods such as custom Gauss-Seidel methods 2036f6dfbefdSBarry Smith `SNESNGS` and the like do not require the norm of the function to be computed, and therefore 2037534ebe21SPeter Brune may either be monitored for convergence or not. As these are often used as nonlinear 2038534ebe21SPeter Brune preconditioners, monitoring the norm of their error is not a useful enterprise within 2039534ebe21SPeter Brune their solution. 2040534ebe21SPeter Brune 2041e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNESNormSchedule`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()` 2042534ebe21SPeter Brune @*/ 2043d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNormSchedule(SNES snes, SNESNormSchedule normschedule) 2044d71ae5a4SJacob Faibussowitsch { 2045534ebe21SPeter Brune PetscFunctionBegin; 2046534ebe21SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2047365a6726SPeter Brune snes->normschedule = normschedule; 20483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2049534ebe21SPeter Brune } 2050534ebe21SPeter Brune 2051534ebe21SPeter Brune /*@ 2052f6dfbefdSBarry Smith SNESGetNormSchedule - Gets the `SNESNormSchedule` used in convergence and monitoring 2053f6dfbefdSBarry Smith of the `SNES` method. 2054534ebe21SPeter Brune 2055c3339decSBarry Smith Logically Collective 2056534ebe21SPeter Brune 2057534ebe21SPeter Brune Input Parameters: 2058f6dfbefdSBarry Smith + snes - the `SNES` context 2059365a6726SPeter Brune - normschedule - the type of the norm used 2060534ebe21SPeter Brune 2061534ebe21SPeter Brune Level: advanced 2062534ebe21SPeter Brune 20631cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 2064534ebe21SPeter Brune @*/ 2065d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNormSchedule(SNES snes, SNESNormSchedule *normschedule) 2066d71ae5a4SJacob Faibussowitsch { 2067534ebe21SPeter Brune PetscFunctionBegin; 2068534ebe21SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2069365a6726SPeter Brune *normschedule = snes->normschedule; 20703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2071534ebe21SPeter Brune } 2072534ebe21SPeter Brune 2073c5ce4427SMatthew G. Knepley /*@ 2074c5ce4427SMatthew G. Knepley SNESSetFunctionNorm - Sets the last computed residual norm. 2075c5ce4427SMatthew G. Knepley 2076c3339decSBarry Smith Logically Collective 2077c5ce4427SMatthew G. Knepley 2078c5ce4427SMatthew G. Knepley Input Parameters: 2079f6dfbefdSBarry Smith + snes - the `SNES` context 2080f6dfbefdSBarry Smith - norm - the value of the norm 2081c5ce4427SMatthew G. Knepley 2082c5ce4427SMatthew G. Knepley Level: developer 2083c5ce4427SMatthew G. Knepley 20841cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 2085c5ce4427SMatthew G. Knepley @*/ 2086d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionNorm(SNES snes, PetscReal norm) 2087d71ae5a4SJacob Faibussowitsch { 2088c5ce4427SMatthew G. Knepley PetscFunctionBegin; 2089c5ce4427SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2090c5ce4427SMatthew G. Knepley snes->norm = norm; 20913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2092c5ce4427SMatthew G. Knepley } 2093c5ce4427SMatthew G. Knepley 2094c5ce4427SMatthew G. Knepley /*@ 2095c5ce4427SMatthew G. Knepley SNESGetFunctionNorm - Gets the last computed norm of the residual 2096c5ce4427SMatthew G. Knepley 2097c5ce4427SMatthew G. Knepley Not Collective 2098c5ce4427SMatthew G. Knepley 2099c5ce4427SMatthew G. Knepley Input Parameter: 2100f6dfbefdSBarry Smith . snes - the `SNES` context 2101c5ce4427SMatthew G. Knepley 2102c5ce4427SMatthew G. Knepley Output Parameter: 2103c5ce4427SMatthew G. Knepley . norm - the last computed residual norm 2104c5ce4427SMatthew G. Knepley 2105c5ce4427SMatthew G. Knepley Level: developer 2106c5ce4427SMatthew G. Knepley 21071cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 2108c5ce4427SMatthew G. Knepley @*/ 2109d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionNorm(SNES snes, PetscReal *norm) 2110d71ae5a4SJacob Faibussowitsch { 2111c5ce4427SMatthew G. Knepley PetscFunctionBegin; 2112c5ce4427SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 21134f572ea9SToby Isaac PetscAssertPointer(norm, 2); 2114c5ce4427SMatthew G. Knepley *norm = snes->norm; 21153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2116c5ce4427SMatthew G. Knepley } 2117c5ce4427SMatthew G. Knepley 2118c1e67a49SFande Kong /*@ 2119f6dfbefdSBarry Smith SNESGetUpdateNorm - Gets the last computed norm of the solution update 2120c1e67a49SFande Kong 2121c1e67a49SFande Kong Not Collective 2122c1e67a49SFande Kong 2123c1e67a49SFande Kong Input Parameter: 2124f6dfbefdSBarry Smith . snes - the `SNES` context 2125c1e67a49SFande Kong 2126c1e67a49SFande Kong Output Parameter: 2127c1e67a49SFande Kong . ynorm - the last computed update norm 2128c1e67a49SFande Kong 2129c1e67a49SFande Kong Level: developer 2130c1e67a49SFande Kong 2131f6dfbefdSBarry Smith Note: 2132f6dfbefdSBarry Smith The new solution is the current solution plus the update, so this norm is an indication of the size of the update 2133f6dfbefdSBarry Smith 21341cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()` 2135c1e67a49SFande Kong @*/ 2136d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUpdateNorm(SNES snes, PetscReal *ynorm) 2137d71ae5a4SJacob Faibussowitsch { 2138c1e67a49SFande Kong PetscFunctionBegin; 2139c1e67a49SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 21404f572ea9SToby Isaac PetscAssertPointer(ynorm, 2); 2141c1e67a49SFande Kong *ynorm = snes->ynorm; 21423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2143c1e67a49SFande Kong } 2144c1e67a49SFande Kong 2145c1e67a49SFande Kong /*@ 21464591eaf2SFande Kong SNESGetSolutionNorm - Gets the last computed norm of the solution 2147c1e67a49SFande Kong 2148c1e67a49SFande Kong Not Collective 2149c1e67a49SFande Kong 2150c1e67a49SFande Kong Input Parameter: 2151f6dfbefdSBarry Smith . snes - the `SNES` context 2152c1e67a49SFande Kong 2153c1e67a49SFande Kong Output Parameter: 2154c1e67a49SFande Kong . xnorm - the last computed solution norm 2155c1e67a49SFande Kong 2156c1e67a49SFande Kong Level: developer 2157c1e67a49SFande Kong 21581cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`, `SNESGetUpdateNorm()` 2159c1e67a49SFande Kong @*/ 2160d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionNorm(SNES snes, PetscReal *xnorm) 2161d71ae5a4SJacob Faibussowitsch { 2162c1e67a49SFande Kong PetscFunctionBegin; 2163c1e67a49SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 21644f572ea9SToby Isaac PetscAssertPointer(xnorm, 2); 2165c1e67a49SFande Kong *xnorm = snes->xnorm; 21663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2167c1e67a49SFande Kong } 2168c1e67a49SFande Kong 2169cc4c1da9SBarry Smith /*@ 2170f6dfbefdSBarry Smith SNESSetFunctionType - Sets the `SNESFunctionType` 2171f6dfbefdSBarry Smith of the `SNES` method. 217247073ea2SPeter Brune 2173c3339decSBarry Smith Logically Collective 217447073ea2SPeter Brune 217547073ea2SPeter Brune Input Parameters: 2176f6dfbefdSBarry Smith + snes - the `SNES` context 2177f6dfbefdSBarry Smith - type - the function type 217847073ea2SPeter Brune 217947073ea2SPeter Brune Level: developer 218047073ea2SPeter Brune 2181420bcc1bSBarry Smith Values of the function type\: 2182f6dfbefdSBarry Smith + `SNES_FUNCTION_DEFAULT` - the default for the given `SNESType` 2183f6dfbefdSBarry Smith . `SNES_FUNCTION_UNPRECONDITIONED` - an unpreconditioned function evaluation (this is the function provided with `SNESSetFunction()` 2184f6dfbefdSBarry Smith - `SNES_FUNCTION_PRECONDITIONED` - a transformation of the function provided with `SNESSetFunction()` 2185f6dfbefdSBarry Smith 2186420bcc1bSBarry Smith Note: 2187f6dfbefdSBarry Smith Different `SNESType`s use this value in different ways 2188f6dfbefdSBarry Smith 21891cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFunctionType`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 219047073ea2SPeter Brune @*/ 2191d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionType(SNES snes, SNESFunctionType type) 2192d71ae5a4SJacob Faibussowitsch { 219347073ea2SPeter Brune PetscFunctionBegin; 219447073ea2SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 219547073ea2SPeter Brune snes->functype = type; 21963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 219747073ea2SPeter Brune } 219847073ea2SPeter Brune 2199cc4c1da9SBarry Smith /*@ 2200f6dfbefdSBarry Smith SNESGetFunctionType - Gets the `SNESFunctionType` used in convergence and monitoring set with `SNESSetFunctionType()` 220147073ea2SPeter Brune of the SNES method. 220247073ea2SPeter Brune 2203c3339decSBarry Smith Logically Collective 220447073ea2SPeter Brune 220547073ea2SPeter Brune Input Parameters: 2206f6dfbefdSBarry Smith + snes - the `SNES` context 2207f6dfbefdSBarry Smith - type - the type of the function evaluation, see `SNESSetFunctionType()` 220847073ea2SPeter Brune 220947073ea2SPeter Brune Level: advanced 221047073ea2SPeter Brune 22111cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetFunctionType()`, `SNESFunctionType`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 221247073ea2SPeter Brune @*/ 2213d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionType(SNES snes, SNESFunctionType *type) 2214d71ae5a4SJacob Faibussowitsch { 221547073ea2SPeter Brune PetscFunctionBegin; 221647073ea2SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 221747073ea2SPeter Brune *type = snes->functype; 22183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2219534ebe21SPeter Brune } 2220534ebe21SPeter Brune 2221c79ef259SPeter Brune /*@C 2222be95d8f1SBarry Smith SNESSetNGS - Sets the user nonlinear Gauss-Seidel routine for 2223c79ef259SPeter Brune use with composed nonlinear solvers. 2224c79ef259SPeter Brune 2225c79ef259SPeter Brune Input Parameters: 22269bcc50f1SBarry Smith + snes - the `SNES` context, usually of the `SNESType` `SNESNGS` 22278434afd1SBarry Smith . f - function evaluation routine to apply Gauss-Seidel, see `SNESNGSFn` for calling sequence 222877e5a1f9SBarry Smith - ctx - [optional] user-defined context for private data for the smoother evaluation routine (may be `NULL`) 2229c79ef259SPeter Brune 2230dc4c0fb0SBarry Smith Level: intermediate 2231dc4c0fb0SBarry Smith 2232f6dfbefdSBarry Smith Note: 2233f6dfbefdSBarry Smith The `SNESNGS` routines are used by the composed nonlinear solver to generate 2234f6dfbefdSBarry Smith a problem appropriate update to the solution, particularly `SNESFAS`. 2235c79ef259SPeter Brune 22368434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGS`, `SNESGetNGS()`, `SNESNCG`, `SNESGetFunction()`, `SNESComputeNGS()`, `SNESNGSFn` 2237c79ef259SPeter Brune @*/ 22388434afd1SBarry Smith PetscErrorCode SNESSetNGS(SNES snes, SNESNGSFn *f, void *ctx) 2239d71ae5a4SJacob Faibussowitsch { 22406cab3a1bSJed Brown DM dm; 22416cab3a1bSJed Brown 2242646217ecSPeter Brune PetscFunctionBegin; 22436cab3a1bSJed Brown PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 22449566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 22459566063dSJacob Faibussowitsch PetscCall(DMSNESSetNGS(dm, f, ctx)); 22463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2247646217ecSPeter Brune } 2248646217ecSPeter Brune 2249bbc1464cSBarry Smith /* 2250bbc1464cSBarry Smith This is used for -snes_mf_operator; it uses a duplicate of snes->jacobian_pre because snes->jacobian_pre cannot be 2251bbc1464cSBarry Smith changed during the KSPSolve() 2252bbc1464cSBarry Smith */ 2253d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeMFFunction(SNES snes, Vec x, Vec f, void *ctx) 2254d71ae5a4SJacob Faibussowitsch { 2255bbc1464cSBarry Smith DM dm; 2256bbc1464cSBarry Smith DMSNES sdm; 2257bbc1464cSBarry Smith 2258bbc1464cSBarry Smith PetscFunctionBegin; 22599566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 22609566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 2261bbc1464cSBarry Smith /* A(x)*x - b(x) */ 2262bbc1464cSBarry Smith if (sdm->ops->computepfunction) { 2263792fecdfSBarry Smith PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx)); 22649566063dSJacob Faibussowitsch PetscCall(VecScale(f, -1.0)); 22650df40c35SBarry Smith /* Cannot share nonzero pattern because of the possible use of SNESComputeJacobianDefault() */ 2266ef1023bdSBarry Smith if (!snes->picard) PetscCall(MatDuplicate(snes->jacobian_pre, MAT_DO_NOT_COPY_VALUES, &snes->picard)); 2267792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx)); 22689566063dSJacob Faibussowitsch PetscCall(MatMultAdd(snes->picard, x, f, f)); 2269bbc1464cSBarry Smith } else { 2270792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx)); 22719566063dSJacob Faibussowitsch PetscCall(MatMult(snes->picard, x, f)); 2272bbc1464cSBarry Smith } 22733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2274bbc1464cSBarry Smith } 2275bbc1464cSBarry Smith 2276d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeFunction(SNES snes, Vec x, Vec f, void *ctx) 2277d71ae5a4SJacob Faibussowitsch { 2278e03ab78fSPeter Brune DM dm; 2279942e3340SBarry Smith DMSNES sdm; 22806cab3a1bSJed Brown 22818b0a5094SBarry Smith PetscFunctionBegin; 22829566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 22839566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 22848b0a5094SBarry Smith /* A(x)*x - b(x) */ 2285bbc1464cSBarry Smith if (sdm->ops->computepfunction) { 2286792fecdfSBarry Smith PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx)); 22879566063dSJacob Faibussowitsch PetscCall(VecScale(f, -1.0)); 2288792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx)); 22899566063dSJacob Faibussowitsch PetscCall(MatMultAdd(snes->jacobian_pre, x, f, f)); 2290bbc1464cSBarry Smith } else { 2291792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx)); 22929566063dSJacob Faibussowitsch PetscCall(MatMult(snes->jacobian_pre, x, f)); 2293bbc1464cSBarry Smith } 22943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22958b0a5094SBarry Smith } 22968b0a5094SBarry Smith 2297d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeJacobian(SNES snes, Vec x1, Mat J, Mat B, void *ctx) 2298d71ae5a4SJacob Faibussowitsch { 22998b0a5094SBarry Smith PetscFunctionBegin; 2300e03ab78fSPeter Brune /* the jacobian matrix should be pre-filled in SNESPicardComputeFunction */ 2301bbc1464cSBarry Smith /* must assembly if matrix-free to get the last SNES solution */ 23029566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 23039566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 23043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23058b0a5094SBarry Smith } 23068b0a5094SBarry Smith 23078b0a5094SBarry Smith /*@C 23081d27aa22SBarry Smith SNESSetPicard - Use `SNES` to solve the system $A(x) x = bp(x) + b $ via a Picard type iteration (Picard linearization) 23098b0a5094SBarry Smith 2310c3339decSBarry Smith Logically Collective 23118b0a5094SBarry Smith 23128b0a5094SBarry Smith Input Parameters: 2313f6dfbefdSBarry Smith + snes - the `SNES` context 2314dc4c0fb0SBarry Smith . r - vector to store function values, may be `NULL` 23158434afd1SBarry Smith . bp - function evaluation routine, may be `NULL`, for the calling sequence see `SNESFunctionFn` 231626a11704SBarry Smith . Amat - matrix with which $A(x) x - bp(x) - b$ is to be computed 2317dc4c0fb0SBarry Smith . Pmat - matrix from which preconditioner is computed (usually the same as `Amat`) 23188434afd1SBarry Smith . J - function to compute matrix values, for the calling sequence see `SNESJacobianFn` 2319dc4c0fb0SBarry Smith - ctx - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`) 2320dc4c0fb0SBarry Smith 2321dc4c0fb0SBarry Smith Level: intermediate 23228b0a5094SBarry Smith 23238b0a5094SBarry Smith Notes: 232426a11704SBarry Smith It is often better to provide the nonlinear function $F()$ and some approximation to its Jacobian directly and use 2325f450aa47SBarry 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. 2326f450aa47SBarry Smith 2327f6dfbefdSBarry Smith One can call `SNESSetPicard()` or `SNESSetFunction()` (and possibly `SNESSetJacobian()`) but cannot call both 23288b0a5094SBarry Smith 23291d27aa22SBarry 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}$. 23301d27aa22SBarry Smith When an exact solver is used this corresponds to the "classic" Picard $A(x^{n}) x^{n+1} = bp(x^{n}) + b$ iteration. 23318b0a5094SBarry Smith 233226a11704SBarry Smith Run with `-snes_mf_operator` to solve the system with Newton's method using $A(x^{n})$ to construct the preconditioner. 23338b0a5094SBarry Smith 23340d04baf8SBarry Smith We implement the defect correction form of the Picard iteration because it converges much more generally when inexact linear solvers are used then 23351d27aa22SBarry Smith the direct Picard iteration $A(x^n) x^{n+1} = bp(x^n) + b$ 23368b0a5094SBarry Smith 23378b0a5094SBarry 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 23381d27aa22SBarry 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 23391d27aa22SBarry Smith different please contact us at petsc-dev@mcs.anl.gov and we'll have an entirely new argument \:-). 23408b0a5094SBarry Smith 23411d27aa22SBarry 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 234226a11704SBarry Smith $A(x^{n})$ is used to build the preconditioner 23436b7fb656SBarry Smith 234415229ffcSPierre 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. 23456b7fb656SBarry Smith 2346dc4c0fb0SBarry 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 234726a11704SBarry 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 234826a11704SBarry 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`. 2349aaa8cc7dSPierre Jolivet See the comment in src/snes/tutorials/ex15.c. 2350bbc1464cSBarry Smith 23519bcc50f1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESGetPicard()`, `SNESLineSearchPreCheckPicard()`, 23528434afd1SBarry Smith `SNESFunctionFn`, `SNESJacobianFn` 23538b0a5094SBarry Smith @*/ 23548434afd1SBarry Smith PetscErrorCode SNESSetPicard(SNES snes, Vec r, SNESFunctionFn *bp, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx) 2355d71ae5a4SJacob Faibussowitsch { 2356e03ab78fSPeter Brune DM dm; 2357e03ab78fSPeter Brune 23588b0a5094SBarry Smith PetscFunctionBegin; 23598b0a5094SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 23609566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 23619566063dSJacob Faibussowitsch PetscCall(DMSNESSetPicard(dm, bp, J, ctx)); 23629566063dSJacob Faibussowitsch PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx)); 23639566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes, r, SNESPicardComputeFunction, ctx)); 23649566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESPicardComputeJacobian, ctx)); 23653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23668b0a5094SBarry Smith } 23678b0a5094SBarry Smith 23687971a8bfSPeter Brune /*@C 23697971a8bfSPeter Brune SNESGetPicard - Returns the context for the Picard iteration 23707971a8bfSPeter Brune 2371f6dfbefdSBarry Smith Not Collective, but `Vec` is parallel if `SNES` is parallel. Collective if `Vec` is requested, but has not been created yet. 23727971a8bfSPeter Brune 23737971a8bfSPeter Brune Input Parameter: 2374f6dfbefdSBarry Smith . snes - the `SNES` context 23757971a8bfSPeter Brune 2376d8d19677SJose E. Roman Output Parameters: 2377dc4c0fb0SBarry Smith + r - the function (or `NULL`) 23788434afd1SBarry Smith . f - the function (or `NULL`); for calling sequence see `SNESFunctionFn` 2379dc4c0fb0SBarry Smith . Amat - the matrix used to defined the operation A(x) x - b(x) (or `NULL`) 2380dc4c0fb0SBarry Smith . Pmat - the matrix from which the preconditioner will be constructed (or `NULL`) 23818434afd1SBarry Smith . J - the function for matrix evaluation (or `NULL`); for calling sequence see `SNESJacobianFn` 2382dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`) 23837971a8bfSPeter Brune 23847971a8bfSPeter Brune Level: advanced 23857971a8bfSPeter Brune 23868434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetFunction()`, `SNESSetPicard()`, `SNESGetFunction()`, `SNESGetJacobian()`, `SNESGetDM()`, `SNESFunctionFn`, `SNESJacobianFn` 23877971a8bfSPeter Brune @*/ 23888434afd1SBarry Smith PetscErrorCode SNESGetPicard(SNES snes, Vec *r, SNESFunctionFn **f, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx) 2389d71ae5a4SJacob Faibussowitsch { 23907971a8bfSPeter Brune DM dm; 23917971a8bfSPeter Brune 23927971a8bfSPeter Brune PetscFunctionBegin; 23937971a8bfSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 23949566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, r, NULL, NULL)); 23959566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL)); 23969566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 23979566063dSJacob Faibussowitsch PetscCall(DMSNESGetPicard(dm, f, J, ctx)); 23983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23997971a8bfSPeter Brune } 24007971a8bfSPeter Brune 2401d25893d9SBarry Smith /*@C 2402dc4c0fb0SBarry Smith SNESSetComputeInitialGuess - Sets a routine used to compute an initial guess for the nonlinear problem 2403d25893d9SBarry Smith 2404c3339decSBarry Smith Logically Collective 2405d25893d9SBarry Smith 2406d25893d9SBarry Smith Input Parameters: 2407f6dfbefdSBarry Smith + snes - the `SNES` context 24088434afd1SBarry Smith . func - function evaluation routine, see `SNESInitialGuessFn` for the calling sequence 2409d25893d9SBarry Smith - ctx - [optional] user-defined context for private data for the 2410dc4c0fb0SBarry Smith function evaluation routine (may be `NULL`) 2411d25893d9SBarry Smith 2412d25893d9SBarry Smith Level: intermediate 2413d25893d9SBarry Smith 24148434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESInitialGuessFn` 2415d25893d9SBarry Smith @*/ 24168434afd1SBarry Smith PetscErrorCode SNESSetComputeInitialGuess(SNES snes, SNESInitialGuessFn *func, void *ctx) 2417d71ae5a4SJacob Faibussowitsch { 2418d25893d9SBarry Smith PetscFunctionBegin; 2419d25893d9SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2420d25893d9SBarry Smith if (func) snes->ops->computeinitialguess = func; 2421d25893d9SBarry Smith if (ctx) snes->initialguessP = ctx; 24223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2423d25893d9SBarry Smith } 2424d25893d9SBarry Smith 24251096aae1SMatthew Knepley /*@C 2426dc4c0fb0SBarry Smith SNESGetRhs - Gets the vector for solving F(x) = `rhs`. If `rhs` is not set 2427dd8e379bSPierre Jolivet it assumes a zero right-hand side. 24281096aae1SMatthew Knepley 2429c3339decSBarry Smith Logically Collective 24301096aae1SMatthew Knepley 24311096aae1SMatthew Knepley Input Parameter: 2432f6dfbefdSBarry Smith . snes - the `SNES` context 24331096aae1SMatthew Knepley 24341096aae1SMatthew Knepley Output Parameter: 2435dd8e379bSPierre Jolivet . rhs - the right-hand side vector or `NULL` if there is no right-hand side vector 24361096aae1SMatthew Knepley 24371096aae1SMatthew Knepley Level: intermediate 24381096aae1SMatthew Knepley 24391cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetFunction()` 24401096aae1SMatthew Knepley @*/ 2441d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetRhs(SNES snes, Vec *rhs) 2442d71ae5a4SJacob Faibussowitsch { 24431096aae1SMatthew Knepley PetscFunctionBegin; 24440700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 24454f572ea9SToby Isaac PetscAssertPointer(rhs, 2); 244685385478SLisandro Dalcin *rhs = snes->vec_rhs; 24473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24481096aae1SMatthew Knepley } 24491096aae1SMatthew Knepley 24509b94acceSBarry Smith /*@ 2451f6dfbefdSBarry Smith SNESComputeFunction - Calls the function that has been set with `SNESSetFunction()`. 24529b94acceSBarry Smith 2453c3339decSBarry Smith Collective 2454c7afd0dbSLois Curfman McInnes 24559b94acceSBarry Smith Input Parameters: 2456f6dfbefdSBarry Smith + snes - the `SNES` context 2457c7afd0dbSLois Curfman McInnes - x - input vector 24589b94acceSBarry Smith 24599b94acceSBarry Smith Output Parameter: 2460f6dfbefdSBarry Smith . y - function vector, as set by `SNESSetFunction()` 24619b94acceSBarry Smith 2462dc4c0fb0SBarry Smith Level: developer 2463dc4c0fb0SBarry Smith 246400677de2SStefano Zampini Notes: 2465f6dfbefdSBarry Smith `SNESComputeFunction()` is typically used within nonlinear solvers 2466bbc1464cSBarry Smith implementations, so users would not generally call this routine themselves. 246736851e7fSLois Curfman McInnes 246800677de2SStefano Zampini When solving for $F(x) = b$, this routine computes $y = F(x) - b$. 246900677de2SStefano Zampini 24701cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeMFFunction()` 24719b94acceSBarry Smith @*/ 2472d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeFunction(SNES snes, Vec x, Vec y) 2473d71ae5a4SJacob Faibussowitsch { 24746cab3a1bSJed Brown DM dm; 2475942e3340SBarry Smith DMSNES sdm; 24769b94acceSBarry Smith 24773a40ed3dSBarry Smith PetscFunctionBegin; 24780700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 24790700a824SBarry Smith PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 24800700a824SBarry Smith PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2481c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, x, 2); 2482c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, y, 3); 2483e0f629ddSJacob Faibussowitsch PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2484184914b5SBarry Smith 24859566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 24869566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 24870fdf79fbSJacob 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()."); 248832f3f7c2SPeter Brune if (sdm->ops->computefunction) { 248948a46eb9SPierre Jolivet if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0)); 24909566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(x)); 24918ddeebeaSSteve Benbow /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */ 24928ddeebeaSSteve Benbow snes->domainerror = PETSC_FALSE; 2493800f99ffSJeremy L Thompson { 2494800f99ffSJeremy L Thompson void *ctx; 24958434afd1SBarry Smith SNESFunctionFn *computefunction; 2496800f99ffSJeremy L Thompson PetscCall(DMSNESGetFunction(dm, &computefunction, &ctx)); 2497800f99ffSJeremy L Thompson PetscCallBack("SNES callback function", (*computefunction)(snes, x, y, ctx)); 2498800f99ffSJeremy L Thompson } 24999566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(x)); 250048a46eb9SPierre Jolivet if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0)); 25010fdf79fbSJacob Faibussowitsch } else /* if (snes->vec_rhs) */ { 25029566063dSJacob Faibussowitsch PetscCall(MatMult(snes->jacobian, x, y)); 25030fdf79fbSJacob Faibussowitsch } 25041baa6e33SBarry Smith if (snes->vec_rhs) PetscCall(VecAXPY(y, -1.0, snes->vec_rhs)); 2505ae3c334cSLois Curfman McInnes snes->nfuncs++; 2506422a814eSBarry Smith /* 2507422a814eSBarry Smith domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will 2508422a814eSBarry Smith propagate the value to all processes 2509422a814eSBarry Smith */ 2510f480ea8aSBarry Smith PetscCall(VecFlag(y, snes->domainerror)); 25113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 25129b94acceSBarry Smith } 25139b94acceSBarry Smith 2514c79ef259SPeter Brune /*@ 25150b4b7b1cSBarry Smith SNESComputeMFFunction - Calls the function that has been set with `DMSNESSetMFFunction()`. 2516bbc1464cSBarry Smith 2517c3339decSBarry Smith Collective 2518bbc1464cSBarry Smith 2519bbc1464cSBarry Smith Input Parameters: 2520f6dfbefdSBarry Smith + snes - the `SNES` context 2521bbc1464cSBarry Smith - x - input vector 2522bbc1464cSBarry Smith 2523bbc1464cSBarry Smith Output Parameter: 25240b4b7b1cSBarry Smith . y - output vector 2525bbc1464cSBarry Smith 2526dc4c0fb0SBarry Smith Level: developer 2527dc4c0fb0SBarry Smith 2528bbc1464cSBarry Smith Notes: 2529420bcc1bSBarry Smith `SNESComputeMFFunction()` is used within the matrix-vector products called by the matrix created with `MatCreateSNESMF()` 2530bbc1464cSBarry Smith so users would not generally call this routine themselves. 2531bbc1464cSBarry Smith 2532dd8e379bSPierre Jolivet Since this function is intended for use with finite differencing it does not subtract the right-hand side vector provided with `SNESSolve()` 2533f6dfbefdSBarry Smith while `SNESComputeFunction()` does. As such, this routine cannot be used with `MatMFFDSetBase()` with a provided F function value even if it applies the 2534dd8e379bSPierre 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. 2535bbc1464cSBarry Smith 25360b4b7b1cSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `MatCreateSNESMF()`, `DMSNESSetMFFunction()` 2537bbc1464cSBarry Smith @*/ 2538d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeMFFunction(SNES snes, Vec x, Vec y) 2539d71ae5a4SJacob Faibussowitsch { 2540bbc1464cSBarry Smith DM dm; 2541bbc1464cSBarry Smith DMSNES sdm; 2542bbc1464cSBarry Smith 2543bbc1464cSBarry Smith PetscFunctionBegin; 2544bbc1464cSBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2545bbc1464cSBarry Smith PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2546bbc1464cSBarry Smith PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2547bbc1464cSBarry Smith PetscCheckSameComm(snes, 1, x, 2); 2548bbc1464cSBarry Smith PetscCheckSameComm(snes, 1, y, 3); 2549e0f629ddSJacob Faibussowitsch PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2550bbc1464cSBarry Smith 25519566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 25529566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 25539566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0)); 25549566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(x)); 2555bbc1464cSBarry Smith /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */ 2556bbc1464cSBarry Smith snes->domainerror = PETSC_FALSE; 2557792fecdfSBarry Smith PetscCallBack("SNES callback function", (*sdm->ops->computemffunction)(snes, x, y, sdm->mffunctionctx)); 25589566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(x)); 25599566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0)); 2560bbc1464cSBarry Smith snes->nfuncs++; 2561bbc1464cSBarry Smith /* 2562bbc1464cSBarry Smith domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will 2563bbc1464cSBarry Smith propagate the value to all processes 2564bbc1464cSBarry Smith */ 2565f480ea8aSBarry Smith PetscCall(VecFlag(y, snes->domainerror)); 25663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2567bbc1464cSBarry Smith } 2568bbc1464cSBarry Smith 2569bbc1464cSBarry Smith /*@ 2570f6dfbefdSBarry Smith SNESComputeNGS - Calls the Gauss-Seidel function that has been set with `SNESSetNGS()`. 2571c79ef259SPeter Brune 2572c3339decSBarry Smith Collective 2573c79ef259SPeter Brune 2574c79ef259SPeter Brune Input Parameters: 2575f6dfbefdSBarry Smith + snes - the `SNES` context 2576c79ef259SPeter Brune . x - input vector 2577c79ef259SPeter Brune - b - rhs vector 2578c79ef259SPeter Brune 2579c79ef259SPeter Brune Output Parameter: 2580c79ef259SPeter Brune . x - new solution vector 2581c79ef259SPeter Brune 2582dc4c0fb0SBarry Smith Level: developer 2583dc4c0fb0SBarry Smith 2584f6dfbefdSBarry Smith Note: 2585f6dfbefdSBarry Smith `SNESComputeNGS()` is typically used within composed nonlinear solver 2586c79ef259SPeter Brune implementations, so most users would not generally call this routine 2587c79ef259SPeter Brune themselves. 2588c79ef259SPeter Brune 25898434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGSFn`, `SNESSetNGS()`, `SNESComputeFunction()`, `SNESNGS` 2590c79ef259SPeter Brune @*/ 2591d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeNGS(SNES snes, Vec b, Vec x) 2592d71ae5a4SJacob Faibussowitsch { 25936cab3a1bSJed Brown DM dm; 2594942e3340SBarry Smith DMSNES sdm; 2595646217ecSPeter Brune 2596646217ecSPeter Brune PetscFunctionBegin; 2597646217ecSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2598064a246eSJacob Faibussowitsch PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 2599064a246eSJacob Faibussowitsch if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 2600064a246eSJacob Faibussowitsch PetscCheckSameComm(snes, 1, x, 3); 2601064a246eSJacob Faibussowitsch if (b) PetscCheckSameComm(snes, 1, b, 2); 2602e0f629ddSJacob Faibussowitsch if (b) PetscCall(VecValidValues_Internal(b, 2, PETSC_TRUE)); 26039566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_NGSEval, snes, x, b, 0)); 26049566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 26059566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 26060fdf79fbSJacob Faibussowitsch PetscCheck(sdm->ops->computegs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetNGS() before SNESComputeNGS(), likely called from SNESSolve()."); 26079566063dSJacob Faibussowitsch if (b) PetscCall(VecLockReadPush(b)); 2608792fecdfSBarry Smith PetscCallBack("SNES callback NGS", (*sdm->ops->computegs)(snes, x, b, sdm->gsctx)); 26099566063dSJacob Faibussowitsch if (b) PetscCall(VecLockReadPop(b)); 26109566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_NGSEval, snes, x, b, 0)); 26113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2612646217ecSPeter Brune } 2613646217ecSPeter Brune 2614494a190aSStefano Zampini static PetscErrorCode SNESComputeFunction_FD(SNES snes, Vec Xin, Vec G) 2615494a190aSStefano Zampini { 2616494a190aSStefano Zampini Vec X; 2617494a190aSStefano Zampini PetscScalar *g; 2618494a190aSStefano Zampini PetscReal f, f2; 2619494a190aSStefano Zampini PetscInt low, high, N, i; 2620494a190aSStefano Zampini PetscBool flg; 2621494a190aSStefano Zampini PetscReal h = .5 * PETSC_SQRT_MACHINE_EPSILON; 2622494a190aSStefano Zampini 2623494a190aSStefano Zampini PetscFunctionBegin; 2624494a190aSStefano Zampini PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_fd_delta", &h, &flg)); 2625494a190aSStefano Zampini PetscCall(VecDuplicate(Xin, &X)); 2626494a190aSStefano Zampini PetscCall(VecCopy(Xin, X)); 2627494a190aSStefano Zampini PetscCall(VecGetSize(X, &N)); 2628494a190aSStefano Zampini PetscCall(VecGetOwnershipRange(X, &low, &high)); 2629494a190aSStefano Zampini PetscCall(VecSetOption(X, VEC_IGNORE_OFF_PROC_ENTRIES, PETSC_TRUE)); 2630494a190aSStefano Zampini PetscCall(VecGetArray(G, &g)); 2631494a190aSStefano Zampini for (i = 0; i < N; i++) { 2632494a190aSStefano Zampini PetscCall(VecSetValue(X, i, -h, ADD_VALUES)); 2633494a190aSStefano Zampini PetscCall(VecAssemblyBegin(X)); 2634494a190aSStefano Zampini PetscCall(VecAssemblyEnd(X)); 2635494a190aSStefano Zampini PetscCall(SNESComputeObjective(snes, X, &f)); 2636494a190aSStefano Zampini PetscCall(VecSetValue(X, i, 2.0 * h, ADD_VALUES)); 2637494a190aSStefano Zampini PetscCall(VecAssemblyBegin(X)); 2638494a190aSStefano Zampini PetscCall(VecAssemblyEnd(X)); 2639494a190aSStefano Zampini PetscCall(SNESComputeObjective(snes, X, &f2)); 2640494a190aSStefano Zampini PetscCall(VecSetValue(X, i, -h, ADD_VALUES)); 2641494a190aSStefano Zampini PetscCall(VecAssemblyBegin(X)); 2642494a190aSStefano Zampini PetscCall(VecAssemblyEnd(X)); 2643494a190aSStefano Zampini if (i >= low && i < high) g[i - low] = (f2 - f) / (2.0 * h); 2644494a190aSStefano Zampini } 2645494a190aSStefano Zampini PetscCall(VecRestoreArray(G, &g)); 2646494a190aSStefano Zampini PetscCall(VecDestroy(&X)); 2647494a190aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2648494a190aSStefano Zampini } 2649494a190aSStefano Zampini 26501dfd7622SMatthew Knepley /*@ 26511dfd7622SMatthew Knepley SNESTestFunction - Computes the difference between the computed and finite-difference functions 26521dfd7622SMatthew Knepley 26531dfd7622SMatthew Knepley Collective 26541dfd7622SMatthew Knepley 2655d5bfe6baSJose E. Roman Input Parameter: 26561dfd7622SMatthew Knepley . snes - the `SNES` context 26571dfd7622SMatthew Knepley 26581dfd7622SMatthew Knepley Options Database Keys: 26591dfd7622SMatthew Knepley + -snes_test_function - compare the user provided function with one compute via finite differences to check for errors. 26601dfd7622SMatthew Knepley - -snes_test_function_view - display the user provided function, the finite difference function and the difference 26611dfd7622SMatthew Knepley 26621dfd7622SMatthew Knepley Level: developer 26631dfd7622SMatthew Knepley 26641dfd7622SMatthew Knepley .seealso: [](ch_snes), `SNESTestJacobian()`, `SNESSetFunction()`, `SNESComputeFunction()` 26651dfd7622SMatthew Knepley @*/ 2666494a190aSStefano Zampini PetscErrorCode SNESTestFunction(SNES snes) 2667494a190aSStefano Zampini { 2668494a190aSStefano Zampini Vec x, g1, g2, g3; 26691dfd7622SMatthew Knepley PetscBool complete_print = PETSC_FALSE; 2670494a190aSStefano Zampini PetscReal hcnorm, fdnorm, hcmax, fdmax, diffmax, diffnorm; 2671494a190aSStefano Zampini PetscScalar dot; 2672494a190aSStefano Zampini MPI_Comm comm; 2673494a190aSStefano Zampini PetscViewer viewer, mviewer; 2674494a190aSStefano Zampini PetscViewerFormat format; 2675494a190aSStefano Zampini PetscInt tabs; 2676494a190aSStefano Zampini static PetscBool directionsprinted = PETSC_FALSE; 26778434afd1SBarry Smith SNESObjectiveFn *objective; 2678494a190aSStefano Zampini 2679494a190aSStefano Zampini PetscFunctionBegin; 2680494a190aSStefano Zampini PetscCall(SNESGetObjective(snes, &objective, NULL)); 2681494a190aSStefano Zampini if (!objective) PetscFunctionReturn(PETSC_SUCCESS); 2682494a190aSStefano Zampini 2683494a190aSStefano Zampini PetscObjectOptionsBegin((PetscObject)snes); 2684494a190aSStefano Zampini PetscCall(PetscOptionsViewer("-snes_test_function_view", "View difference between hand-coded and finite difference function element entries", "None", &mviewer, &format, &complete_print)); 2685494a190aSStefano Zampini PetscOptionsEnd(); 2686494a190aSStefano Zampini 2687494a190aSStefano Zampini PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 2688494a190aSStefano Zampini PetscCall(PetscViewerASCIIGetStdout(comm, &viewer)); 2689494a190aSStefano Zampini PetscCall(PetscViewerASCIIGetTab(viewer, &tabs)); 2690494a190aSStefano Zampini PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel)); 2691494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Function -------------\n")); 2692494a190aSStefano Zampini if (!complete_print && !directionsprinted) { 2693494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Run with -snes_test_function_view and optionally -snes_test_function <threshold> to show difference\n")); 2694494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " of hand-coded and finite difference function entries greater than <threshold>.\n")); 2695494a190aSStefano Zampini } 2696494a190aSStefano Zampini if (!directionsprinted) { 2697494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Testing hand-coded Function, if (for double precision runs) ||F - Ffd||/||F|| is\n")); 2698494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " O(1.e-8), the hand-coded Function is probably correct.\n")); 2699494a190aSStefano Zampini directionsprinted = PETSC_TRUE; 2700494a190aSStefano Zampini } 2701494a190aSStefano Zampini if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format)); 2702494a190aSStefano Zampini 2703494a190aSStefano Zampini PetscCall(SNESGetSolution(snes, &x)); 2704494a190aSStefano Zampini PetscCall(VecDuplicate(x, &g1)); 2705494a190aSStefano Zampini PetscCall(VecDuplicate(x, &g2)); 2706494a190aSStefano Zampini PetscCall(VecDuplicate(x, &g3)); 2707494a190aSStefano Zampini PetscCall(SNESComputeFunction(snes, x, g1)); 2708494a190aSStefano Zampini PetscCall(SNESComputeFunction_FD(snes, x, g2)); 2709494a190aSStefano Zampini 2710494a190aSStefano Zampini PetscCall(VecNorm(g2, NORM_2, &fdnorm)); 2711494a190aSStefano Zampini PetscCall(VecNorm(g1, NORM_2, &hcnorm)); 2712494a190aSStefano Zampini PetscCall(VecNorm(g2, NORM_INFINITY, &fdmax)); 2713494a190aSStefano Zampini PetscCall(VecNorm(g1, NORM_INFINITY, &hcmax)); 2714494a190aSStefano Zampini PetscCall(VecDot(g1, g2, &dot)); 2715494a190aSStefano Zampini PetscCall(VecCopy(g1, g3)); 2716494a190aSStefano Zampini PetscCall(VecAXPY(g3, -1.0, g2)); 2717494a190aSStefano Zampini PetscCall(VecNorm(g3, NORM_2, &diffnorm)); 2718494a190aSStefano Zampini PetscCall(VecNorm(g3, NORM_INFINITY, &diffmax)); 2719494a190aSStefano 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)))); 2720494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " 2-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffnorm / PetscMax(hcnorm, fdnorm)), (double)diffnorm)); 2721494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " max-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffmax / PetscMax(hcmax, fdmax)), (double)diffmax)); 2722494a190aSStefano Zampini 2723494a190aSStefano Zampini if (complete_print) { 2724494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded function ----------\n")); 2725494a190aSStefano Zampini PetscCall(VecView(g1, mviewer)); 2726494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Finite difference function ----------\n")); 2727494a190aSStefano Zampini PetscCall(VecView(g2, mviewer)); 2728494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded minus finite-difference function ----------\n")); 2729494a190aSStefano Zampini PetscCall(VecView(g3, mviewer)); 2730494a190aSStefano Zampini } 2731494a190aSStefano Zampini PetscCall(VecDestroy(&g1)); 2732494a190aSStefano Zampini PetscCall(VecDestroy(&g2)); 2733494a190aSStefano Zampini PetscCall(VecDestroy(&g3)); 2734494a190aSStefano Zampini 2735494a190aSStefano Zampini if (complete_print) { 2736494a190aSStefano Zampini PetscCall(PetscViewerPopFormat(mviewer)); 2737494a190aSStefano Zampini PetscCall(PetscViewerDestroy(&mviewer)); 2738494a190aSStefano Zampini } 2739494a190aSStefano Zampini PetscCall(PetscViewerASCIISetTab(viewer, tabs)); 2740494a190aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2741494a190aSStefano Zampini } 2742494a190aSStefano Zampini 2743cbf8f02cSMatthew G. Knepley /*@ 2744cbf8f02cSMatthew G. Knepley SNESTestJacobian - Computes the difference between the computed and finite-difference Jacobians 2745cbf8f02cSMatthew G. Knepley 2746cbf8f02cSMatthew G. Knepley Collective 2747cbf8f02cSMatthew G. Knepley 2748d5bfe6baSJose E. Roman Input Parameter: 2749cbf8f02cSMatthew G. Knepley . snes - the `SNES` context 2750cbf8f02cSMatthew G. Knepley 2751cbf8f02cSMatthew G. Knepley Output Parameters: 27521dfd7622SMatthew Knepley + Jnorm - the Frobenius norm of the computed Jacobian, or `NULL` 27531dfd7622SMatthew Knepley - diffNorm - the Frobenius norm of the difference of the computed and finite-difference Jacobians, or `NULL` 2754cbf8f02cSMatthew G. Knepley 2755cbf8f02cSMatthew G. Knepley Options Database Keys: 2756cbf8f02cSMatthew 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. 2757cbf8f02cSMatthew G. Knepley - -snes_test_jacobian_view - display the user provided Jacobian, the finite difference Jacobian and the difference 2758cbf8f02cSMatthew G. Knepley 2759cbf8f02cSMatthew G. Knepley Level: developer 2760cbf8f02cSMatthew G. Knepley 27611dfd7622SMatthew Knepley Note: 27621dfd7622SMatthew Knepley Directions and norms are printed to stdout if `diffNorm` is `NULL`. 27631dfd7622SMatthew Knepley 27641dfd7622SMatthew Knepley .seealso: [](ch_snes), `SNESTestFunction()`, `SNESSetJacobian()`, `SNESComputeJacobian()` 2765cbf8f02cSMatthew G. Knepley @*/ 2766cbf8f02cSMatthew G. Knepley PetscErrorCode SNESTestJacobian(SNES snes, PetscReal *Jnorm, PetscReal *diffNorm) 2767d71ae5a4SJacob Faibussowitsch { 276812837594SBarry Smith Mat A, B, C, D, jacobian; 27694df93895SStefano Zampini Vec x = snes->vec_sol, f; 2770e885f1abSBarry Smith PetscReal nrm, gnorm; 277181e7118cSBarry Smith PetscReal threshold = 1.e-5; 27720e276705SLisandro Dalcin MatType mattype; 2773e885f1abSBarry Smith PetscInt m, n, M, N; 2774e885f1abSBarry Smith void *functx; 27751dfd7622SMatthew Knepley PetscBool complete_print = PETSC_FALSE, threshold_print = PETSC_FALSE, flg, istranspose; 27761dfd7622SMatthew Knepley PetscBool silent = diffNorm != PETSC_NULLPTR ? PETSC_TRUE : PETSC_FALSE; 27773325ff46SBarry Smith PetscViewer viewer, mviewer; 2778e885f1abSBarry Smith MPI_Comm comm; 2779e885f1abSBarry Smith PetscInt tabs; 278012837594SBarry Smith static PetscBool directionsprinted = PETSC_FALSE; 27813325ff46SBarry Smith PetscViewerFormat format; 2782e885f1abSBarry Smith 2783e885f1abSBarry Smith PetscFunctionBegin; 2784d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)snes); 27859566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-snes_test_jacobian", "Threshold for element difference between hand-coded and finite difference being meaningful", "None", threshold, &threshold, NULL)); 27869566063dSJacob Faibussowitsch PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display", "-snes_test_jacobian_view", "3.13", NULL)); 27874ead3382SBarry Smith PetscCall(PetscOptionsViewer("-snes_test_jacobian_view", "View difference between hand-coded and finite difference Jacobians element entries", "None", &mviewer, &format, &complete_print)); 27889566063dSJacob Faibussowitsch PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display_threshold", "-snes_test_jacobian", "3.13", "-snes_test_jacobian accepts an optional threshold (since v3.10)")); 27899566063dSJacob 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)); 2790d0609cedSBarry Smith PetscOptionsEnd(); 2791e885f1abSBarry Smith 27929566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 27939566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(comm, &viewer)); 27949566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetTab(viewer, &tabs)); 27959566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel)); 27961dfd7622SMatthew Knepley if (!silent) PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Jacobian -------------\n")); 27971dfd7622SMatthew Knepley if (!complete_print && !silent && !directionsprinted) { 27989566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Run with -snes_test_jacobian_view and optionally -snes_test_jacobian <threshold> to show difference\n")); 27999566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " of hand-coded and finite difference Jacobian entries greater than <threshold>.\n")); 280012837594SBarry Smith } 28011dfd7622SMatthew Knepley if (!directionsprinted && !silent) { 28029566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Testing hand-coded Jacobian, if (for double precision runs) ||J - Jfd||_F/||J||_F is\n")); 28039566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " O(1.e-8), the hand-coded Jacobian is probably correct.\n")); 280412837594SBarry Smith directionsprinted = PETSC_TRUE; 2805e885f1abSBarry Smith } 28061baa6e33SBarry Smith if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format)); 2807e885f1abSBarry Smith 28089566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes->jacobian, MATMFFD, &flg)); 280912837594SBarry Smith if (!flg) jacobian = snes->jacobian; 281012837594SBarry Smith else jacobian = snes->jacobian_pre; 281112837594SBarry Smith 28124df93895SStefano Zampini if (!x) PetscCall(MatCreateVecs(jacobian, &x, NULL)); 28134df93895SStefano Zampini else PetscCall(PetscObjectReference((PetscObject)x)); 28149566063dSJacob Faibussowitsch PetscCall(VecDuplicate(x, &f)); 28154df93895SStefano Zampini 2816a82339d0SMatthew G. Knepley /* evaluate the function at this point because SNESComputeJacobianDefault() assumes that the function has been evaluated and put into snes->vec_func */ 28179566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, x, f)); 28189566063dSJacob Faibussowitsch PetscCall(VecDestroy(&f)); 28199566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESKSPTRANSPOSEONLY, &istranspose)); 282012837594SBarry Smith while (jacobian) { 28212cd624f9SStefano Zampini Mat JT = NULL, Jsave = NULL; 28222cd624f9SStefano Zampini 28232cd624f9SStefano Zampini if (istranspose) { 28249566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(jacobian, &JT)); 28252cd624f9SStefano Zampini Jsave = jacobian; 28262cd624f9SStefano Zampini jacobian = JT; 28272cd624f9SStefano Zampini } 28289566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)jacobian, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, "")); 282912837594SBarry Smith if (flg) { 283012837594SBarry Smith A = jacobian; 28319566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 283212837594SBarry Smith } else { 28339566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(jacobian, MATAIJ, &A)); 283412837594SBarry Smith } 2835e885f1abSBarry Smith 28369566063dSJacob Faibussowitsch PetscCall(MatGetType(A, &mattype)); 28379566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &M, &N)); 28389566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &m, &n)); 28399566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B)); 28409566063dSJacob Faibussowitsch PetscCall(MatSetType(B, mattype)); 28419566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, m, n, M, N)); 28429566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(B, A, A)); 28439566063dSJacob Faibussowitsch PetscCall(MatSetUp(B)); 28449566063dSJacob Faibussowitsch PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 2845e885f1abSBarry Smith 28469566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, NULL, &functx)); 28479566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobianDefault(snes, x, B, B, functx)); 284812837594SBarry Smith 28499566063dSJacob Faibussowitsch PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &D)); 28509566063dSJacob Faibussowitsch PetscCall(MatAYPX(D, -1.0, A, DIFFERENT_NONZERO_PATTERN)); 28519566063dSJacob Faibussowitsch PetscCall(MatNorm(D, NORM_FROBENIUS, &nrm)); 28529566063dSJacob Faibussowitsch PetscCall(MatNorm(A, NORM_FROBENIUS, &gnorm)); 28539566063dSJacob Faibussowitsch PetscCall(MatDestroy(&D)); 285412837594SBarry Smith if (!gnorm) gnorm = 1; /* just in case */ 28551dfd7622SMatthew Knepley if (!silent) PetscCall(PetscViewerASCIIPrintf(viewer, " ||J - Jfd||_F/||J||_F = %g, ||J - Jfd||_F = %g\n", (double)(nrm / gnorm), (double)nrm)); 2856e885f1abSBarry Smith if (complete_print) { 28579566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded Jacobian ----------\n")); 28589566063dSJacob Faibussowitsch PetscCall(MatView(A, mviewer)); 28599566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Finite difference Jacobian ----------\n")); 28609566063dSJacob Faibussowitsch PetscCall(MatView(B, mviewer)); 2861e885f1abSBarry Smith } 2862e885f1abSBarry Smith 2863df10fb39SFande Kong if (threshold_print || complete_print) { 2864e885f1abSBarry Smith PetscInt Istart, Iend, *ccols, bncols, cncols, j, row; 2865e885f1abSBarry Smith PetscScalar *cvals; 2866e885f1abSBarry Smith const PetscInt *bcols; 2867e885f1abSBarry Smith const PetscScalar *bvals; 2868e885f1abSBarry Smith 28699566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C)); 28709566063dSJacob Faibussowitsch PetscCall(MatSetType(C, mattype)); 28719566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, m, n, M, N)); 28729566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(C, A, A)); 28739566063dSJacob Faibussowitsch PetscCall(MatSetUp(C)); 28749566063dSJacob Faibussowitsch PetscCall(MatSetOption(C, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 28750e276705SLisandro Dalcin 28769566063dSJacob Faibussowitsch PetscCall(MatAYPX(B, -1.0, A, DIFFERENT_NONZERO_PATTERN)); 28779566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(B, &Istart, &Iend)); 2878e885f1abSBarry Smith 2879e885f1abSBarry Smith for (row = Istart; row < Iend; row++) { 28809566063dSJacob Faibussowitsch PetscCall(MatGetRow(B, row, &bncols, &bcols, &bvals)); 28819566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(bncols, &ccols, bncols, &cvals)); 2882e885f1abSBarry Smith for (j = 0, cncols = 0; j < bncols; j++) { 288323a52b1dSBarry Smith if (PetscAbsScalar(bvals[j]) > threshold) { 2884e885f1abSBarry Smith ccols[cncols] = bcols[j]; 2885e885f1abSBarry Smith cvals[cncols] = bvals[j]; 2886e885f1abSBarry Smith cncols += 1; 2887e885f1abSBarry Smith } 2888e885f1abSBarry Smith } 288948a46eb9SPierre Jolivet if (cncols) PetscCall(MatSetValues(C, 1, &row, cncols, ccols, cvals, INSERT_VALUES)); 28909566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(B, row, &bncols, &bcols, &bvals)); 28919566063dSJacob Faibussowitsch PetscCall(PetscFree2(ccols, cvals)); 2892e885f1abSBarry Smith } 28939566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 28949566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 28959566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded minus finite-difference Jacobian with tolerance %g ----------\n", (double)threshold)); 28969566063dSJacob Faibussowitsch PetscCall(MatView(C, complete_print ? mviewer : viewer)); 28979566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C)); 2898e885f1abSBarry Smith } 28999566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A)); 29009566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 29019566063dSJacob Faibussowitsch PetscCall(MatDestroy(&JT)); 29022cd624f9SStefano Zampini if (Jsave) jacobian = Jsave; 290312837594SBarry Smith if (jacobian != snes->jacobian_pre) { 290412837594SBarry Smith jacobian = snes->jacobian_pre; 29051dfd7622SMatthew Knepley if (!silent) PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Jacobian for preconditioner -------------\n")); 29069371c9d4SSatish Balay } else jacobian = NULL; 290712837594SBarry Smith } 29089566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); 29091baa6e33SBarry Smith if (complete_print) PetscCall(PetscViewerPopFormat(mviewer)); 2910648c30bcSBarry Smith if (mviewer) PetscCall(PetscViewerDestroy(&mviewer)); 29119566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISetTab(viewer, tabs)); 2912cbf8f02cSMatthew G. Knepley 2913cbf8f02cSMatthew G. Knepley if (Jnorm) *Jnorm = gnorm; 2914cbf8f02cSMatthew G. Knepley if (diffNorm) *diffNorm = nrm; 29153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2916e885f1abSBarry Smith } 2917e885f1abSBarry Smith 291862fef451SLois Curfman McInnes /*@ 2919f6dfbefdSBarry Smith SNESComputeJacobian - Computes the Jacobian matrix that has been set with `SNESSetJacobian()`. 292062fef451SLois Curfman McInnes 2921c3339decSBarry Smith Collective 2922c7afd0dbSLois Curfman McInnes 292362fef451SLois Curfman McInnes Input Parameters: 2924f6dfbefdSBarry Smith + snes - the `SNES` context 2925e4094ef1SJacob Faibussowitsch - X - input vector 292662fef451SLois Curfman McInnes 292762fef451SLois Curfman McInnes Output Parameters: 2928c7afd0dbSLois Curfman McInnes + A - Jacobian matrix 2929420bcc1bSBarry Smith - B - optional matrix for building the preconditioner, usually the same as `A` 2930fee21e36SBarry Smith 2931e35cf81dSBarry Smith Options Database Keys: 293267b8a455SSatish Balay + -snes_lag_preconditioner <lag> - how often to rebuild preconditioner 293367b8a455SSatish Balay . -snes_lag_jacobian <lag> - how often to rebuild Jacobian 2934455a5933SJed 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. 2935455a5933SJed 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 2936693365a8SJed Brown . -snes_compare_explicit - Compare the computed Jacobian to the finite difference Jacobian and output the differences 2937693365a8SJed Brown . -snes_compare_explicit_draw - Compare the computed Jacobian to the finite difference Jacobian and draw the result 2938693365a8SJed Brown . -snes_compare_explicit_contour - Compare the computed Jacobian to the finite difference Jacobian and draw a contour plot with the result 29397addb90fSBarry Smith . -snes_compare_operator - Make the comparison options above use the operator instead of the matrix used to construct the preconditioner 294094d6a431SBarry Smith . -snes_compare_coloring - Compute the finite difference Jacobian using coloring and display norms of difference 2941a5b23f4aSJose E. Roman . -snes_compare_coloring_display - Compute the finite difference Jacobian using coloring and display verbose differences 2942c01495d3SJed Brown . -snes_compare_coloring_threshold - Display only those matrix entries that differ by more than a given threshold 2943dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_atol - Absolute tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold` 2944dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_rtol - Relative tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold` 2945a5b23f4aSJose E. Roman . -snes_compare_coloring_draw - Compute the finite difference Jacobian using coloring and draw differences 2946a5b23f4aSJose E. Roman - -snes_compare_coloring_draw_contour - Compute the finite difference Jacobian using coloring and show contours of matrices and differences 2947c01495d3SJed Brown 2948dc4c0fb0SBarry Smith Level: developer 2949dc4c0fb0SBarry Smith 2950f6dfbefdSBarry Smith Note: 295162fef451SLois Curfman McInnes Most users should not need to explicitly call this routine, as it 295262fef451SLois Curfman McInnes is used internally within the nonlinear solvers. 295362fef451SLois Curfman McInnes 2954420bcc1bSBarry Smith Developer Note: 2955dc4c0fb0SBarry 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 2956420bcc1bSBarry Smith with the `SNESType` of test that has been removed. 2957e885f1abSBarry Smith 29581cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetJacobian()`, `KSPSetOperators()`, `MatStructure`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()` 295962fef451SLois Curfman McInnes @*/ 2960d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeJacobian(SNES snes, Vec X, Mat A, Mat B) 2961d71ae5a4SJacob Faibussowitsch { 2962ace3abfcSBarry Smith PetscBool flag; 29636cab3a1bSJed Brown DM dm; 2964942e3340SBarry Smith DMSNES sdm; 2965e0e3a89bSBarry Smith KSP ksp; 29663a40ed3dSBarry Smith 29673a40ed3dSBarry Smith PetscFunctionBegin; 29680700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 29690700a824SBarry Smith PetscValidHeaderSpecific(X, VEC_CLASSID, 2); 2970c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, X, 2); 2971e0f629ddSJacob Faibussowitsch PetscCall(VecValidValues_Internal(X, 2, PETSC_TRUE)); 29729566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 29739566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 29743232da50SPeter Brune 297501c1178eSBarry Smith /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix-free */ 2976fe3ffe1eSBarry Smith if (snes->lagjacobian == -2) { 2977fe3ffe1eSBarry Smith snes->lagjacobian = -1; 2978f5af7f23SKarl Rupp 29799566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n")); 2980fe3ffe1eSBarry Smith } else if (snes->lagjacobian == -1) { 29819566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is -1\n")); 29829566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag)); 2983ebd3b9afSBarry Smith if (flag) { 29849566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 29859566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 2986ebd3b9afSBarry Smith } 29873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 298837ec4e1aSPeter Brune } else if (snes->lagjacobian > 1 && (snes->iter + snes->jac_iter) % snes->lagjacobian) { 298963a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagjacobian, snes->iter)); 29909566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag)); 2991ebd3b9afSBarry Smith if (flag) { 29929566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 29939566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 2994ebd3b9afSBarry Smith } 29953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2996e35cf81dSBarry Smith } 2997efd4aadfSBarry Smith if (snes->npc && snes->npcside == PC_LEFT) { 29989566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 29999566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 30003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3001d728fb7dSPeter Brune } 3002e35cf81dSBarry Smith 30039566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_JacobianEval, snes, X, A, B)); 30049566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(X)); 3005800f99ffSJeremy L Thompson { 3006800f99ffSJeremy L Thompson void *ctx; 30078434afd1SBarry Smith SNESJacobianFn *J; 3008800f99ffSJeremy L Thompson PetscCall(DMSNESGetJacobian(dm, &J, &ctx)); 3009800f99ffSJeremy L Thompson PetscCallBack("SNES callback Jacobian", (*J)(snes, X, A, B, ctx)); 3010800f99ffSJeremy L Thompson } 30119566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(X)); 30129566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_JacobianEval, snes, X, A, B)); 301328d58a37SPierre Jolivet 30147addb90fSBarry Smith /* attach latest linearization point to the matrix used to construct the preconditioner */ 30159566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)B, "__SNES_latest_X", (PetscObject)X)); 3016a8054027SBarry Smith 3017e0e3a89bSBarry Smith /* the next line ensures that snes->ksp exists */ 30189566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 30193b4f5425SBarry Smith if (snes->lagpreconditioner == -2) { 30209566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Rebuilding preconditioner exactly once since lag is -2\n")); 30219566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE)); 30223b4f5425SBarry Smith snes->lagpreconditioner = -1; 30233b4f5425SBarry Smith } else if (snes->lagpreconditioner == -1) { 30249566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is -1\n")); 30259566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE)); 302637ec4e1aSPeter Brune } else if (snes->lagpreconditioner > 1 && (snes->iter + snes->pre_iter) % snes->lagpreconditioner) { 302763a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagpreconditioner, snes->iter)); 30289566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE)); 3029d1e9a80fSBarry Smith } else { 30309566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Rebuilding preconditioner\n")); 30319566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE)); 3032a8054027SBarry Smith } 3033a8054027SBarry Smith 30344df93895SStefano Zampini /* monkey business to allow testing Jacobians in multilevel solvers. 30354df93895SStefano Zampini This is needed because the SNESTestXXX interface does not accept vectors and matrices */ 30364df93895SStefano Zampini { 30374df93895SStefano Zampini Vec xsave = snes->vec_sol; 30384df93895SStefano Zampini Mat jacobiansave = snes->jacobian; 30394df93895SStefano Zampini Mat jacobian_presave = snes->jacobian_pre; 30404df93895SStefano Zampini 30414df93895SStefano Zampini snes->vec_sol = X; 30424df93895SStefano Zampini snes->jacobian = A; 30434df93895SStefano Zampini snes->jacobian_pre = B; 30441dfd7622SMatthew Knepley if (snes->testFunc) PetscCall(SNESTestFunction(snes)); 30451dfd7622SMatthew Knepley if (snes->testJac) PetscCall(SNESTestJacobian(snes, NULL, NULL)); 3046494a190aSStefano Zampini 30474df93895SStefano Zampini snes->vec_sol = xsave; 30484df93895SStefano Zampini snes->jacobian = jacobiansave; 30494df93895SStefano Zampini snes->jacobian_pre = jacobian_presave; 30504df93895SStefano Zampini } 30514df93895SStefano Zampini 3052693365a8SJed Brown { 3053693365a8SJed Brown PetscBool flag = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_operator = PETSC_FALSE; 3054648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit", NULL, NULL, &flag)); 3055648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw", NULL, NULL, &flag_draw)); 3056648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw_contour", NULL, NULL, &flag_contour)); 3057648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_operator", NULL, NULL, &flag_operator)); 3058693365a8SJed Brown if (flag || flag_draw || flag_contour) { 30590298fd71SBarry Smith Mat Bexp_mine = NULL, Bexp, FDexp; 3060693365a8SJed Brown PetscViewer vdraw, vstdout; 30616b3a5b13SJed Brown PetscBool flg; 3062693365a8SJed Brown if (flag_operator) { 30639566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(A, MATAIJ, &Bexp_mine)); 3064693365a8SJed Brown Bexp = Bexp_mine; 3065693365a8SJed Brown } else { 30667addb90fSBarry Smith /* See if the matrix used to construct the preconditioner can be viewed and added directly */ 30679566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)B, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPIBAIJ, "")); 306894ab13aaSBarry Smith if (flg) Bexp = B; 3069693365a8SJed Brown else { 3070693365a8SJed Brown /* If the "preconditioning" matrix is itself MATSHELL or some other type without direct support */ 30719566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(B, MATAIJ, &Bexp_mine)); 3072693365a8SJed Brown Bexp = Bexp_mine; 3073693365a8SJed Brown } 3074693365a8SJed Brown } 30759566063dSJacob Faibussowitsch PetscCall(MatConvert(Bexp, MATSAME, MAT_INITIAL_MATRIX, &FDexp)); 30769566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobianDefault(snes, X, FDexp, FDexp, NULL)); 30779566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout)); 3078693365a8SJed Brown if (flag_draw || flag_contour) { 30799566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Explicit Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw)); 30809566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 30810298fd71SBarry Smith } else vdraw = NULL; 30829566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit %s\n", flag_operator ? "Jacobian" : "preconditioning Jacobian")); 30839566063dSJacob Faibussowitsch if (flag) PetscCall(MatView(Bexp, vstdout)); 30849566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(Bexp, vdraw)); 30859566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Finite difference Jacobian\n")); 30869566063dSJacob Faibussowitsch if (flag) PetscCall(MatView(FDexp, vstdout)); 30879566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(FDexp, vdraw)); 30889566063dSJacob Faibussowitsch PetscCall(MatAYPX(FDexp, -1.0, Bexp, SAME_NONZERO_PATTERN)); 30899566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian\n")); 30909566063dSJacob Faibussowitsch if (flag) PetscCall(MatView(FDexp, vstdout)); 3091693365a8SJed Brown if (vdraw) { /* Always use contour for the difference */ 30929566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 30939566063dSJacob Faibussowitsch PetscCall(MatView(FDexp, vdraw)); 30949566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(vdraw)); 3095693365a8SJed Brown } 30969566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw)); 30979566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&vdraw)); 30989566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bexp_mine)); 30999566063dSJacob Faibussowitsch PetscCall(MatDestroy(&FDexp)); 3100693365a8SJed Brown } 3101693365a8SJed Brown } 31024c30e9fbSJed Brown { 31036719d8e4SJed Brown PetscBool flag = PETSC_FALSE, flag_display = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_threshold = PETSC_FALSE; 31046719d8e4SJed Brown PetscReal threshold_atol = PETSC_SQRT_MACHINE_EPSILON, threshold_rtol = 10 * PETSC_SQRT_MACHINE_EPSILON; 3105648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring", NULL, NULL, &flag)); 3106648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_display", NULL, NULL, &flag_display)); 3107648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw", NULL, NULL, &flag_draw)); 3108648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw_contour", NULL, NULL, &flag_contour)); 3109648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold", NULL, NULL, &flag_threshold)); 311027b0f280SBarry Smith if (flag_threshold) { 31119566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_rtol", &threshold_rtol, NULL)); 31129566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_atol", &threshold_atol, NULL)); 311327b0f280SBarry Smith } 31146719d8e4SJed Brown if (flag || flag_display || flag_draw || flag_contour || flag_threshold) { 31154c30e9fbSJed Brown Mat Bfd; 31164c30e9fbSJed Brown PetscViewer vdraw, vstdout; 3117335efc43SPeter Brune MatColoring coloring; 31184c30e9fbSJed Brown ISColoring iscoloring; 31194c30e9fbSJed Brown MatFDColoring matfdcoloring; 31208434afd1SBarry Smith SNESFunctionFn *func; 31214c30e9fbSJed Brown void *funcctx; 31226719d8e4SJed Brown PetscReal norm1, norm2, normmax; 31234c30e9fbSJed Brown 31249566063dSJacob Faibussowitsch PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &Bfd)); 31259566063dSJacob Faibussowitsch PetscCall(MatColoringCreate(Bfd, &coloring)); 31269566063dSJacob Faibussowitsch PetscCall(MatColoringSetType(coloring, MATCOLORINGSL)); 31279566063dSJacob Faibussowitsch PetscCall(MatColoringSetFromOptions(coloring)); 31289566063dSJacob Faibussowitsch PetscCall(MatColoringApply(coloring, &iscoloring)); 31299566063dSJacob Faibussowitsch PetscCall(MatColoringDestroy(&coloring)); 31309566063dSJacob Faibussowitsch PetscCall(MatFDColoringCreate(Bfd, iscoloring, &matfdcoloring)); 31319566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFromOptions(matfdcoloring)); 31329566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetUp(Bfd, iscoloring, matfdcoloring)); 31339566063dSJacob Faibussowitsch PetscCall(ISColoringDestroy(&iscoloring)); 31344c30e9fbSJed Brown 31354c30e9fbSJed Brown /* This method of getting the function is currently unreliable since it doesn't work for DM local functions. */ 31369566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, &func, &funcctx)); 31372ba42892SBarry Smith PetscCall(MatFDColoringSetFunction(matfdcoloring, (MatFDColoringFn *)func, funcctx)); 31389566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)matfdcoloring, ((PetscObject)snes)->prefix)); 31399566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)matfdcoloring, "coloring_")); 31409566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFromOptions(matfdcoloring)); 31419566063dSJacob Faibussowitsch PetscCall(MatFDColoringApply(Bfd, matfdcoloring, X, snes)); 31429566063dSJacob Faibussowitsch PetscCall(MatFDColoringDestroy(&matfdcoloring)); 31434c30e9fbSJed Brown 31449566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout)); 31454c30e9fbSJed Brown if (flag_draw || flag_contour) { 31469566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Colored Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw)); 31479566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 31480298fd71SBarry Smith } else vdraw = NULL; 31499566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit preconditioning Jacobian\n")); 31509566063dSJacob Faibussowitsch if (flag_display) PetscCall(MatView(B, vstdout)); 31519566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(B, vdraw)); 31529566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Colored Finite difference Jacobian\n")); 31539566063dSJacob Faibussowitsch if (flag_display) PetscCall(MatView(Bfd, vstdout)); 31549566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(Bfd, vdraw)); 31559566063dSJacob Faibussowitsch PetscCall(MatAYPX(Bfd, -1.0, B, SAME_NONZERO_PATTERN)); 31569566063dSJacob Faibussowitsch PetscCall(MatNorm(Bfd, NORM_1, &norm1)); 31579566063dSJacob Faibussowitsch PetscCall(MatNorm(Bfd, NORM_FROBENIUS, &norm2)); 31589566063dSJacob Faibussowitsch PetscCall(MatNorm(Bfd, NORM_MAX, &normmax)); 31599566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian, norm1=%g normFrob=%g normmax=%g\n", (double)norm1, (double)norm2, (double)normmax)); 31609566063dSJacob Faibussowitsch if (flag_display) PetscCall(MatView(Bfd, vstdout)); 31614c30e9fbSJed Brown if (vdraw) { /* Always use contour for the difference */ 31629566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 31639566063dSJacob Faibussowitsch PetscCall(MatView(Bfd, vdraw)); 31649566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(vdraw)); 31654c30e9fbSJed Brown } 31669566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw)); 31676719d8e4SJed Brown 31686719d8e4SJed Brown if (flag_threshold) { 31696719d8e4SJed Brown PetscInt bs, rstart, rend, i; 31709566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(B, &bs)); 31719566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(B, &rstart, &rend)); 31726719d8e4SJed Brown for (i = rstart; i < rend; i++) { 31736719d8e4SJed Brown const PetscScalar *ba, *ca; 31746719d8e4SJed Brown const PetscInt *bj, *cj; 31756719d8e4SJed Brown PetscInt bn, cn, j, maxentrycol = -1, maxdiffcol = -1, maxrdiffcol = -1; 31766719d8e4SJed Brown PetscReal maxentry = 0, maxdiff = 0, maxrdiff = 0; 31779566063dSJacob Faibussowitsch PetscCall(MatGetRow(B, i, &bn, &bj, &ba)); 31789566063dSJacob Faibussowitsch PetscCall(MatGetRow(Bfd, i, &cn, &cj, &ca)); 31795f80ce2aSJacob Faibussowitsch PetscCheck(bn == cn, ((PetscObject)A)->comm, PETSC_ERR_PLIB, "Unexpected different nonzero pattern in -snes_compare_coloring_threshold"); 31806719d8e4SJed Brown for (j = 0; j < bn; j++) { 31816719d8e4SJed Brown PetscReal rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j])); 31826719d8e4SJed Brown if (PetscAbsScalar(ba[j]) > PetscAbs(maxentry)) { 31836719d8e4SJed Brown maxentrycol = bj[j]; 31846719d8e4SJed Brown maxentry = PetscRealPart(ba[j]); 31856719d8e4SJed Brown } 31866719d8e4SJed Brown if (PetscAbsScalar(ca[j]) > PetscAbs(maxdiff)) { 31876719d8e4SJed Brown maxdiffcol = bj[j]; 31886719d8e4SJed Brown maxdiff = PetscRealPart(ca[j]); 31896719d8e4SJed Brown } 31906719d8e4SJed Brown if (rdiff > maxrdiff) { 31916719d8e4SJed Brown maxrdiffcol = bj[j]; 31926719d8e4SJed Brown maxrdiff = rdiff; 31936719d8e4SJed Brown } 31946719d8e4SJed Brown } 31956719d8e4SJed Brown if (maxrdiff > 1) { 319663a3b9bcSJacob 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)); 31976719d8e4SJed Brown for (j = 0; j < bn; j++) { 31986719d8e4SJed Brown PetscReal rdiff; 31996719d8e4SJed Brown rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j])); 320048a46eb9SPierre Jolivet if (rdiff > 1) PetscCall(PetscViewerASCIIPrintf(vstdout, " (%" PetscInt_FMT ",%g:%g)", bj[j], (double)PetscRealPart(ba[j]), (double)PetscRealPart(ca[j]))); 32016719d8e4SJed Brown } 320263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "\n")); 32036719d8e4SJed Brown } 32049566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(B, i, &bn, &bj, &ba)); 32059566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(Bfd, i, &cn, &cj, &ca)); 32066719d8e4SJed Brown } 32076719d8e4SJed Brown } 32089566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&vdraw)); 32099566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bfd)); 32104c30e9fbSJed Brown } 32114c30e9fbSJed Brown } 32123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 32139b94acceSBarry Smith } 32149b94acceSBarry Smith 32159b94acceSBarry Smith /*@C 32169b94acceSBarry Smith SNESSetJacobian - Sets the function to compute Jacobian as well as the 3217044dda88SLois Curfman McInnes location to store the matrix. 32189b94acceSBarry Smith 3219c3339decSBarry Smith Logically Collective 3220c7afd0dbSLois Curfman McInnes 32219b94acceSBarry Smith Input Parameters: 3222f6dfbefdSBarry Smith + snes - the `SNES` context 3223e5d3d808SBarry Smith . Amat - the matrix that defines the (approximate) Jacobian 3224dc4c0fb0SBarry Smith . Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`. 32258434afd1SBarry Smith . J - Jacobian evaluation routine (if `NULL` then `SNES` retains any previously set value), see `SNESJacobianFn` for details 3226c7afd0dbSLois Curfman McInnes - ctx - [optional] user-defined context for private data for the 3227dc4c0fb0SBarry Smith Jacobian evaluation routine (may be `NULL`) (if `NULL` then `SNES` retains any previously set value) 3228dc4c0fb0SBarry Smith 3229dc4c0fb0SBarry Smith Level: beginner 32309b94acceSBarry Smith 32319b94acceSBarry Smith Notes: 3232dc4c0fb0SBarry Smith If the `Amat` matrix and `Pmat` matrix are different you must call `MatAssemblyBegin()`/`MatAssemblyEnd()` on 323316913363SBarry Smith each matrix. 323416913363SBarry Smith 3235dc4c0fb0SBarry Smith If you know the operator `Amat` has a null space you can use `MatSetNullSpace()` and `MatSetTransposeNullSpace()` to supply the null 3236dc4c0fb0SBarry Smith space to `Amat` and the `KSP` solvers will automatically use that null space as needed during the solution process. 3237895c21f2SBarry Smith 3238dc4c0fb0SBarry Smith If using `SNESComputeJacobianDefaultColor()` to assemble a Jacobian, the `ctx` argument 3239f6dfbefdSBarry Smith must be a `MatFDColoring`. 3240a8a26c1eSJed Brown 3241c3cc8fd1SJed Brown Other defect-correction schemes can be used by computing a different matrix in place of the Jacobian. One common 3242f6dfbefdSBarry Smith example is to use the "Picard linearization" which only differentiates through the highest order parts of each term using `SNESSetPicard()` 3243c3cc8fd1SJed Brown 32441cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSPSetOperators()`, `SNESSetFunction()`, `MatMFFDComputeJacobian()`, `SNESComputeJacobianDefaultColor()`, `MatStructure`, 32458434afd1SBarry Smith `SNESSetPicard()`, `SNESJacobianFn`, `SNESFunctionFn` 32469b94acceSBarry Smith @*/ 32478434afd1SBarry Smith PetscErrorCode SNESSetJacobian(SNES snes, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx) 3248d71ae5a4SJacob Faibussowitsch { 32496cab3a1bSJed Brown DM dm; 32503a7fca6bSBarry Smith 32513a40ed3dSBarry Smith PetscFunctionBegin; 32520700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3253e5d3d808SBarry Smith if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2); 3254e5d3d808SBarry Smith if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3); 3255e5d3d808SBarry Smith if (Amat) PetscCheckSameComm(snes, 1, Amat, 2); 3256e5d3d808SBarry Smith if (Pmat) PetscCheckSameComm(snes, 1, Pmat, 3); 32579566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 32589566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, J, ctx)); 3259e5d3d808SBarry Smith if (Amat) { 32609566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)Amat)); 32619566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian)); 3262f5af7f23SKarl Rupp 3263e5d3d808SBarry Smith snes->jacobian = Amat; 32643a7fca6bSBarry Smith } 3265e5d3d808SBarry Smith if (Pmat) { 32669566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)Pmat)); 32679566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian_pre)); 3268f5af7f23SKarl Rupp 3269e5d3d808SBarry Smith snes->jacobian_pre = Pmat; 32703a7fca6bSBarry Smith } 32713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 32729b94acceSBarry Smith } 327362fef451SLois Curfman McInnes 3274c2aafc4cSSatish Balay /*@C 3275b4fd4287SBarry Smith SNESGetJacobian - Returns the Jacobian matrix and optionally the user 3276b4fd4287SBarry Smith provided context for evaluating the Jacobian. 3277b4fd4287SBarry Smith 3278420bcc1bSBarry Smith Not Collective, but `Mat` object will be parallel if `SNES` is 3279c7afd0dbSLois Curfman McInnes 3280b4fd4287SBarry Smith Input Parameter: 3281b4fd4287SBarry Smith . snes - the nonlinear solver context 3282b4fd4287SBarry Smith 3283b4fd4287SBarry Smith Output Parameters: 3284dc4c0fb0SBarry Smith + Amat - location to stash (approximate) Jacobian matrix (or `NULL`) 3285dc4c0fb0SBarry Smith . Pmat - location to stash matrix used to compute the preconditioner (or `NULL`) 32868434afd1SBarry Smith . J - location to put Jacobian function (or `NULL`), for calling sequence see `SNESJacobianFn` 3287dc4c0fb0SBarry Smith - ctx - location to stash Jacobian ctx (or `NULL`) 3288fee21e36SBarry Smith 328936851e7fSLois Curfman McInnes Level: advanced 329036851e7fSLois Curfman McInnes 32918434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `Mat`, `SNESSetJacobian()`, `SNESComputeJacobian()`, `SNESJacobianFn`, `SNESGetFunction()` 3292b4fd4287SBarry Smith @*/ 32938434afd1SBarry Smith PetscErrorCode SNESGetJacobian(SNES snes, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx) 3294d71ae5a4SJacob Faibussowitsch { 32956cab3a1bSJed Brown DM dm; 32966cab3a1bSJed Brown 32973a40ed3dSBarry Smith PetscFunctionBegin; 32980700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3299e5d3d808SBarry Smith if (Amat) *Amat = snes->jacobian; 3300e5d3d808SBarry Smith if (Pmat) *Pmat = snes->jacobian_pre; 33019566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 3302800f99ffSJeremy L Thompson PetscCall(DMSNESGetJacobian(dm, J, ctx)); 33033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3304b4fd4287SBarry Smith } 3305b4fd4287SBarry Smith 3306d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetDefaultComputeJacobian(SNES snes) 3307d71ae5a4SJacob Faibussowitsch { 330858b371f3SBarry Smith DM dm; 330958b371f3SBarry Smith DMSNES sdm; 331058b371f3SBarry Smith 331158b371f3SBarry Smith PetscFunctionBegin; 33129566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 33139566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 331458b371f3SBarry Smith if (!sdm->ops->computejacobian && snes->jacobian_pre) { 331558b371f3SBarry Smith DM dm; 331658b371f3SBarry Smith PetscBool isdense, ismf; 331758b371f3SBarry Smith 33189566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 33199566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &isdense, MATSEQDENSE, MATMPIDENSE, MATDENSE, NULL)); 33209566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &ismf, MATMFFD, MATSHELL, NULL)); 332158b371f3SBarry Smith if (isdense) { 33229566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefault, NULL)); 332358b371f3SBarry Smith } else if (!ismf) { 33249566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefaultColor, NULL)); 332558b371f3SBarry Smith } 332658b371f3SBarry Smith } 33273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 332858b371f3SBarry Smith } 332958b371f3SBarry Smith 33309b94acceSBarry Smith /*@ 33319b94acceSBarry Smith SNESSetUp - Sets up the internal data structures for the later use 33320b4b7b1cSBarry Smith of a nonlinear solver `SNESSolve()`. 33339b94acceSBarry Smith 3334c3339decSBarry Smith Collective 3335fee21e36SBarry Smith 33362fe279fdSBarry Smith Input Parameter: 3337f6dfbefdSBarry Smith . snes - the `SNES` context 3338c7afd0dbSLois Curfman McInnes 3339dc4c0fb0SBarry Smith Level: advanced 3340dc4c0fb0SBarry Smith 3341f6dfbefdSBarry Smith Note: 33420b4b7b1cSBarry Smith For basic use of the `SNES` solvers the user does not need to explicitly call 3343f6dfbefdSBarry Smith `SNESSetUp()`, since these actions will automatically occur during 3344f6dfbefdSBarry Smith the call to `SNESSolve()`. However, if one wishes to control this 3345f6dfbefdSBarry Smith phase separately, `SNESSetUp()` should be called after `SNESCreate()` 3346f6dfbefdSBarry Smith and optional routines of the form SNESSetXXX(), but before `SNESSolve()`. 3347272ac6f2SLois Curfman McInnes 33480b4b7b1cSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`, `SNESDestroy()`, `SNESSetFromOptions()` 33499b94acceSBarry Smith @*/ 3350d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUp(SNES snes) 3351d71ae5a4SJacob Faibussowitsch { 33526cab3a1bSJed Brown DM dm; 3353942e3340SBarry Smith DMSNES sdm; 3354c35f09e5SBarry Smith SNESLineSearch linesearch, pclinesearch; 33556e2a1849SPeter Brune void *lsprectx, *lspostctx; 33569b5c1c08SStefano Zampini PetscBool mf_operator, mf; 33579b5c1c08SStefano Zampini Vec f, fpc; 33589b5c1c08SStefano Zampini void *funcctx; 33599b5c1c08SStefano Zampini void *jacctx, *appctx; 33609b5c1c08SStefano Zampini Mat j, jpre; 33616b2b7091SBarry Smith PetscErrorCode (*precheck)(SNESLineSearch, Vec, Vec, PetscBool *, void *); 33626b2b7091SBarry Smith PetscErrorCode (*postcheck)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *); 33638434afd1SBarry Smith SNESFunctionFn *func; 33648434afd1SBarry Smith SNESJacobianFn *jac; 33653a40ed3dSBarry Smith 33663a40ed3dSBarry Smith PetscFunctionBegin; 33670700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 33683ba16761SJacob Faibussowitsch if (snes->setupcalled) PetscFunctionReturn(PETSC_SUCCESS); 3369fc8bc0e3SRichard Tran Mills PetscCall(PetscLogEventBegin(SNES_SetUp, snes, 0, 0, 0)); 33709b94acceSBarry Smith 337148a46eb9SPierre Jolivet if (!((PetscObject)snes)->type_name) PetscCall(SNESSetType(snes, SNESNEWTONLS)); 337285385478SLisandro Dalcin 33739566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &snes->vec_func, NULL, NULL)); 337458c9b817SLisandro Dalcin 33759566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 33769566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 33779566063dSJacob Faibussowitsch PetscCall(SNESSetDefaultComputeJacobian(snes)); 337858b371f3SBarry Smith 337948a46eb9SPierre Jolivet if (!snes->vec_func) PetscCall(DMCreateGlobalVector(dm, &snes->vec_func)); 3380efd51863SBarry Smith 338148a46eb9SPierre Jolivet if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 3382b710008aSBarry Smith 3383d8d34be6SBarry Smith if (snes->linesearch) { 33849566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 33859566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetFunction(snes->linesearch, SNESComputeFunction)); 3386d8d34be6SBarry Smith } 33879e764e56SPeter Brune 33889b5c1c08SStefano Zampini PetscCall(SNESGetUseMatrixFree(snes, &mf_operator, &mf)); 3389b552625fSStefano Zampini if (snes->npc && snes->npcside == PC_LEFT) { 3390172a4300SPeter Brune snes->mf = PETSC_TRUE; 3391172a4300SPeter Brune snes->mf_operator = PETSC_FALSE; 3392172a4300SPeter Brune } 3393d8f46077SPeter Brune 3394efd4aadfSBarry Smith if (snes->npc) { 33956e2a1849SPeter Brune /* copy the DM over */ 33969566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 33979566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes->npc, dm)); 33986e2a1849SPeter Brune 33999566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &f, &func, &funcctx)); 34009566063dSJacob Faibussowitsch PetscCall(VecDuplicate(f, &fpc)); 34019566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes->npc, fpc, func, funcctx)); 34029566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, &j, &jpre, &jac, &jacctx)); 34039566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes->npc, j, jpre, jac, jacctx)); 34049566063dSJacob Faibussowitsch PetscCall(SNESGetApplicationContext(snes, &appctx)); 34059566063dSJacob Faibussowitsch PetscCall(SNESSetApplicationContext(snes->npc, appctx)); 34069b5c1c08SStefano Zampini PetscCall(SNESSetUseMatrixFree(snes->npc, mf_operator, mf)); 34079566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fpc)); 34086e2a1849SPeter Brune 34096e2a1849SPeter Brune /* copy the function pointers over */ 34109566063dSJacob Faibussowitsch PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)snes->npc)); 34116e2a1849SPeter Brune 34126e2a1849SPeter Brune /* default to 1 iteration */ 34139566063dSJacob Faibussowitsch PetscCall(SNESSetTolerances(snes->npc, 0.0, 0.0, 0.0, 1, snes->npc->max_funcs)); 3414efd4aadfSBarry Smith if (snes->npcside == PC_RIGHT) { 34159566063dSJacob Faibussowitsch PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_FINAL_ONLY)); 3416a9936a0cSPeter Brune } else { 34179566063dSJacob Faibussowitsch PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_NONE)); 3418a9936a0cSPeter Brune } 34199566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes->npc)); 34206e2a1849SPeter Brune 34216e2a1849SPeter Brune /* copy the line search context over */ 3422d8d34be6SBarry Smith if (snes->linesearch && snes->npc->linesearch) { 34239566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &linesearch)); 34249566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes->npc, &pclinesearch)); 34259566063dSJacob Faibussowitsch PetscCall(SNESLineSearchGetPreCheck(linesearch, &precheck, &lsprectx)); 34269566063dSJacob Faibussowitsch PetscCall(SNESLineSearchGetPostCheck(linesearch, &postcheck, &lspostctx)); 34279566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetPreCheck(pclinesearch, precheck, lsprectx)); 34289566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetPostCheck(pclinesearch, postcheck, lspostctx)); 34299566063dSJacob Faibussowitsch PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch)); 34306e2a1849SPeter Brune } 3431d8d34be6SBarry Smith } 34321baa6e33SBarry Smith if (snes->mf) PetscCall(SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version)); 3433835f2295SStefano Zampini if (snes->ops->usercompute && !snes->ctx) PetscCallBack("SNES callback compute application context", (*snes->ops->usercompute)(snes, &snes->ctx)); 34346e2a1849SPeter Brune 343537ec4e1aSPeter Brune snes->jac_iter = 0; 343637ec4e1aSPeter Brune snes->pre_iter = 0; 343737ec4e1aSPeter Brune 3438dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, setup); 343958c9b817SLisandro Dalcin 34409566063dSJacob Faibussowitsch PetscCall(SNESSetDefaultComputeJacobian(snes)); 344158b371f3SBarry Smith 3442b552625fSStefano Zampini if (snes->npc && snes->npcside == PC_LEFT) { 34436c67d002SPeter Brune if (snes->functype == SNES_FUNCTION_PRECONDITIONED) { 3444d8d34be6SBarry Smith if (snes->linesearch) { 34459566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &linesearch)); 34469566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunctionDefaultNPC)); 34476c67d002SPeter Brune } 34486c67d002SPeter Brune } 3449d8d34be6SBarry Smith } 3450fc8bc0e3SRichard Tran Mills PetscCall(PetscLogEventEnd(SNES_SetUp, snes, 0, 0, 0)); 34517aaed0d8SBarry Smith snes->setupcalled = PETSC_TRUE; 34523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 34539b94acceSBarry Smith } 34549b94acceSBarry Smith 345537596af1SLisandro Dalcin /*@ 34560b4b7b1cSBarry 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 345737596af1SLisandro Dalcin 3458c3339decSBarry Smith Collective 345937596af1SLisandro Dalcin 346037596af1SLisandro Dalcin Input Parameter: 34610b4b7b1cSBarry Smith . snes - the nonlinear iterative solver context obtained from `SNESCreate()` 346237596af1SLisandro Dalcin 3463d25893d9SBarry Smith Level: intermediate 3464d25893d9SBarry Smith 346595452b02SPatrick Sanan Notes: 34660b4b7b1cSBarry Smith Any options set on the `SNES` object, including those set with `SNESSetFromOptions()` remain. 34670b4b7b1cSBarry Smith 3468f6dfbefdSBarry Smith Call this if you wish to reuse a `SNES` but with different size vectors 346937596af1SLisandro Dalcin 3470f6dfbefdSBarry Smith Also calls the application context destroy routine set with `SNESSetComputeApplicationContext()` 3471f6dfbefdSBarry Smith 34721cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESDestroy()`, `SNESCreate()`, `SNESSetUp()`, `SNESSolve()` 347337596af1SLisandro Dalcin @*/ 3474d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESReset(SNES snes) 3475d71ae5a4SJacob Faibussowitsch { 347637596af1SLisandro Dalcin PetscFunctionBegin; 347737596af1SLisandro Dalcin PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 347849abdd8aSBarry Smith if (snes->ops->ctxdestroy && snes->ctx) { 3479835f2295SStefano Zampini PetscCallBack("SNES callback destroy application context", (*snes->ops->ctxdestroy)(&snes->ctx)); 348049abdd8aSBarry Smith snes->ctx = NULL; 3481d25893d9SBarry Smith } 34821baa6e33SBarry Smith if (snes->npc) PetscCall(SNESReset(snes->npc)); 34838a23116dSBarry Smith 3484dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, reset); 34851baa6e33SBarry Smith if (snes->ksp) PetscCall(KSPReset(snes->ksp)); 34869e764e56SPeter Brune 34871baa6e33SBarry Smith if (snes->linesearch) PetscCall(SNESLineSearchReset(snes->linesearch)); 34889e764e56SPeter Brune 34899566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_rhs)); 34909566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol)); 34919566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol_update)); 34929566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_func)); 34939566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian)); 34949566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian_pre)); 34959566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->picard)); 34969566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(snes->nwork, &snes->work)); 34979566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(snes->nvwork, &snes->vwork)); 3498f5af7f23SKarl Rupp 349940fdac6aSLawrence Mitchell snes->alwayscomputesfinalresidual = PETSC_FALSE; 350040fdac6aSLawrence Mitchell 350137596af1SLisandro Dalcin snes->nwork = snes->nvwork = 0; 350237596af1SLisandro Dalcin snes->setupcalled = PETSC_FALSE; 35033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 350437596af1SLisandro Dalcin } 350537596af1SLisandro Dalcin 350652baeb72SSatish Balay /*@ 350736d43d94SBarry Smith SNESConvergedReasonViewCancel - Clears all the reason view functions for a `SNES` object provided with `SNESConvergedReasonViewSet()` also 350836d43d94SBarry Smith removes the default viewer. 3509c4421ceaSFande Kong 3510c3339decSBarry Smith Collective 3511c4421ceaSFande Kong 3512c4421ceaSFande Kong Input Parameter: 35130b4b7b1cSBarry Smith . snes - the nonlinear iterative solver context obtained from `SNESCreate()` 3514c4421ceaSFande Kong 3515c4421ceaSFande Kong Level: intermediate 3516c4421ceaSFande Kong 3517420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESReset()`, `SNESConvergedReasonViewSet()` 3518c4421ceaSFande Kong @*/ 3519d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewCancel(SNES snes) 3520d71ae5a4SJacob Faibussowitsch { 3521c4421ceaSFande Kong PetscInt i; 3522c4421ceaSFande Kong 3523c4421ceaSFande Kong PetscFunctionBegin; 3524c4421ceaSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3525c4421ceaSFande Kong for (i = 0; i < snes->numberreasonviews; i++) { 352648a46eb9SPierre Jolivet if (snes->reasonviewdestroy[i]) PetscCall((*snes->reasonviewdestroy[i])(&snes->reasonviewcontext[i])); 3527c4421ceaSFande Kong } 3528c4421ceaSFande Kong snes->numberreasonviews = 0; 3529648c30bcSBarry Smith PetscCall(PetscViewerDestroy(&snes->convergedreasonviewer)); 35303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3531c4421ceaSFande Kong } 3532c4421ceaSFande Kong 35330764c050SBarry Smith /*@ 35349b94acceSBarry Smith SNESDestroy - Destroys the nonlinear solver context that was created 3535f6dfbefdSBarry Smith with `SNESCreate()`. 35369b94acceSBarry Smith 3537c3339decSBarry Smith Collective 3538c7afd0dbSLois Curfman McInnes 35399b94acceSBarry Smith Input Parameter: 3540f6dfbefdSBarry Smith . snes - the `SNES` context 35419b94acceSBarry Smith 354236851e7fSLois Curfman McInnes Level: beginner 354336851e7fSLois Curfman McInnes 35441cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()` 35459b94acceSBarry Smith @*/ 3546d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESDestroy(SNES *snes) 3547d71ae5a4SJacob Faibussowitsch { 354892e852f7SPablo Brubeck DM dm; 354992e852f7SPablo Brubeck 35503a40ed3dSBarry Smith PetscFunctionBegin; 35513ba16761SJacob Faibussowitsch if (!*snes) PetscFunctionReturn(PETSC_SUCCESS); 3552f4f49eeaSPierre Jolivet PetscValidHeaderSpecific(*snes, SNES_CLASSID, 1); 3553f4f49eeaSPierre Jolivet if (--((PetscObject)*snes)->refct > 0) { 35549371c9d4SSatish Balay *snes = NULL; 35553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 35569371c9d4SSatish Balay } 3557d4bb536fSBarry Smith 3558f4f49eeaSPierre Jolivet PetscCall(SNESReset(*snes)); 35599566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&(*snes)->npc)); 35606b8b9a38SLisandro Dalcin 3561e04113cfSBarry Smith /* if memory was published with SAWs then destroy it */ 35629566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsViewOff((PetscObject)*snes)); 3563f4f49eeaSPierre Jolivet PetscTryTypeMethod(*snes, destroy); 35646d4c513bSLisandro Dalcin 356592e852f7SPablo Brubeck dm = (*snes)->dm; 356692e852f7SPablo Brubeck while (dm) { 356792e852f7SPablo Brubeck PetscCall(DMCoarsenHookRemove(dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, *snes)); 356892e852f7SPablo Brubeck PetscCall(DMGetCoarseDM(dm, &dm)); 356992e852f7SPablo Brubeck } 357092e852f7SPablo Brubeck 35719566063dSJacob Faibussowitsch PetscCall(DMDestroy(&(*snes)->dm)); 35729566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&(*snes)->ksp)); 35739566063dSJacob Faibussowitsch PetscCall(SNESLineSearchDestroy(&(*snes)->linesearch)); 35746b8b9a38SLisandro Dalcin 35759566063dSJacob Faibussowitsch PetscCall(PetscFree((*snes)->kspconvctx)); 357648a46eb9SPierre Jolivet if ((*snes)->ops->convergeddestroy) PetscCall((*(*snes)->ops->convergeddestroy)((*snes)->cnvP)); 357748a46eb9SPierre Jolivet if ((*snes)->conv_hist_alloc) PetscCall(PetscFree2((*snes)->conv_hist, (*snes)->conv_hist_its)); 3578f4f49eeaSPierre Jolivet PetscCall(SNESMonitorCancel(*snes)); 3579f4f49eeaSPierre Jolivet PetscCall(SNESConvergedReasonViewCancel(*snes)); 35809566063dSJacob Faibussowitsch PetscCall(PetscHeaderDestroy(snes)); 35813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 35829b94acceSBarry Smith } 35839b94acceSBarry Smith 35849b94acceSBarry Smith /* ----------- Routines to set solver parameters ---------- */ 35859b94acceSBarry Smith 3586a8054027SBarry Smith /*@ 35870b4b7b1cSBarry Smith SNESSetLagPreconditioner - Sets when the preconditioner is rebuilt in the nonlinear solve `SNESSolve()`. 3588a8054027SBarry Smith 3589c3339decSBarry Smith Logically Collective 3590a8054027SBarry Smith 3591a8054027SBarry Smith Input Parameters: 3592f6dfbefdSBarry Smith + snes - the `SNES` context 3593d8e291bfSBarry Smith - lag - 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time 35943b4f5425SBarry Smith the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that 3595a8054027SBarry Smith 3596a8054027SBarry Smith Options Database Keys: 3597420bcc1bSBarry Smith + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple `SNESSolve()` 35983d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 3599420bcc1bSBarry Smith . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple `SNESSolve()` 36003d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 3601a8054027SBarry Smith 3602dc4c0fb0SBarry Smith Level: intermediate 3603dc4c0fb0SBarry Smith 3604420bcc1bSBarry Smith Notes: 3605a8054027SBarry Smith The default is 1 3606420bcc1bSBarry Smith 3607f6dfbefdSBarry Smith The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagPreconditionerPersists()` was called 3608d8e291bfSBarry Smith 3609f6dfbefdSBarry Smith `SNESSetLagPreconditionerPersists()` allows using the same uniform lagging (for example every second linear solve) across multiple nonlinear solves. 3610a8054027SBarry Smith 36113201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetLagPreconditionerPersists()`, 3612f6dfbefdSBarry Smith `SNESSetLagJacobianPersists()`, `SNES`, `SNESSolve()` 3613a8054027SBarry Smith @*/ 3614d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditioner(SNES snes, PetscInt lag) 3615d71ae5a4SJacob Faibussowitsch { 3616a8054027SBarry Smith PetscFunctionBegin; 36170700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 36185f80ce2aSJacob Faibussowitsch PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater"); 36195f80ce2aSJacob Faibussowitsch PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0"); 3620c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, lag, 2); 3621a8054027SBarry Smith snes->lagpreconditioner = lag; 36223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3623a8054027SBarry Smith } 3624a8054027SBarry Smith 3625efd51863SBarry Smith /*@ 3626f6dfbefdSBarry Smith SNESSetGridSequence - sets the number of steps of grid sequencing that `SNES` will do 3627efd51863SBarry Smith 3628c3339decSBarry Smith Logically Collective 3629efd51863SBarry Smith 3630efd51863SBarry Smith Input Parameters: 3631f6dfbefdSBarry Smith + snes - the `SNES` context 3632efd51863SBarry Smith - steps - the number of refinements to do, defaults to 0 3633efd51863SBarry Smith 3634f6dfbefdSBarry Smith Options Database Key: 363567b8a455SSatish Balay . -snes_grid_sequence <steps> - Use grid sequencing to generate initial guess 3636efd51863SBarry Smith 3637efd51863SBarry Smith Level: intermediate 3638efd51863SBarry Smith 36390b4b7b1cSBarry Smith Notes: 36400b4b7b1cSBarry Smith Once grid sequencing is turned on `SNESSolve()` will automatically perform the solve on each grid refinement. 36410b4b7b1cSBarry Smith 3642f6dfbefdSBarry Smith Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing. 3643c0df2a02SJed Brown 36443201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetGridSequence()`, 364554c05997SPierre Jolivet `SNESSetDM()`, `SNESSolve()` 3646efd51863SBarry Smith @*/ 3647d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetGridSequence(SNES snes, PetscInt steps) 3648d71ae5a4SJacob Faibussowitsch { 3649efd51863SBarry Smith PetscFunctionBegin; 3650efd51863SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3651efd51863SBarry Smith PetscValidLogicalCollectiveInt(snes, steps, 2); 3652efd51863SBarry Smith snes->gridsequence = steps; 36533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3654efd51863SBarry Smith } 3655efd51863SBarry Smith 3656fa19ca70SBarry Smith /*@ 3657f6dfbefdSBarry Smith SNESGetGridSequence - gets the number of steps of grid sequencing that `SNES` will do 3658fa19ca70SBarry Smith 3659c3339decSBarry Smith Logically Collective 3660fa19ca70SBarry Smith 3661fa19ca70SBarry Smith Input Parameter: 3662f6dfbefdSBarry Smith . snes - the `SNES` context 3663fa19ca70SBarry Smith 3664fa19ca70SBarry Smith Output Parameter: 3665fa19ca70SBarry Smith . steps - the number of refinements to do, defaults to 0 3666fa19ca70SBarry Smith 3667fa19ca70SBarry Smith Level: intermediate 3668fa19ca70SBarry Smith 36693201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetGridSequence()` 3670fa19ca70SBarry Smith @*/ 3671d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetGridSequence(SNES snes, PetscInt *steps) 3672d71ae5a4SJacob Faibussowitsch { 3673fa19ca70SBarry Smith PetscFunctionBegin; 3674fa19ca70SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3675fa19ca70SBarry Smith *steps = snes->gridsequence; 36763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3677fa19ca70SBarry Smith } 3678fa19ca70SBarry Smith 3679a8054027SBarry Smith /*@ 3680f6dfbefdSBarry Smith SNESGetLagPreconditioner - Return how often the preconditioner is rebuilt 3681a8054027SBarry Smith 36823f9fe445SBarry Smith Not Collective 3683a8054027SBarry Smith 3684a8054027SBarry Smith Input Parameter: 3685f6dfbefdSBarry Smith . snes - the `SNES` context 3686a8054027SBarry Smith 3687a8054027SBarry Smith Output Parameter: 3688a8054027SBarry 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 36893b4f5425SBarry Smith the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that 3690a8054027SBarry Smith 3691dc4c0fb0SBarry Smith Level: intermediate 3692dc4c0fb0SBarry Smith 3693a8054027SBarry Smith Notes: 3694a8054027SBarry Smith The default is 1 3695f6dfbefdSBarry Smith 3696a8054027SBarry Smith The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 3697a8054027SBarry Smith 36983201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3699a8054027SBarry Smith @*/ 3700d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagPreconditioner(SNES snes, PetscInt *lag) 3701d71ae5a4SJacob Faibussowitsch { 3702a8054027SBarry Smith PetscFunctionBegin; 37030700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3704a8054027SBarry Smith *lag = snes->lagpreconditioner; 37053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3706a8054027SBarry Smith } 3707a8054027SBarry Smith 3708e35cf81dSBarry Smith /*@ 3709f6dfbefdSBarry Smith SNESSetLagJacobian - Set when the Jacobian is rebuilt in the nonlinear solve. See `SNESSetLagPreconditioner()` for determining how 3710e35cf81dSBarry Smith often the preconditioner is rebuilt. 3711e35cf81dSBarry Smith 3712c3339decSBarry Smith Logically Collective 3713e35cf81dSBarry Smith 3714e35cf81dSBarry Smith Input Parameters: 3715f6dfbefdSBarry Smith + snes - the `SNES` context 3716e35cf81dSBarry 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 3717fe3ffe1eSBarry Smith the Jacobian is built etc. -2 means rebuild at next chance but then never again 3718e35cf81dSBarry Smith 3719e35cf81dSBarry Smith Options Database Keys: 372079a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 37213d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 372279a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 37233d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag. 3724e35cf81dSBarry Smith 3725dc4c0fb0SBarry Smith Level: intermediate 3726dc4c0fb0SBarry Smith 3727e35cf81dSBarry Smith Notes: 3728e35cf81dSBarry Smith The default is 1 3729f6dfbefdSBarry Smith 3730e35cf81dSBarry Smith The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 3731f6dfbefdSBarry Smith 3732fe3ffe1eSBarry 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 3733fe3ffe1eSBarry Smith at the next Newton step but never again (unless it is reset to another value) 3734e35cf81dSBarry Smith 37353201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagPreconditioner()`, `SNESGetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3736e35cf81dSBarry Smith @*/ 3737d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobian(SNES snes, PetscInt lag) 3738d71ae5a4SJacob Faibussowitsch { 3739e35cf81dSBarry Smith PetscFunctionBegin; 37400700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 37415f80ce2aSJacob Faibussowitsch PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater"); 37425f80ce2aSJacob Faibussowitsch PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0"); 3743c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, lag, 2); 3744e35cf81dSBarry Smith snes->lagjacobian = lag; 37453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3746e35cf81dSBarry Smith } 3747e35cf81dSBarry Smith 3748e35cf81dSBarry Smith /*@ 3749f6dfbefdSBarry Smith SNESGetLagJacobian - Get how often the Jacobian is rebuilt. See `SNESGetLagPreconditioner()` to determine when the preconditioner is rebuilt 3750e35cf81dSBarry Smith 37513f9fe445SBarry Smith Not Collective 3752e35cf81dSBarry Smith 3753e35cf81dSBarry Smith Input Parameter: 3754f6dfbefdSBarry Smith . snes - the `SNES` context 3755e35cf81dSBarry Smith 3756e35cf81dSBarry Smith Output Parameter: 3757e35cf81dSBarry 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 3758e35cf81dSBarry Smith the Jacobian is built etc. 3759e35cf81dSBarry Smith 3760dc4c0fb0SBarry Smith Level: intermediate 3761dc4c0fb0SBarry Smith 3762e35cf81dSBarry Smith Notes: 3763e35cf81dSBarry Smith The default is 1 3764f6dfbefdSBarry Smith 3765f6dfbefdSBarry Smith The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagJacobianPersists()` was called. 3766e35cf81dSBarry Smith 37673201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobian()`, `SNESSetLagPreconditioner()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3768e35cf81dSBarry Smith 3769e35cf81dSBarry Smith @*/ 3770d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagJacobian(SNES snes, PetscInt *lag) 3771d71ae5a4SJacob Faibussowitsch { 3772e35cf81dSBarry Smith PetscFunctionBegin; 37730700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3774e35cf81dSBarry Smith *lag = snes->lagjacobian; 37753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3776e35cf81dSBarry Smith } 3777e35cf81dSBarry Smith 377837ec4e1aSPeter Brune /*@ 3779f6dfbefdSBarry Smith SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple nonlinear solves 378037ec4e1aSPeter Brune 3781c3339decSBarry Smith Logically collective 378237ec4e1aSPeter Brune 3783d8d19677SJose E. Roman Input Parameters: 3784f6dfbefdSBarry Smith + snes - the `SNES` context 37859d7e2deaSPeter Brune - flg - jacobian lagging persists if true 378637ec4e1aSPeter Brune 378737ec4e1aSPeter Brune Options Database Keys: 378879a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 37893d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 379079a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 37913d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 37923d5a8a6aSBarry Smith 3793dc4c0fb0SBarry Smith Level: advanced 3794dc4c0fb0SBarry Smith 379595452b02SPatrick Sanan Notes: 3796420bcc1bSBarry Smith Normally when `SNESSetLagJacobian()` is used, the Jacobian is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior 3797f6dfbefdSBarry Smith 379895452b02SPatrick Sanan This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by 379937ec4e1aSPeter Brune several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several 380037ec4e1aSPeter Brune timesteps may present huge efficiency gains. 380137ec4e1aSPeter Brune 380242747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditionerPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()` 380337ec4e1aSPeter Brune @*/ 3804d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobianPersists(SNES snes, PetscBool flg) 3805d71ae5a4SJacob Faibussowitsch { 380637ec4e1aSPeter Brune PetscFunctionBegin; 380737ec4e1aSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 380837ec4e1aSPeter Brune PetscValidLogicalCollectiveBool(snes, flg, 2); 380937ec4e1aSPeter Brune snes->lagjac_persist = flg; 38103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 381137ec4e1aSPeter Brune } 381237ec4e1aSPeter Brune 381337ec4e1aSPeter Brune /*@ 3814d8e291bfSBarry Smith SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple nonlinear solves 381537ec4e1aSPeter Brune 3816c3339decSBarry Smith Logically Collective 381737ec4e1aSPeter Brune 3818d8d19677SJose E. Roman Input Parameters: 3819f6dfbefdSBarry Smith + snes - the `SNES` context 38209d7e2deaSPeter Brune - flg - preconditioner lagging persists if true 382137ec4e1aSPeter Brune 382237ec4e1aSPeter Brune Options Database Keys: 382379a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 38243d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 382579a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 38263d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 382737ec4e1aSPeter Brune 3828dc4c0fb0SBarry Smith Level: developer 3829dc4c0fb0SBarry Smith 383095452b02SPatrick Sanan Notes: 3831420bcc1bSBarry Smith Normally when `SNESSetLagPreconditioner()` is used, the preconditioner is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior 3832f6dfbefdSBarry Smith 383395452b02SPatrick Sanan This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale 383437ec4e1aSPeter Brune by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over 383537ec4e1aSPeter Brune several timesteps may present huge efficiency gains. 383637ec4e1aSPeter Brune 38371cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobianPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagPreconditioner()` 383837ec4e1aSPeter Brune @*/ 3839d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes, PetscBool flg) 3840d71ae5a4SJacob Faibussowitsch { 384137ec4e1aSPeter Brune PetscFunctionBegin; 384237ec4e1aSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 384337ec4e1aSPeter Brune PetscValidLogicalCollectiveBool(snes, flg, 2); 384437ec4e1aSPeter Brune snes->lagpre_persist = flg; 38453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 384637ec4e1aSPeter Brune } 384737ec4e1aSPeter Brune 38489b94acceSBarry Smith /*@ 3849f6dfbefdSBarry Smith SNESSetForceIteration - force `SNESSolve()` to take at least one iteration regardless of the initial residual norm 3850be5caee7SBarry Smith 3851c3339decSBarry Smith Logically Collective 3852be5caee7SBarry Smith 3853be5caee7SBarry Smith Input Parameters: 3854f6dfbefdSBarry Smith + snes - the `SNES` context 3855f6dfbefdSBarry Smith - force - `PETSC_TRUE` require at least one iteration 3856be5caee7SBarry Smith 3857f6dfbefdSBarry Smith Options Database Key: 3858be5caee7SBarry Smith . -snes_force_iteration <force> - Sets forcing an iteration 3859be5caee7SBarry Smith 3860dc4c0fb0SBarry Smith Level: intermediate 3861dc4c0fb0SBarry Smith 3862f6dfbefdSBarry Smith Note: 3863f6dfbefdSBarry Smith This is used sometimes with `TS` to prevent `TS` from detecting a false steady state solution 3864be5caee7SBarry Smith 38653201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `TS`, `SNESSetDivergenceTolerance()` 3866be5caee7SBarry Smith @*/ 3867d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetForceIteration(SNES snes, PetscBool force) 3868d71ae5a4SJacob Faibussowitsch { 3869be5caee7SBarry Smith PetscFunctionBegin; 3870be5caee7SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3871be5caee7SBarry Smith snes->forceiteration = force; 38723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3873be5caee7SBarry Smith } 3874be5caee7SBarry Smith 387585216dc7SFande Kong /*@ 3876f6dfbefdSBarry Smith SNESGetForceIteration - Check whether or not `SNESSolve()` take at least one iteration regardless of the initial residual norm 387785216dc7SFande Kong 3878c3339decSBarry Smith Logically Collective 387985216dc7SFande Kong 38802fe279fdSBarry Smith Input Parameter: 3881f6dfbefdSBarry Smith . snes - the `SNES` context 388285216dc7SFande Kong 388385216dc7SFande Kong Output Parameter: 3884dc4c0fb0SBarry Smith . force - `PETSC_TRUE` requires at least one iteration. 388585216dc7SFande Kong 388606dd6b0eSSatish Balay Level: intermediate 388706dd6b0eSSatish Balay 38883201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetForceIteration()`, `SNESSetDivergenceTolerance()` 388985216dc7SFande Kong @*/ 3890d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetForceIteration(SNES snes, PetscBool *force) 3891d71ae5a4SJacob Faibussowitsch { 389285216dc7SFande Kong PetscFunctionBegin; 389385216dc7SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 389485216dc7SFande Kong *force = snes->forceiteration; 38953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 389685216dc7SFande Kong } 3897be5caee7SBarry Smith 3898be5caee7SBarry Smith /*@ 38990b4b7b1cSBarry Smith SNESSetTolerances - Sets various parameters used in `SNES` convergence tests. 39009b94acceSBarry Smith 3901c3339decSBarry Smith Logically Collective 3902c7afd0dbSLois Curfman McInnes 39039b94acceSBarry Smith Input Parameters: 3904f6dfbefdSBarry Smith + snes - the `SNES` context 39050b4b7b1cSBarry Smith . abstol - the absolute convergence tolerance, $ F(x^n) \le abstol $ 39060b4b7b1cSBarry Smith . rtol - the relative convergence tolerance, $ F(x^n) \le reltol * F(x^0) $ 39075358d0d4SBarry Smith . stol - convergence tolerance in terms of the norm of the change in the solution between steps, || delta x || < stol*|| x || 39080b4b7b1cSBarry Smith . maxit - the maximum number of iterations allowed in the solver, default 50. 39090b4b7b1cSBarry Smith - maxf - the maximum number of function evaluations allowed in the solver (use `PETSC_UNLIMITED` indicates no limit), default 10,000 3910fee21e36SBarry Smith 391133174efeSLois Curfman McInnes Options Database Keys: 391277e5a1f9SBarry Smith + -snes_atol <abstol> - Sets `abstol` 391377e5a1f9SBarry Smith . -snes_rtol <rtol> - Sets `rtol` 391477e5a1f9SBarry Smith . -snes_stol <stol> - Sets `stol` 391577e5a1f9SBarry Smith . -snes_max_it <maxit> - Sets `maxit` 391677e5a1f9SBarry Smith - -snes_max_funcs <maxf> - Sets `maxf` (use `unlimited` to have no maximum) 39179b94acceSBarry Smith 391836851e7fSLois Curfman McInnes Level: intermediate 391936851e7fSLois Curfman McInnes 392077e5a1f9SBarry Smith Note: 392177e5a1f9SBarry Smith All parameters must be non-negative 392277e5a1f9SBarry Smith 392377e5a1f9SBarry Smith Use `PETSC_CURRENT` to retain the current value of any parameter and `PETSC_DETERMINE` to use the default value for the given `SNES`. 392477e5a1f9SBarry Smith The default value is the value in the object when its type is set. 392577e5a1f9SBarry Smith 392677e5a1f9SBarry Smith Use `PETSC_UNLIMITED` on `maxit` or `maxf` to indicate there is no bound on the number of iterations or number of function evaluations. 392777e5a1f9SBarry Smith 392877e5a1f9SBarry Smith Fortran Note: 392977e5a1f9SBarry Smith Use `PETSC_CURRENT_INTEGER`, `PETSC_CURRENT_REAL`, `PETSC_UNLIMITED_INTEGER`, `PETSC_DETERMINE_INTEGER`, or `PETSC_DETERMINE_REAL` 393077e5a1f9SBarry Smith 39313201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESSolve()`, `SNES`, `SNESSetDivergenceTolerance()`, `SNESSetForceIteration()` 39329b94acceSBarry Smith @*/ 3933d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTolerances(SNES snes, PetscReal abstol, PetscReal rtol, PetscReal stol, PetscInt maxit, PetscInt maxf) 3934d71ae5a4SJacob Faibussowitsch { 39353a40ed3dSBarry Smith PetscFunctionBegin; 39360700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3937c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, abstol, 2); 3938c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, rtol, 3); 3939c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, stol, 4); 3940c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, maxit, 5); 3941c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, maxf, 6); 3942c5eb9154SBarry Smith 394377e5a1f9SBarry Smith if (abstol == (PetscReal)PETSC_DETERMINE) { 394477e5a1f9SBarry Smith snes->abstol = snes->default_abstol; 394577e5a1f9SBarry Smith } else if (abstol != (PetscReal)PETSC_CURRENT) { 39465f80ce2aSJacob Faibussowitsch PetscCheck(abstol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)abstol); 3947ab54825eSJed Brown snes->abstol = abstol; 3948ab54825eSJed Brown } 394977e5a1f9SBarry Smith 395077e5a1f9SBarry Smith if (rtol == (PetscReal)PETSC_DETERMINE) { 395177e5a1f9SBarry Smith snes->rtol = snes->default_rtol; 395277e5a1f9SBarry Smith } else if (rtol != (PetscReal)PETSC_CURRENT) { 39535f80ce2aSJacob 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); 3954ab54825eSJed Brown snes->rtol = rtol; 3955ab54825eSJed Brown } 395677e5a1f9SBarry Smith 395777e5a1f9SBarry Smith if (stol == (PetscReal)PETSC_DETERMINE) { 395877e5a1f9SBarry Smith snes->stol = snes->default_stol; 395977e5a1f9SBarry Smith } else if (stol != (PetscReal)PETSC_CURRENT) { 39605f80ce2aSJacob Faibussowitsch PetscCheck(stol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Step tolerance %g must be non-negative", (double)stol); 3961c60f73f4SPeter Brune snes->stol = stol; 3962ab54825eSJed Brown } 396377e5a1f9SBarry Smith 3964835f2295SStefano Zampini if (maxit == PETSC_DETERMINE) { 396577e5a1f9SBarry Smith snes->max_its = snes->default_max_its; 3966835f2295SStefano Zampini } else if (maxit == PETSC_UNLIMITED) { 396777e5a1f9SBarry Smith snes->max_its = PETSC_INT_MAX; 396877e5a1f9SBarry Smith } else if (maxit != PETSC_CURRENT) { 396963a3b9bcSJacob Faibussowitsch PetscCheck(maxit >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", maxit); 3970ab54825eSJed Brown snes->max_its = maxit; 3971ab54825eSJed Brown } 397277e5a1f9SBarry Smith 3973835f2295SStefano Zampini if (maxf == PETSC_DETERMINE) { 397477e5a1f9SBarry Smith snes->max_funcs = snes->default_max_funcs; 3975835f2295SStefano Zampini } else if (maxf == PETSC_UNLIMITED || maxf == -1) { 397677e5a1f9SBarry Smith snes->max_funcs = PETSC_UNLIMITED; 397777e5a1f9SBarry Smith } else if (maxf != PETSC_CURRENT) { 397877e5a1f9SBarry Smith PetscCheck(maxf >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations %" PetscInt_FMT " must be nonnegative", maxf); 3979ab54825eSJed Brown snes->max_funcs = maxf; 3980ab54825eSJed Brown } 39813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 39829b94acceSBarry Smith } 39839b94acceSBarry Smith 3984e4d06f11SPatrick Farrell /*@ 3985f6dfbefdSBarry Smith SNESSetDivergenceTolerance - Sets the divergence tolerance used for the `SNES` divergence test. 3986e4d06f11SPatrick Farrell 3987c3339decSBarry Smith Logically Collective 3988e4d06f11SPatrick Farrell 3989e4d06f11SPatrick Farrell Input Parameters: 3990f6dfbefdSBarry Smith + snes - the `SNES` context 39910b4b7b1cSBarry 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 39920b4b7b1cSBarry Smith is stopped due to divergence. 3993e4d06f11SPatrick Farrell 3994f6dfbefdSBarry Smith Options Database Key: 3995dc4c0fb0SBarry Smith . -snes_divergence_tolerance <divtol> - Sets `divtol` 3996e4d06f11SPatrick Farrell 3997e4d06f11SPatrick Farrell Level: intermediate 3998e4d06f11SPatrick Farrell 399977e5a1f9SBarry Smith Notes: 400077e5a1f9SBarry Smith Use `PETSC_DETERMINE` to use the default value from when the object's type was set. 4001e5cd489fSStefano Zampini 400277e5a1f9SBarry Smith Fortran Note: 400377e5a1f9SBarry Smith Use ``PETSC_DETERMINE_REAL` or `PETSC_UNLIMITED_REAL` 400477e5a1f9SBarry Smith 400577e5a1f9SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetTolerances()`, `SNESGetDivergenceTolerance()` 4006e4d06f11SPatrick Farrell @*/ 4007d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDivergenceTolerance(SNES snes, PetscReal divtol) 4008d71ae5a4SJacob Faibussowitsch { 4009e4d06f11SPatrick Farrell PetscFunctionBegin; 4010e4d06f11SPatrick Farrell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4011e4d06f11SPatrick Farrell PetscValidLogicalCollectiveReal(snes, divtol, 2); 401277e5a1f9SBarry Smith 401377e5a1f9SBarry Smith if (divtol == (PetscReal)PETSC_DETERMINE) { 401477e5a1f9SBarry Smith snes->divtol = snes->default_divtol; 401577e5a1f9SBarry Smith } else if (divtol == (PetscReal)PETSC_UNLIMITED || divtol == -1) { 401677e5a1f9SBarry Smith snes->divtol = PETSC_UNLIMITED; 401777e5a1f9SBarry Smith } else if (divtol != (PetscReal)PETSC_CURRENT) { 401877e5a1f9SBarry Smith PetscCheck(divtol >= 1.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Divergence tolerance %g must be greater than 1.0", (double)divtol); 401977e5a1f9SBarry Smith snes->divtol = divtol; 402077e5a1f9SBarry Smith } 40213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4022e4d06f11SPatrick Farrell } 4023e4d06f11SPatrick Farrell 40249b94acceSBarry Smith /*@ 40250b4b7b1cSBarry Smith SNESGetTolerances - Gets various parameters used in `SNES` convergence tests. 402633174efeSLois Curfman McInnes 4027c7afd0dbSLois Curfman McInnes Not Collective 4028c7afd0dbSLois Curfman McInnes 402977e5a1f9SBarry Smith Input Parameter: 403077e5a1f9SBarry Smith . snes - the `SNES` context 403177e5a1f9SBarry Smith 403277e5a1f9SBarry Smith Output Parameters: 40330b4b7b1cSBarry Smith + atol - the absolute convergence tolerance 40340b4b7b1cSBarry Smith . rtol - the relative convergence tolerance 403577e5a1f9SBarry Smith . stol - convergence tolerance in terms of the norm of the change in the solution between steps 40360b4b7b1cSBarry Smith . maxit - the maximum number of iterations allowed 40370b4b7b1cSBarry Smith - maxf - the maximum number of function evaluations allowed, `PETSC_UNLIMITED` indicates no bound 4038fee21e36SBarry Smith 403936851e7fSLois Curfman McInnes Level: intermediate 404036851e7fSLois Curfman McInnes 40410b4b7b1cSBarry Smith Notes: 40420b4b7b1cSBarry Smith See `SNESSetTolerances()` for details on the parameters. 40430b4b7b1cSBarry Smith 4044dc4c0fb0SBarry Smith The user can specify `NULL` for any parameter that is not needed. 4045dc4c0fb0SBarry Smith 40461cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTolerances()` 404733174efeSLois Curfman McInnes @*/ 4048d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetTolerances(SNES snes, PetscReal *atol, PetscReal *rtol, PetscReal *stol, PetscInt *maxit, PetscInt *maxf) 4049d71ae5a4SJacob Faibussowitsch { 40503a40ed3dSBarry Smith PetscFunctionBegin; 40510700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 405285385478SLisandro Dalcin if (atol) *atol = snes->abstol; 405333174efeSLois Curfman McInnes if (rtol) *rtol = snes->rtol; 4054c60f73f4SPeter Brune if (stol) *stol = snes->stol; 405533174efeSLois Curfman McInnes if (maxit) *maxit = snes->max_its; 405633174efeSLois Curfman McInnes if (maxf) *maxf = snes->max_funcs; 40573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 405833174efeSLois Curfman McInnes } 405933174efeSLois Curfman McInnes 4060e4d06f11SPatrick Farrell /*@ 4061e4d06f11SPatrick Farrell SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test. 4062e4d06f11SPatrick Farrell 4063e4d06f11SPatrick Farrell Not Collective 4064e4d06f11SPatrick Farrell 4065e4d06f11SPatrick Farrell Input Parameters: 4066f6dfbefdSBarry Smith + snes - the `SNES` context 4067e4d06f11SPatrick Farrell - divtol - divergence tolerance 4068e4d06f11SPatrick Farrell 4069e4d06f11SPatrick Farrell Level: intermediate 4070e4d06f11SPatrick Farrell 40711cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetDivergenceTolerance()` 4072e4d06f11SPatrick Farrell @*/ 4073d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDivergenceTolerance(SNES snes, PetscReal *divtol) 4074d71ae5a4SJacob Faibussowitsch { 4075e4d06f11SPatrick Farrell PetscFunctionBegin; 4076e4d06f11SPatrick Farrell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4077e4d06f11SPatrick Farrell if (divtol) *divtol = snes->divtol; 40783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4079e4d06f11SPatrick Farrell } 4080e4d06f11SPatrick Farrell 40816ba87a44SLisandro Dalcin PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *); 40826ba87a44SLisandro Dalcin 4083d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorLGRange(SNES snes, PetscInt n, PetscReal rnorm, void *monctx) 4084d71ae5a4SJacob Faibussowitsch { 4085b271bb04SBarry Smith PetscDrawLG lg; 4086b271bb04SBarry Smith PetscReal x, y, per; 4087b271bb04SBarry Smith PetscViewer v = (PetscViewer)monctx; 4088b271bb04SBarry Smith static PetscReal prev; /* should be in the context */ 4089b271bb04SBarry Smith PetscDraw draw; 4090b271bb04SBarry Smith 4091459f5d12SBarry Smith PetscFunctionBegin; 40924d4332d5SBarry Smith PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 4); 40939566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 0, &lg)); 40949566063dSJacob Faibussowitsch if (!n) PetscCall(PetscDrawLGReset(lg)); 40959566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 40969566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "Residual norm")); 4097b271bb04SBarry Smith x = (PetscReal)n; 409877b4d14cSPeter Brune if (rnorm > 0.0) y = PetscLog10Real(rnorm); 409994c9c6d3SKarl Rupp else y = -15.0; 41009566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 41016934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 41029566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 41039566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 4104b271bb04SBarry Smith } 4105b271bb04SBarry Smith 41069566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 1, &lg)); 41079566063dSJacob Faibussowitsch if (!n) PetscCall(PetscDrawLGReset(lg)); 41089566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 4109aaa8cc7dSPierre Jolivet PetscCall(PetscDrawSetTitle(draw, "% elements > .2*max element")); 41109566063dSJacob Faibussowitsch PetscCall(SNESMonitorRange_Private(snes, n, &per)); 4111b271bb04SBarry Smith x = (PetscReal)n; 4112b271bb04SBarry Smith y = 100.0 * per; 41139566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 41146934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 41159566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 41169566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 4117b271bb04SBarry Smith } 4118b271bb04SBarry Smith 41199566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 2, &lg)); 41209371c9d4SSatish Balay if (!n) { 41219371c9d4SSatish Balay prev = rnorm; 41229371c9d4SSatish Balay PetscCall(PetscDrawLGReset(lg)); 41239371c9d4SSatish Balay } 41249566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 41259566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm")); 4126b271bb04SBarry Smith x = (PetscReal)n; 4127b271bb04SBarry Smith y = (prev - rnorm) / prev; 41289566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 41296934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 41309566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 41319566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 4132b271bb04SBarry Smith } 4133b271bb04SBarry Smith 41349566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 3, &lg)); 41359566063dSJacob Faibussowitsch if (!n) PetscCall(PetscDrawLGReset(lg)); 41369566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 41379566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm*(% > .2 max)")); 4138b271bb04SBarry Smith x = (PetscReal)n; 4139b271bb04SBarry Smith y = (prev - rnorm) / (prev * per); 4140b271bb04SBarry Smith if (n > 2) { /*skip initial crazy value */ 41419566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 4142b271bb04SBarry Smith } 41436934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 41449566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 41459566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 4146b271bb04SBarry Smith } 4147b271bb04SBarry Smith prev = rnorm; 41483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4149b271bb04SBarry Smith } 4150b271bb04SBarry Smith 4151228d79bcSJed Brown /*@ 41522d157150SStefano Zampini SNESConverged - Run the convergence test and update the `SNESConvergedReason`. 41532d157150SStefano Zampini 41542d157150SStefano Zampini Collective 41552d157150SStefano Zampini 41562d157150SStefano Zampini Input Parameters: 41572d157150SStefano Zampini + snes - the `SNES` context 41582d157150SStefano Zampini . it - current iteration 41592d157150SStefano Zampini . xnorm - 2-norm of current iterate 41602d157150SStefano Zampini . snorm - 2-norm of current step 41612d157150SStefano Zampini - fnorm - 2-norm of function 41622d157150SStefano Zampini 41632d157150SStefano Zampini Level: developer 41642d157150SStefano Zampini 41652d157150SStefano Zampini Note: 4166420bcc1bSBarry Smith This routine is called by the `SNESSolve()` implementations. 41672d157150SStefano Zampini It does not typically need to be called by the user. 41682d157150SStefano Zampini 4169c948abdaSPierre Jolivet .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()` 41702d157150SStefano Zampini @*/ 41712d157150SStefano Zampini PetscErrorCode SNESConverged(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm) 41722d157150SStefano Zampini { 41732d157150SStefano Zampini PetscFunctionBegin; 41742d157150SStefano Zampini if (!snes->reason) { 41752d157150SStefano Zampini if (snes->normschedule == SNES_NORM_ALWAYS) PetscUseTypeMethod(snes, converged, it, xnorm, snorm, fnorm, &snes->reason, snes->cnvP); 41762d157150SStefano Zampini if (it == snes->max_its && !snes->reason) { 41772d157150SStefano Zampini if (snes->normschedule == SNES_NORM_ALWAYS) { 41782d157150SStefano Zampini PetscCall(PetscInfo(snes, "Maximum number of iterations has been reached: %" PetscInt_FMT "\n", snes->max_its)); 41792d157150SStefano Zampini snes->reason = SNES_DIVERGED_MAX_IT; 41802d157150SStefano Zampini } else snes->reason = SNES_CONVERGED_ITS; 41812d157150SStefano Zampini } 41822d157150SStefano Zampini } 41832d157150SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 41842d157150SStefano Zampini } 41852d157150SStefano Zampini 41862d157150SStefano Zampini /*@ 41870b4b7b1cSBarry Smith SNESMonitor - runs any `SNES` monitor routines provided with `SNESMonitor()` or the options database 4188228d79bcSJed Brown 4189c3339decSBarry Smith Collective 4190228d79bcSJed Brown 4191228d79bcSJed Brown Input Parameters: 4192f6dfbefdSBarry Smith + snes - nonlinear solver context obtained from `SNESCreate()` 41930b4b7b1cSBarry Smith . iter - current iteration number 41940b4b7b1cSBarry Smith - rnorm - current relative norm of the residual 4195228d79bcSJed Brown 4196dc4c0fb0SBarry Smith Level: developer 4197dc4c0fb0SBarry Smith 4198f6dfbefdSBarry Smith Note: 4199420bcc1bSBarry Smith This routine is called by the `SNESSolve()` implementations. 4200228d79bcSJed Brown It does not typically need to be called by the user. 4201228d79bcSJed Brown 42021cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorSet()` 4203228d79bcSJed Brown @*/ 4204d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitor(SNES snes, PetscInt iter, PetscReal rnorm) 4205d71ae5a4SJacob Faibussowitsch { 42067a03ce2fSLisandro Dalcin PetscInt i, n = snes->numbermonitors; 42077a03ce2fSLisandro Dalcin 42087a03ce2fSLisandro Dalcin PetscFunctionBegin; 42099566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(snes->vec_sol)); 421048a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall((*snes->monitor[i])(snes, iter, rnorm, snes->monitorcontext[i])); 42119566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(snes->vec_sol)); 42123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 42137a03ce2fSLisandro Dalcin } 42147a03ce2fSLisandro Dalcin 42159b94acceSBarry Smith /* ------------ Routines to set performance monitoring options ----------- */ 42169b94acceSBarry Smith 4217bf388a1fSBarry Smith /*MC 4218f6dfbefdSBarry Smith SNESMonitorFunction - functional form passed to `SNESMonitorSet()` to monitor convergence of nonlinear solver 4219bf388a1fSBarry Smith 4220bf388a1fSBarry Smith Synopsis: 4221aaa7dc30SBarry Smith #include <petscsnes.h> 422237fdd005SBarry Smith PetscErrorCode SNESMonitorFunction(SNES snes, PetscInt its, PetscReal norm, void *mctx) 4223bf388a1fSBarry Smith 4224c3339decSBarry Smith Collective 42251843f636SBarry Smith 42261843f636SBarry Smith Input Parameters: 4227f6dfbefdSBarry Smith + snes - the `SNES` context 4228bf388a1fSBarry Smith . its - iteration number 4229bf388a1fSBarry Smith . norm - 2-norm function value (may be estimated) 4230bf388a1fSBarry Smith - mctx - [optional] monitoring context 4231bf388a1fSBarry Smith 4232878cb397SSatish Balay Level: advanced 4233878cb397SSatish Balay 4234*56296ac4SStefano Zampini .seealso: [](ch_snes), `SNESMonitorSet()` 4235bf388a1fSBarry Smith M*/ 4236bf388a1fSBarry Smith 42379b94acceSBarry Smith /*@C 4238a6570f20SBarry Smith SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every 42390b4b7b1cSBarry Smith iteration of the `SNES` nonlinear solver to display the iteration's 42409b94acceSBarry Smith progress. 42419b94acceSBarry Smith 4242c3339decSBarry Smith Logically Collective 4243fee21e36SBarry Smith 4244c7afd0dbSLois Curfman McInnes Input Parameters: 4245f6dfbefdSBarry Smith + snes - the `SNES` context 424620f4b53cSBarry Smith . f - the monitor function, for the calling sequence see `SNESMonitorFunction` 4247420bcc1bSBarry Smith . mctx - [optional] user-defined context for private data for the monitor routine (use `NULL` if no context is desired) 424849abdd8aSBarry Smith - monitordestroy - [optional] routine that frees monitor context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence 42499b94acceSBarry Smith 42509665c990SLois Curfman McInnes Options Database Keys: 4251f6dfbefdSBarry Smith + -snes_monitor - sets `SNESMonitorDefault()` 4252798534f6SMatthew G. Knepley . -snes_monitor draw::draw_lg - sets line graph monitor, 4253dc4c0fb0SBarry 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 4254c7afd0dbSLois Curfman McInnes the options database. 42559665c990SLois Curfman McInnes 4256dc4c0fb0SBarry Smith Level: intermediate 4257dc4c0fb0SBarry Smith 4258f6dfbefdSBarry Smith Note: 42596bc08f3fSLois Curfman McInnes Several different monitoring routines may be set by calling 4260f6dfbefdSBarry Smith `SNESMonitorSet()` multiple times; all will be called in the 42616bc08f3fSLois Curfman McInnes order in which they were set. 4262639f9d9dSBarry Smith 4263420bcc1bSBarry Smith Fortran Note: 4264f6dfbefdSBarry Smith Only a single monitor function can be set for each `SNES` object 4265025f1a04SBarry Smith 426649abdd8aSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESMonitorDefault()`, `SNESMonitorCancel()`, `SNESMonitorFunction`, `PetscCtxDestroyFn` 42679b94acceSBarry Smith @*/ 426849abdd8aSBarry Smith PetscErrorCode SNESMonitorSet(SNES snes, PetscErrorCode (*f)(SNES, PetscInt, PetscReal, void *), void *mctx, PetscCtxDestroyFn *monitordestroy) 4269d71ae5a4SJacob Faibussowitsch { 4270b90d0a6eSBarry Smith PetscInt i; 427178064530SBarry Smith PetscBool identical; 4272b90d0a6eSBarry Smith 42733a40ed3dSBarry Smith PetscFunctionBegin; 42740700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4275b90d0a6eSBarry Smith for (i = 0; i < snes->numbermonitors; i++) { 42769566063dSJacob Faibussowitsch PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))f, mctx, monitordestroy, (PetscErrorCode (*)(void))snes->monitor[i], snes->monitorcontext[i], snes->monitordestroy[i], &identical)); 42773ba16761SJacob Faibussowitsch if (identical) PetscFunctionReturn(PETSC_SUCCESS); 4278649052a6SBarry Smith } 42795f80ce2aSJacob Faibussowitsch PetscCheck(snes->numbermonitors < MAXSNESMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set"); 42806e4dcb14SBarry Smith snes->monitor[snes->numbermonitors] = f; 4281b8a78c4aSBarry Smith snes->monitordestroy[snes->numbermonitors] = monitordestroy; 4282835f2295SStefano Zampini snes->monitorcontext[snes->numbermonitors++] = mctx; 42833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 42849b94acceSBarry Smith } 42859b94acceSBarry Smith 4286a278d85bSSatish Balay /*@ 4287f6dfbefdSBarry Smith SNESMonitorCancel - Clears all the monitor functions for a `SNES` object. 42885cd90555SBarry Smith 4289c3339decSBarry Smith Logically Collective 4290c7afd0dbSLois Curfman McInnes 42912fe279fdSBarry Smith Input Parameter: 4292f6dfbefdSBarry Smith . snes - the `SNES` context 42935cd90555SBarry Smith 42941a480d89SAdministrator Options Database Key: 4295a6570f20SBarry Smith . -snes_monitor_cancel - cancels all monitors that have been hardwired 4296dc4c0fb0SBarry Smith into a code by calls to `SNESMonitorSet()`, but does not cancel those 4297c7afd0dbSLois Curfman McInnes set via the options database 42985cd90555SBarry Smith 4299dc4c0fb0SBarry Smith Level: intermediate 4300dc4c0fb0SBarry Smith 4301f6dfbefdSBarry Smith Note: 4302f6dfbefdSBarry Smith There is no way to clear one specific monitor from a `SNES` object. 43035cd90555SBarry Smith 4304*56296ac4SStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESMonitorDefault()`, `SNESMonitorSet()` 43055cd90555SBarry Smith @*/ 4306d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorCancel(SNES snes) 4307d71ae5a4SJacob Faibussowitsch { 4308d952e501SBarry Smith PetscInt i; 4309d952e501SBarry Smith 43105cd90555SBarry Smith PetscFunctionBegin; 43110700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4312d952e501SBarry Smith for (i = 0; i < snes->numbermonitors; i++) { 431348a46eb9SPierre Jolivet if (snes->monitordestroy[i]) PetscCall((*snes->monitordestroy[i])(&snes->monitorcontext[i])); 4314d952e501SBarry Smith } 43155cd90555SBarry Smith snes->numbermonitors = 0; 43163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 43175cd90555SBarry Smith } 43185cd90555SBarry Smith 4319bf388a1fSBarry Smith /*MC 4320bf388a1fSBarry Smith SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver 4321bf388a1fSBarry Smith 4322bf388a1fSBarry Smith Synopsis: 4323aaa7dc30SBarry Smith #include <petscsnes.h> 432437fdd005SBarry Smith PetscErrorCode SNESConvergenceTest(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *cctx) 4325bf388a1fSBarry Smith 4326c3339decSBarry Smith Collective 43271843f636SBarry Smith 43281843f636SBarry Smith Input Parameters: 4329f6dfbefdSBarry Smith + snes - the `SNES` context 4330bf388a1fSBarry Smith . it - current iteration (0 is the first and is before any Newton step) 4331bf388a1fSBarry Smith . xnorm - 2-norm of current iterate 4332bf388a1fSBarry Smith . gnorm - 2-norm of current step 43331843f636SBarry Smith . f - 2-norm of function 43341843f636SBarry Smith - cctx - [optional] convergence context 43351843f636SBarry Smith 43361843f636SBarry Smith Output Parameter: 43371843f636SBarry Smith . reason - reason for convergence/divergence, only needs to be set when convergence or divergence is detected 4338bf388a1fSBarry Smith 4339878cb397SSatish Balay Level: intermediate 4340bf388a1fSBarry Smith 4341c948abdaSPierre Jolivet .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()` 4342bf388a1fSBarry Smith M*/ 4343bf388a1fSBarry Smith 43449b94acceSBarry Smith /*@C 43459b94acceSBarry Smith SNESSetConvergenceTest - Sets the function that is to be used 43469b94acceSBarry Smith to test for convergence of the nonlinear iterative solution. 43479b94acceSBarry Smith 4348c3339decSBarry Smith Logically Collective 4349fee21e36SBarry Smith 4350c7afd0dbSLois Curfman McInnes Input Parameters: 4351f6dfbefdSBarry Smith + snes - the `SNES` context 4352e4094ef1SJacob Faibussowitsch . SNESConvergenceTestFunction - routine to test for convergence 4353dc4c0fb0SBarry Smith . cctx - [optional] context for private data for the convergence routine (may be `NULL`) 4354dc4c0fb0SBarry Smith - destroy - [optional] destructor for the context (may be `NULL`; `PETSC_NULL_FUNCTION` in Fortran) 43559b94acceSBarry Smith 435636851e7fSLois Curfman McInnes Level: advanced 435736851e7fSLois Curfman McInnes 43581cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedDefault()`, `SNESConvergedSkip()`, `SNESConvergenceTestFunction` 43599b94acceSBarry Smith @*/ 4360d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceTest(SNES snes, PetscErrorCode (*SNESConvergenceTestFunction)(SNES, PetscInt, PetscReal, PetscReal, PetscReal, SNESConvergedReason *, void *), void *cctx, PetscErrorCode (*destroy)(void *)) 4361d71ae5a4SJacob Faibussowitsch { 43623a40ed3dSBarry Smith PetscFunctionBegin; 43630700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4364e2a6519dSDmitry Karpeev if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip; 43651baa6e33SBarry Smith if (snes->ops->convergeddestroy) PetscCall((*snes->ops->convergeddestroy)(snes->cnvP)); 4366bf388a1fSBarry Smith snes->ops->converged = SNESConvergenceTestFunction; 43677f7931b9SBarry Smith snes->ops->convergeddestroy = destroy; 436885385478SLisandro Dalcin snes->cnvP = cctx; 43693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 43709b94acceSBarry Smith } 43719b94acceSBarry Smith 437252baeb72SSatish Balay /*@ 43730b4b7b1cSBarry Smith SNESGetConvergedReason - Gets the reason the `SNES` iteration was stopped, which may be due to convergence, divergence, or stagnation 4374184914b5SBarry Smith 4375184914b5SBarry Smith Not Collective 4376184914b5SBarry Smith 4377184914b5SBarry Smith Input Parameter: 4378f6dfbefdSBarry Smith . snes - the `SNES` context 4379184914b5SBarry Smith 4380184914b5SBarry Smith Output Parameter: 4381f6dfbefdSBarry Smith . reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` for the individual convergence tests for complete lists 4382184914b5SBarry Smith 4383f6dfbefdSBarry Smith Options Database Key: 43846a4d7782SBarry Smith . -snes_converged_reason - prints the reason to standard out 43856a4d7782SBarry Smith 4386184914b5SBarry Smith Level: intermediate 4387184914b5SBarry Smith 4388f6dfbefdSBarry Smith Note: 4389f6dfbefdSBarry Smith Should only be called after the call the `SNESSolve()` is complete, if it is called earlier it returns the value `SNES__CONVERGED_ITERATING`. 4390184914b5SBarry Smith 43911cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESSetConvergedReason()`, `SNESConvergedReason`, `SNESGetConvergedReasonString()` 4392184914b5SBarry Smith @*/ 4393d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReason(SNES snes, SNESConvergedReason *reason) 4394d71ae5a4SJacob Faibussowitsch { 4395184914b5SBarry Smith PetscFunctionBegin; 43960700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 43974f572ea9SToby Isaac PetscAssertPointer(reason, 2); 4398184914b5SBarry Smith *reason = snes->reason; 43993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4400184914b5SBarry Smith } 4401184914b5SBarry Smith 4402c4421ceaSFande Kong /*@C 4403f6dfbefdSBarry Smith SNESGetConvergedReasonString - Return a human readable string for `SNESConvergedReason` 4404c4421ceaSFande Kong 4405c4421ceaSFande Kong Not Collective 4406c4421ceaSFande Kong 4407c4421ceaSFande Kong Input Parameter: 4408f6dfbefdSBarry Smith . snes - the `SNES` context 4409c4421ceaSFande Kong 4410c4421ceaSFande Kong Output Parameter: 4411dc4c0fb0SBarry Smith . strreason - a human readable string that describes `SNES` converged reason 4412c4421ceaSFande Kong 441399c90e12SSatish Balay Level: beginner 4414c4421ceaSFande Kong 44151cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetConvergedReason()` 4416c4421ceaSFande Kong @*/ 4417d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReasonString(SNES snes, const char **strreason) 4418d71ae5a4SJacob Faibussowitsch { 4419c4421ceaSFande Kong PetscFunctionBegin; 4420c4421ceaSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 44214f572ea9SToby Isaac PetscAssertPointer(strreason, 2); 4422c4421ceaSFande Kong *strreason = SNESConvergedReasons[snes->reason]; 44233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4424c4421ceaSFande Kong } 4425c4421ceaSFande Kong 442633866048SMatthew G. Knepley /*@ 4427f6dfbefdSBarry Smith SNESSetConvergedReason - Sets the reason the `SNES` iteration was stopped. 442833866048SMatthew G. Knepley 442933866048SMatthew G. Knepley Not Collective 443033866048SMatthew G. Knepley 443133866048SMatthew G. Knepley Input Parameters: 4432f6dfbefdSBarry Smith + snes - the `SNES` context 4433f6dfbefdSBarry Smith - reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` or the 443433866048SMatthew G. Knepley manual pages for the individual convergence tests for complete lists 443533866048SMatthew G. Knepley 4436f6dfbefdSBarry Smith Level: developer 4437f6dfbefdSBarry Smith 4438420bcc1bSBarry Smith Developer Note: 4439f6dfbefdSBarry Smith Called inside the various `SNESSolve()` implementations 444033866048SMatthew G. Knepley 44411cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetConvergedReason()`, `SNESSetConvergenceTest()`, `SNESConvergedReason` 444233866048SMatthew G. Knepley @*/ 4443d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergedReason(SNES snes, SNESConvergedReason reason) 4444d71ae5a4SJacob Faibussowitsch { 444533866048SMatthew G. Knepley PetscFunctionBegin; 444633866048SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 44475f3c5e7aSBarry Smith PetscCheck(!snes->errorifnotconverged || reason > 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "SNES code should have previously errored due to negative reason"); 444833866048SMatthew G. Knepley snes->reason = reason; 44493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 445033866048SMatthew G. Knepley } 445133866048SMatthew G. Knepley 4452c9005455SLois Curfman McInnes /*@ 4453420bcc1bSBarry Smith SNESSetConvergenceHistory - Sets the arrays used to hold the convergence history. 4454c9005455SLois Curfman McInnes 4455c3339decSBarry Smith Logically Collective 4456fee21e36SBarry Smith 4457c7afd0dbSLois Curfman McInnes Input Parameters: 4458f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 44598c7482ecSBarry Smith . a - array to hold history, this array will contain the function norms computed at each step 4460cd5578b5SBarry Smith . its - integer array holds the number of linear iterations for each solve. 4461420bcc1bSBarry Smith . na - size of `a` and `its` 4462f6dfbefdSBarry Smith - reset - `PETSC_TRUE` indicates each new nonlinear solve resets the history counter to zero, 4463758f92a0SBarry Smith else it continues storing new values for new nonlinear solves after the old ones 4464c7afd0dbSLois Curfman McInnes 4465dc4c0fb0SBarry Smith Level: intermediate 4466dc4c0fb0SBarry Smith 4467308dcc3eSBarry Smith Notes: 4468ce78bad3SBarry 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 446977e5a1f9SBarry Smith default array of length 1,000 is allocated. 4470308dcc3eSBarry Smith 4471c9005455SLois Curfman McInnes This routine is useful, e.g., when running a code for purposes 4472c9005455SLois Curfman McInnes of accurate performance monitoring, when no I/O should be done 4473c9005455SLois Curfman McInnes during the section of code that is being timed. 4474c9005455SLois Curfman McInnes 4475420bcc1bSBarry Smith If the arrays run out of space after a number of iterations then the later values are not saved in the history 4476420bcc1bSBarry Smith 44771cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetConvergenceHistory()` 4478c9005455SLois Curfman McInnes @*/ 4479d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceHistory(SNES snes, PetscReal a[], PetscInt its[], PetscInt na, PetscBool reset) 4480d71ae5a4SJacob Faibussowitsch { 44813a40ed3dSBarry Smith PetscFunctionBegin; 44820700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 44834f572ea9SToby Isaac if (a) PetscAssertPointer(a, 2); 44844f572ea9SToby Isaac if (its) PetscAssertPointer(its, 3); 44857a1ec6d4SBarry Smith if (!a) { 448677e5a1f9SBarry Smith if (na == PETSC_DECIDE) na = 1000; 44879566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(na, &a, na, &its)); 4488071fcb05SBarry Smith snes->conv_hist_alloc = PETSC_TRUE; 4489308dcc3eSBarry Smith } 4490c9005455SLois Curfman McInnes snes->conv_hist = a; 4491758f92a0SBarry Smith snes->conv_hist_its = its; 4492115dd874SBarry Smith snes->conv_hist_max = (size_t)na; 4493a12bc48fSLisandro Dalcin snes->conv_hist_len = 0; 4494758f92a0SBarry Smith snes->conv_hist_reset = reset; 44953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4496758f92a0SBarry Smith } 4497758f92a0SBarry Smith 4498d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB) 4499c6db04a5SJed Brown #include <engine.h> /* MATLAB include file */ 4500c6db04a5SJed Brown #include <mex.h> /* MATLAB include file */ 450199e0435eSBarry Smith 4502d71ae5a4SJacob Faibussowitsch PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes) 4503d71ae5a4SJacob Faibussowitsch { 4504308dcc3eSBarry Smith mxArray *mat; 4505308dcc3eSBarry Smith PetscInt i; 4506308dcc3eSBarry Smith PetscReal *ar; 4507308dcc3eSBarry Smith 4508308dcc3eSBarry Smith mat = mxCreateDoubleMatrix(snes->conv_hist_len, 1, mxREAL); 4509308dcc3eSBarry Smith ar = (PetscReal *)mxGetData(mat); 4510f5af7f23SKarl Rupp for (i = 0; i < snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i]; 451111cc89d2SBarry Smith return mat; 4512308dcc3eSBarry Smith } 4513308dcc3eSBarry Smith #endif 4514308dcc3eSBarry Smith 45150c4c9dddSBarry Smith /*@C 4516420bcc1bSBarry Smith SNESGetConvergenceHistory - Gets the arrays used to hold the convergence history. 4517758f92a0SBarry Smith 45183f9fe445SBarry Smith Not Collective 4519758f92a0SBarry Smith 4520758f92a0SBarry Smith Input Parameter: 4521f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 4522758f92a0SBarry Smith 4523758f92a0SBarry Smith Output Parameters: 4524f6dfbefdSBarry Smith + a - array to hold history, usually was set with `SNESSetConvergenceHistory()` 4525758f92a0SBarry Smith . its - integer array holds the number of linear iterations (or 4526758f92a0SBarry Smith negative if not converged) for each solve. 452720f4b53cSBarry Smith - na - size of `a` and `its` 4528758f92a0SBarry Smith 4529dc4c0fb0SBarry Smith Level: intermediate 4530dc4c0fb0SBarry Smith 453120f4b53cSBarry Smith Note: 453220f4b53cSBarry Smith This routine is useful, e.g., when running a code for purposes 453320f4b53cSBarry Smith of accurate performance monitoring, when no I/O should be done 453420f4b53cSBarry Smith during the section of code that is being timed. 453520f4b53cSBarry Smith 4536ce78bad3SBarry Smith Fortran Notes: 4537ce78bad3SBarry Smith Return the arrays with ``SNESRestoreConvergenceHistory()` 4538ce78bad3SBarry Smith 4539ce78bad3SBarry Smith Use the arguments 4540dc4c0fb0SBarry Smith .vb 4541ce78bad3SBarry Smith PetscReal, pointer :: a(:) 4542ce78bad3SBarry Smith PetscInt, pointer :: its(:) 4543dc4c0fb0SBarry Smith .ve 4544758f92a0SBarry Smith 45451cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceHistory()` 4546758f92a0SBarry Smith @*/ 4547d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergenceHistory(SNES snes, PetscReal *a[], PetscInt *its[], PetscInt *na) 4548d71ae5a4SJacob Faibussowitsch { 4549758f92a0SBarry Smith PetscFunctionBegin; 45500700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4551758f92a0SBarry Smith if (a) *a = snes->conv_hist; 4552758f92a0SBarry Smith if (its) *its = snes->conv_hist_its; 4553115dd874SBarry Smith if (na) *na = (PetscInt)snes->conv_hist_len; 45543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4555c9005455SLois Curfman McInnes } 4556c9005455SLois Curfman McInnes 4557ac226902SBarry Smith /*@C 455876b2cf59SMatthew Knepley SNESSetUpdate - Sets the general-purpose update function called 4559eec8f646SJed Brown at the beginning of every iteration of the nonlinear solve. Specifically 456053e5d35bSStefano Zampini it is called just before the Jacobian is "evaluated" and after the function 456153e5d35bSStefano Zampini evaluation. 456276b2cf59SMatthew Knepley 4563c3339decSBarry Smith Logically Collective 456476b2cf59SMatthew Knepley 456576b2cf59SMatthew Knepley Input Parameters: 4566a2b725a8SWilliam Gropp + snes - The nonlinear solver context 456753e5d35bSStefano Zampini - func - The update function; for calling sequence see `SNESUpdateFn` 456876b2cf59SMatthew Knepley 4569fe97e370SBarry Smith Level: advanced 4570fe97e370SBarry Smith 4571420bcc1bSBarry Smith Notes: 4572f6dfbefdSBarry 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 4573f6dfbefdSBarry Smith to `SNESSetFunction()`, or `SNESSetPicard()` 457453e5d35bSStefano Zampini This is not used by most users, and it is intended to provide a general hook that is run 457553e5d35bSStefano Zampini right before the direction step is computed. 4576ce78bad3SBarry Smith 457753e5d35bSStefano Zampini Users are free to modify the current residual vector, 457853e5d35bSStefano Zampini the current linearization point, or any other vector associated to the specific solver used. 457953e5d35bSStefano Zampini If such modifications take place, it is the user responsibility to update all the relevant 4580ce78bad3SBarry Smith vectors. For example, if one is adjusting the model parameters at each Newton step their code may look like 4581ce78bad3SBarry Smith .vb 4582ce78bad3SBarry Smith PetscErrorCode update(SNES snes, PetscInt iteration) 4583ce78bad3SBarry Smith { 4584ce78bad3SBarry Smith PetscFunctionBeginUser; 4585ce78bad3SBarry Smith if (iteration > 0) { 4586ce78bad3SBarry Smith // update the model parameters here 4587ce78bad3SBarry Smith Vec x,f; 4588ce78bad3SBarry Smith PetscCall(SNESGetSolution(snes,&x)); 4589ce78bad3SBarry Smith PetcCall(SNESGetFunction(snes,&f,NULL,NULL)); 4590ce78bad3SBarry Smith PetscCall(SNESComputeFunction(snes,x,f)); 4591ce78bad3SBarry Smith } 4592ce78bad3SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 4593ce78bad3SBarry Smith } 4594ce78bad3SBarry Smith .ve 459576b2cf59SMatthew Knepley 4596aaa8cc7dSPierre 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. 45976b7fb656SBarry Smith 4598e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetJacobian()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRSetPostCheck()`, 459953e5d35bSStefano Zampini `SNESMonitorSet()` 460076b2cf59SMatthew Knepley @*/ 460153e5d35bSStefano Zampini PetscErrorCode SNESSetUpdate(SNES snes, SNESUpdateFn *func) 4602d71ae5a4SJacob Faibussowitsch { 460376b2cf59SMatthew Knepley PetscFunctionBegin; 46040700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4605e7788613SBarry Smith snes->ops->update = func; 46063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 460776b2cf59SMatthew Knepley } 460876b2cf59SMatthew Knepley 4609ffeef943SBarry Smith /*@ 4610f6dfbefdSBarry Smith SNESConvergedReasonView - Displays the reason a `SNES` solve converged or diverged to a viewer 46112a359c20SBarry Smith 4612c3339decSBarry Smith Collective 46132a359c20SBarry Smith 4614e4094ef1SJacob Faibussowitsch Input Parameters: 4615f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 46162a359c20SBarry Smith - viewer - the viewer to display the reason 46172a359c20SBarry Smith 46182a359c20SBarry Smith Options Database Keys: 4619ee300463SSatish Balay + -snes_converged_reason - print reason for converged or diverged, also prints number of iterations 4620ee300463SSatish Balay - -snes_converged_reason ::failed - only print reason and number of iterations when diverged 4621eafd5ff0SAlex Lindsay 4622420bcc1bSBarry Smith Level: beginner 4623420bcc1bSBarry Smith 4624f6dfbefdSBarry Smith Note: 4625f6dfbefdSBarry Smith To change the format of the output call `PetscViewerPushFormat`(viewer,format) before this call. Use `PETSC_VIEWER_DEFAULT` for the default, 4626f6dfbefdSBarry Smith use `PETSC_VIEWER_FAILED` to only display a reason if it fails. 46272a359c20SBarry Smith 46281cc06b55SBarry Smith .seealso: [](ch_snes), `SNESConvergedReason`, `PetscViewer`, `SNES`, 4629f6dfbefdSBarry Smith `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, 4630f6dfbefdSBarry Smith `SNESConvergedReasonViewFromOptions()`, 4631db781477SPatrick Sanan `PetscViewerPushFormat()`, `PetscViewerPopFormat()` 46322a359c20SBarry Smith @*/ 4633d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonView(SNES snes, PetscViewer viewer) 4634d71ae5a4SJacob Faibussowitsch { 463575cca76cSMatthew G. Knepley PetscViewerFormat format; 46362a359c20SBarry Smith PetscBool isAscii; 46372a359c20SBarry Smith 46382a359c20SBarry Smith PetscFunctionBegin; 463919a666eeSBarry Smith if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)); 46409566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii)); 46412a359c20SBarry Smith if (isAscii) { 46429566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 464365bf60d2SBarry Smith PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel + 1)); 464475cca76cSMatthew G. Knepley if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 464575cca76cSMatthew G. Knepley DM dm; 464675cca76cSMatthew G. Knepley Vec u; 464775cca76cSMatthew G. Knepley PetscDS prob; 464875cca76cSMatthew G. Knepley PetscInt Nf, f; 464995cbbfd3SMatthew G. Knepley PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *); 465095cbbfd3SMatthew G. Knepley void **exactCtx; 465175cca76cSMatthew G. Knepley PetscReal error; 465275cca76cSMatthew G. Knepley 46539566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 46549566063dSJacob Faibussowitsch PetscCall(SNESGetSolution(snes, &u)); 46559566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob)); 46569566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(prob, &Nf)); 46579566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(Nf, &exactSol, Nf, &exactCtx)); 46589566063dSJacob Faibussowitsch for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f])); 46599566063dSJacob Faibussowitsch PetscCall(DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error)); 46609566063dSJacob Faibussowitsch PetscCall(PetscFree2(exactSol, exactCtx)); 46619566063dSJacob Faibussowitsch if (error < 1.0e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n")); 466263a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", (double)error)); 466375cca76cSMatthew G. Knepley } 4664eafd5ff0SAlex Lindsay if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) { 46652a359c20SBarry Smith if (((PetscObject)snes)->prefix) { 466663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter)); 46672a359c20SBarry Smith } else { 466863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve converged due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter)); 46692a359c20SBarry Smith } 4670eafd5ff0SAlex Lindsay } else if (snes->reason <= 0) { 46712a359c20SBarry Smith if (((PetscObject)snes)->prefix) { 467263a3b9bcSJacob 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)); 46732a359c20SBarry Smith } else { 467463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve did not converge due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter)); 46752a359c20SBarry Smith } 46762a359c20SBarry Smith } 467765bf60d2SBarry Smith PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel + 1)); 46782a359c20SBarry Smith } 46793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 46802a359c20SBarry Smith } 46812a359c20SBarry Smith 4682c4421ceaSFande Kong /*@C 4683c4421ceaSFande Kong SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the 4684aaa8cc7dSPierre Jolivet end of the nonlinear solver to display the convergence reason of the nonlinear solver. 4685c4421ceaSFande Kong 4686c3339decSBarry Smith Logically Collective 4687c4421ceaSFande Kong 4688c4421ceaSFande Kong Input Parameters: 4689f6dfbefdSBarry Smith + snes - the `SNES` context 4690420bcc1bSBarry Smith . f - the `SNESConvergedReason` view function 4691420bcc1bSBarry Smith . vctx - [optional] user-defined context for private data for the `SNESConvergedReason` view function (use `NULL` if no context is desired) 469249abdd8aSBarry Smith - reasonviewdestroy - [optional] routine that frees the context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence 4693420bcc1bSBarry Smith 4694420bcc1bSBarry Smith Calling sequence of `f`: 4695420bcc1bSBarry Smith + snes - the `SNES` context 469649abdd8aSBarry Smith - vctx - [optional] context for private data for the function 4697c4421ceaSFande Kong 4698c4421ceaSFande Kong Options Database Keys: 4699f6dfbefdSBarry Smith + -snes_converged_reason - sets a default `SNESConvergedReasonView()` 4700420bcc1bSBarry Smith - -snes_converged_reason_view_cancel - cancels all converged reason viewers that have been hardwired into a code by 4701420bcc1bSBarry Smith calls to `SNESConvergedReasonViewSet()`, but does not cancel those set via the options database. 4702c4421ceaSFande Kong 4703dc4c0fb0SBarry Smith Level: intermediate 4704dc4c0fb0SBarry Smith 4705f6dfbefdSBarry Smith Note: 4706c4421ceaSFande Kong Several different converged reason view routines may be set by calling 4707f6dfbefdSBarry Smith `SNESConvergedReasonViewSet()` multiple times; all will be called in the 4708c4421ceaSFande Kong order in which they were set. 4709c4421ceaSFande Kong 471049abdd8aSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`, `SNESConvergedReasonViewCancel()`, 471149abdd8aSBarry Smith `PetscCtxDestroyFn` 4712c4421ceaSFande Kong @*/ 471349abdd8aSBarry Smith PetscErrorCode SNESConvergedReasonViewSet(SNES snes, PetscErrorCode (*f)(SNES snes, void *vctx), void *vctx, PetscCtxDestroyFn *reasonviewdestroy) 4714d71ae5a4SJacob Faibussowitsch { 4715c4421ceaSFande Kong PetscInt i; 4716c4421ceaSFande Kong PetscBool identical; 4717c4421ceaSFande Kong 4718c4421ceaSFande Kong PetscFunctionBegin; 4719c4421ceaSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4720c4421ceaSFande Kong for (i = 0; i < snes->numberreasonviews; i++) { 47219566063dSJacob Faibussowitsch PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))f, vctx, reasonviewdestroy, (PetscErrorCode (*)(void))snes->reasonview[i], snes->reasonviewcontext[i], snes->reasonviewdestroy[i], &identical)); 47223ba16761SJacob Faibussowitsch if (identical) PetscFunctionReturn(PETSC_SUCCESS); 4723c4421ceaSFande Kong } 47245f80ce2aSJacob Faibussowitsch PetscCheck(snes->numberreasonviews < MAXSNESREASONVIEWS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many SNES reasonview set"); 4725c4421ceaSFande Kong snes->reasonview[snes->numberreasonviews] = f; 4726c4421ceaSFande Kong snes->reasonviewdestroy[snes->numberreasonviews] = reasonviewdestroy; 4727835f2295SStefano Zampini snes->reasonviewcontext[snes->numberreasonviews++] = vctx; 47283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4729c4421ceaSFande Kong } 4730c4421ceaSFande Kong 473191f3e32bSBarry Smith /*@ 4732420bcc1bSBarry Smith SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a `SNESConvergedReason` is to be viewed at the end of `SNESSolve()` 47330b4b7b1cSBarry Smith All the user-provided viewer routines set with `SNESConvergedReasonViewSet()` will be called, if they exist. 47342a359c20SBarry Smith 4735c3339decSBarry Smith Collective 47362a359c20SBarry Smith 47372fe279fdSBarry Smith Input Parameter: 4738f6dfbefdSBarry Smith . snes - the `SNES` object 47392a359c20SBarry Smith 4740f6dfbefdSBarry Smith Level: advanced 47412a359c20SBarry Smith 47421cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESConvergedReasonViewSet()`, `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, 4743f6dfbefdSBarry Smith `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()` 47442a359c20SBarry Smith @*/ 4745d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes) 4746d71ae5a4SJacob Faibussowitsch { 47472a359c20SBarry Smith static PetscBool incall = PETSC_FALSE; 47482a359c20SBarry Smith 47492a359c20SBarry Smith PetscFunctionBegin; 47503ba16761SJacob Faibussowitsch if (incall) PetscFunctionReturn(PETSC_SUCCESS); 47512a359c20SBarry Smith incall = PETSC_TRUE; 4752c4421ceaSFande Kong 4753c4421ceaSFande Kong /* All user-provided viewers are called first, if they exist. */ 475436d43d94SBarry Smith for (PetscInt i = 0; i < snes->numberreasonviews; i++) PetscCall((*snes->reasonview[i])(snes, snes->reasonviewcontext[i])); 4755c4421ceaSFande Kong 4756c4421ceaSFande Kong /* Call PETSc default routine if users ask for it */ 475736d43d94SBarry Smith if (snes->convergedreasonviewer) { 475836d43d94SBarry Smith PetscCall(PetscViewerPushFormat(snes->convergedreasonviewer, snes->convergedreasonformat)); 475936d43d94SBarry Smith PetscCall(SNESConvergedReasonView(snes, snes->convergedreasonviewer)); 476036d43d94SBarry Smith PetscCall(PetscViewerPopFormat(snes->convergedreasonviewer)); 47612a359c20SBarry Smith } 47622a359c20SBarry Smith incall = PETSC_FALSE; 47633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 47642a359c20SBarry Smith } 47652a359c20SBarry Smith 4766487a658cSBarry Smith /*@ 47670b4b7b1cSBarry Smith SNESSolve - Solves a nonlinear system $F(x) = b $ associated with a `SNES` object 47689b94acceSBarry Smith 4769c3339decSBarry Smith Collective 4770c7afd0dbSLois Curfman McInnes 4771b2002411SLois Curfman McInnes Input Parameters: 4772f6dfbefdSBarry Smith + snes - the `SNES` context 47730b4b7b1cSBarry Smith . b - the constant part of the equation $F(x) = b$, or `NULL` to use zero. 477485385478SLisandro Dalcin - x - the solution vector. 47759b94acceSBarry Smith 4776dc4c0fb0SBarry Smith Level: beginner 4777dc4c0fb0SBarry Smith 4778f6dfbefdSBarry Smith Note: 4779420bcc1bSBarry Smith The user should initialize the vector, `x`, with the initial guess 4780a9b45538SStefano Zampini for the nonlinear solve prior to calling `SNESSolve()` . 47818ddd3da0SLois Curfman McInnes 47821cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESSetFunction()`, `SNESSetJacobian()`, `SNESSetGridSequence()`, `SNESGetSolution()`, 4783db781477SPatrick Sanan `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRGetPreCheck()`, `SNESNewtonTRSetPostCheck()`, `SNESNewtonTRGetPostCheck()`, 4784a9b45538SStefano Zampini `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()` 47859b94acceSBarry Smith @*/ 4786d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSolve(SNES snes, Vec b, Vec x) 4787d71ae5a4SJacob Faibussowitsch { 4788ace3abfcSBarry Smith PetscBool flg; 4789efd51863SBarry Smith PetscInt grid; 47900298fd71SBarry Smith Vec xcreated = NULL; 4791caa4e7f2SJed Brown DM dm; 4792052efed2SBarry Smith 47933a40ed3dSBarry Smith PetscFunctionBegin; 47940700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4795a69afd8bSBarry Smith if (x) PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4796a69afd8bSBarry Smith if (x) PetscCheckSameComm(snes, 1, x, 3); 47970700a824SBarry Smith if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 479885385478SLisandro Dalcin if (b) PetscCheckSameComm(snes, 1, b, 2); 479985385478SLisandro Dalcin 480034b4d3a8SMatthew G. Knepley /* High level operations using the nonlinear solver */ 480106fc46c8SMatthew G. Knepley { 480206fc46c8SMatthew G. Knepley PetscViewer viewer; 480306fc46c8SMatthew G. Knepley PetscViewerFormat format; 48047c88af5aSMatthew G. Knepley PetscInt num; 480506fc46c8SMatthew G. Knepley PetscBool flg; 480606fc46c8SMatthew G. Knepley static PetscBool incall = PETSC_FALSE; 480706fc46c8SMatthew G. Knepley 480806fc46c8SMatthew G. Knepley if (!incall) { 480934b4d3a8SMatthew G. Knepley /* Estimate the convergence rate of the discretization */ 4810648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg)); 481106fc46c8SMatthew G. Knepley if (flg) { 481206fc46c8SMatthew G. Knepley PetscConvEst conv; 481346079b62SMatthew G. Knepley DM dm; 481446079b62SMatthew G. Knepley PetscReal *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */ 481546079b62SMatthew G. Knepley PetscInt Nf; 481606fc46c8SMatthew G. Knepley 481706fc46c8SMatthew G. Knepley incall = PETSC_TRUE; 48189566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 48199566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 48209566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(Nf, &alpha)); 48219566063dSJacob Faibussowitsch PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)snes), &conv)); 48229566063dSJacob Faibussowitsch PetscCall(PetscConvEstSetSolver(conv, (PetscObject)snes)); 48239566063dSJacob Faibussowitsch PetscCall(PetscConvEstSetFromOptions(conv)); 48249566063dSJacob Faibussowitsch PetscCall(PetscConvEstSetUp(conv)); 48259566063dSJacob Faibussowitsch PetscCall(PetscConvEstGetConvRate(conv, alpha)); 48269566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(viewer, format)); 48279566063dSJacob Faibussowitsch PetscCall(PetscConvEstRateView(conv, alpha, viewer)); 48289566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer)); 4829648c30bcSBarry Smith PetscCall(PetscViewerDestroy(&viewer)); 48309566063dSJacob Faibussowitsch PetscCall(PetscConvEstDestroy(&conv)); 48319566063dSJacob Faibussowitsch PetscCall(PetscFree(alpha)); 483206fc46c8SMatthew G. Knepley incall = PETSC_FALSE; 483306fc46c8SMatthew G. Knepley } 483434b4d3a8SMatthew G. Knepley /* Adaptively refine the initial grid */ 4835b2588ea6SMatthew G. Knepley num = 1; 48369566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_initial", &num, &flg)); 483734b4d3a8SMatthew G. Knepley if (flg) { 483834b4d3a8SMatthew G. Knepley DMAdaptor adaptor; 483934b4d3a8SMatthew G. Knepley 484034b4d3a8SMatthew G. Knepley incall = PETSC_TRUE; 48419566063dSJacob Faibussowitsch PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor)); 48429566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSolver(adaptor, snes)); 48439566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSequenceLength(adaptor, num)); 48449566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetFromOptions(adaptor)); 48459566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetUp(adaptor)); 48469566063dSJacob Faibussowitsch PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x)); 48479566063dSJacob Faibussowitsch PetscCall(DMAdaptorDestroy(&adaptor)); 484834b4d3a8SMatthew G. Knepley incall = PETSC_FALSE; 484934b4d3a8SMatthew G. Knepley } 48507c88af5aSMatthew G. Knepley /* Use grid sequencing to adapt */ 48517c88af5aSMatthew G. Knepley num = 0; 48529566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_sequence", &num, NULL)); 48537c88af5aSMatthew G. Knepley if (num) { 48547c88af5aSMatthew G. Knepley DMAdaptor adaptor; 4855e03fd340SMatthew G. Knepley const char *prefix; 48567c88af5aSMatthew G. Knepley 48577c88af5aSMatthew G. Knepley incall = PETSC_TRUE; 48589566063dSJacob Faibussowitsch PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor)); 4859e03fd340SMatthew G. Knepley PetscCall(SNESGetOptionsPrefix(snes, &prefix)); 4860e03fd340SMatthew G. Knepley PetscCall(DMAdaptorSetOptionsPrefix(adaptor, prefix)); 48619566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSolver(adaptor, snes)); 48629566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSequenceLength(adaptor, num)); 48639566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetFromOptions(adaptor)); 48649566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetUp(adaptor)); 4865e5148a0bSMatthew G. Knepley PetscCall(PetscObjectViewFromOptions((PetscObject)adaptor, NULL, "-snes_adapt_view")); 48669566063dSJacob Faibussowitsch PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x)); 48679566063dSJacob Faibussowitsch PetscCall(DMAdaptorDestroy(&adaptor)); 48687c88af5aSMatthew G. Knepley incall = PETSC_FALSE; 48697c88af5aSMatthew G. Knepley } 487006fc46c8SMatthew G. Knepley } 487106fc46c8SMatthew G. Knepley } 4872ad540459SPierre Jolivet if (!x) x = snes->vec_sol; 4873caa4e7f2SJed Brown if (!x) { 48749566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 48759566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dm, &xcreated)); 4876a69afd8bSBarry Smith x = xcreated; 4877a69afd8bSBarry Smith } 48789566063dSJacob Faibussowitsch PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view_pre")); 4879f05ece33SBarry Smith 48809566063dSJacob Faibussowitsch for (grid = 0; grid < snes->gridsequence; grid++) PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)))); 4881efd51863SBarry Smith for (grid = 0; grid < snes->gridsequence + 1; grid++) { 488285385478SLisandro Dalcin /* set solution vector */ 48839566063dSJacob Faibussowitsch if (!grid) PetscCall(PetscObjectReference((PetscObject)x)); 48849566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol)); 488585385478SLisandro Dalcin snes->vec_sol = x; 48869566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 4887caa4e7f2SJed Brown 4888caa4e7f2SJed Brown /* set affine vector if provided */ 48899566063dSJacob Faibussowitsch if (b) PetscCall(PetscObjectReference((PetscObject)b)); 48909566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_rhs)); 489185385478SLisandro Dalcin snes->vec_rhs = b; 489285385478SLisandro Dalcin 48935f80ce2aSJacob 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"); 48945f80ce2aSJacob Faibussowitsch PetscCheck(snes->vec_func != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be function vector"); 4895dd8e379bSPierre Jolivet PetscCheck(snes->vec_rhs != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be right-hand side vector"); 4896aa624791SPierre Jolivet if (!snes->vec_sol_update /* && snes->vec_sol */) PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_sol_update)); 48979566063dSJacob Faibussowitsch PetscCall(DMShellSetGlobalVector(dm, snes->vec_sol)); 48989566063dSJacob Faibussowitsch PetscCall(SNESSetUp(snes)); 48993f149594SLisandro Dalcin 49007eee914bSBarry Smith if (!grid) { 49019927e4dfSBarry Smith if (snes->ops->computeinitialguess) PetscCallBack("SNES callback compute initial guess", (*snes->ops->computeinitialguess)(snes, snes->vec_sol, snes->initialguessP)); 4902dd568438SSatish Balay } 4903d25893d9SBarry Smith 4904abc0a331SBarry Smith if (snes->conv_hist_reset) snes->conv_hist_len = 0; 490512b1dd1aSStefano Zampini PetscCall(SNESResetCounters(snes)); 49062d157150SStefano Zampini snes->reason = SNES_CONVERGED_ITERATING; 49079566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_Solve, snes, 0, 0, 0)); 4908dbbe0bcdSBarry Smith PetscUseTypeMethod(snes, solve); 49099566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_Solve, snes, 0, 0, 0)); 49102d157150SStefano Zampini PetscCheck(snes->reason, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error, solver %s returned without setting converged reason", ((PetscObject)snes)->type_name); 4911422a814eSBarry Smith snes->domainerror = PETSC_FALSE; /* clear the flag if it has been set */ 49123f149594SLisandro Dalcin 491337ec4e1aSPeter Brune if (snes->lagjac_persist) snes->jac_iter += snes->iter; 491437ec4e1aSPeter Brune if (snes->lagpre_persist) snes->pre_iter += snes->iter; 491537ec4e1aSPeter Brune 4916648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_test_local_min", NULL, NULL, &flg)); 49179566063dSJacob Faibussowitsch if (flg && !PetscPreLoadingOn) PetscCall(SNESTestLocalMin(snes)); 4918c4421ceaSFande Kong /* Call converged reason views. This may involve user-provided viewers as well */ 49199566063dSJacob Faibussowitsch PetscCall(SNESConvergedReasonViewFromOptions(snes)); 49205968eb51SBarry Smith 49215f80ce2aSJacob Faibussowitsch if (snes->errorifnotconverged) PetscCheck(snes->reason >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_NOT_CONVERGED, "SNESSolve has not converged"); 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