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 120*6b1535e8SBarry 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: 128*6b1535e8SBarry Smith This does not need to be called by all processes in the `SNES` MPI communicator. 129*6b1535e8SBarry 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 137*6b1535e8SBarry Smith You can call `SNESSetJacobianDomainError()` during a Jacobian computation to indicate the proposed solution is not in the domain. 138*6b1535e8SBarry Smith 139*6b1535e8SBarry Smith Developer Note: 140*6b1535e8SBarry Smith This value is used by `SNESCheckFunctionNorm()` to determine if the `SNESConvergedReason` is set to `SNES_DIVERGED_FUNCTION_DOMAIN` 141*6b1535e8SBarry Smith 1428434afd1SBarry Smith .seealso: [](ch_snes), `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetJacobianDomainError()`, `SNESVISetVariableBounds()`, 143*6b1535e8SBarry Smith `SNESVISetComputeVariableBounds()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, 144*6b1535e8SBarry 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 237*6b1535e8SBarry 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 247*6b1535e8SBarry Smith Notes: 248*6b1535e8SBarry Smith The value will only be true on those MPI processes that called `SNESSetFunctionDomainError()` 249*6b1535e8SBarry Smith 250*6b1535e8SBarry Smith The value is reset to `PETSC_FALSE` when `SNESCheckFunctionNorm()` is called. 251*6b1535e8SBarry 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 266*6b1535e8SBarry 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 276*6b1535e8SBarry Smith Notes: 277*6b1535e8SBarry Smith The value will only be true on those MPI processes that called `SNESSetJacobianDomainError()` 278*6b1535e8SBarry Smith 279*6b1535e8SBarry Smith The value is reset to `PETSC_FALSE` when `SNESCheckJacobianDomainerror()` is called but only `SNESSetCheckJacobianDomainError()` was called 280*6b1535e8SBarry 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; 40472a02f06SBarry Smith PetscBool iascii, 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 4169566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 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 42332077d6dSBarry Smith if (iascii) { 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 826ce78bad3SBarry Smith PETSC_EXTERN 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 1143c40d0f55SPeter Brune flg = PETSC_FALSE; 11449566063dSJacob Faibussowitsch PetscCall(SNESGetNPCSide(snes, &pcside)); 11459566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-snes_npc_side", "SNES nonlinear preconditioner side", "SNESSetNPCSide", PCSides, (PetscEnum)pcside, (PetscEnum *)&pcside, &flg)); 11469566063dSJacob Faibussowitsch if (flg) PetscCall(SNESSetNPCSide(snes, pcside)); 1147c40d0f55SPeter Brune 1148e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS) 11498a70d858SHong Zhang /* 11508a70d858SHong Zhang Publish convergence information using SAWs 11518a70d858SHong Zhang */ 11528a70d858SHong Zhang flg = PETSC_FALSE; 11539566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_monitor_saws", "Publish SNES progress using SAWs", "SNESMonitorSet", flg, &flg, NULL)); 11548a70d858SHong Zhang if (flg) { 11558a70d858SHong Zhang void *ctx; 11569566063dSJacob Faibussowitsch PetscCall(SNESMonitorSAWsCreate(snes, &ctx)); 11579566063dSJacob Faibussowitsch PetscCall(SNESMonitorSet(snes, SNESMonitorSAWs, ctx, SNESMonitorSAWsDestroy)); 11588a70d858SHong Zhang } 11598a70d858SHong Zhang #endif 11608a70d858SHong Zhang #if defined(PETSC_HAVE_SAWS) 1161b90c6cbeSBarry Smith { 1162b90c6cbeSBarry Smith PetscBool set; 1163b90c6cbeSBarry Smith flg = PETSC_FALSE; 11649566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_saws_block", "Block for SAWs at end of SNESSolve", "PetscObjectSAWsBlock", ((PetscObject)snes)->amspublishblock, &flg, &set)); 11651baa6e33SBarry Smith if (set) PetscCall(PetscObjectSAWsSetBlock((PetscObject)snes, flg)); 1166b90c6cbeSBarry Smith } 1167b90c6cbeSBarry Smith #endif 1168b90c6cbeSBarry Smith 116948a46eb9SPierre Jolivet for (i = 0; i < numberofsetfromoptions; i++) PetscCall((*othersetfromoptions[i])(snes)); 117076b2cf59SMatthew Knepley 1171dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, setfromoptions, PetscOptionsObject); 11725d973c19SBarry Smith 11735d973c19SBarry Smith /* process any options handlers added with PetscObjectAddOptionsHandler() */ 1174dbbe0bcdSBarry Smith PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)snes, PetscOptionsObject)); 1175d0609cedSBarry Smith PetscOptionsEnd(); 11764bbc92c1SBarry Smith 1177d8d34be6SBarry Smith if (snes->linesearch) { 11789566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 11799566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetFromOptions(snes->linesearch)); 1180d8d34be6SBarry Smith } 11819e764e56SPeter Brune 11826aa5e7e9SBarry Smith if (snes->usesksp) { 11839566063dSJacob Faibussowitsch if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 11849566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(snes->ksp, snes->jacobian, snes->jacobian_pre)); 11859566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(snes->ksp)); 11866aa5e7e9SBarry Smith } 11876991f827SBarry Smith 1188b5badacbSBarry Smith /* if user has set the SNES NPC type via options database, create it. */ 11899566063dSJacob Faibussowitsch PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 11909566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)snes)->options, optionsprefix, "-npc_snes_type", &pcset)); 119148a46eb9SPierre Jolivet if (pcset && (!snes->npc)) PetscCall(SNESGetNPC(snes, &snes->npc)); 11921baa6e33SBarry Smith if (snes->npc) PetscCall(SNESSetFromOptions(snes->npc)); 1193b3cd9a81SMatthew G. Knepley snes->setfromoptionscalled++; 11943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1195b3cd9a81SMatthew G. Knepley } 1196b3cd9a81SMatthew G. Knepley 1197b3cd9a81SMatthew G. Knepley /*@ 1198420bcc1bSBarry Smith SNESResetFromOptions - Sets various `SNES` and `KSP` parameters from user options ONLY if the `SNESSetFromOptions()` was previously called 1199b3cd9a81SMatthew G. Knepley 1200c3339decSBarry Smith Collective 1201b3cd9a81SMatthew G. Knepley 1202b3cd9a81SMatthew G. Knepley Input Parameter: 1203f6dfbefdSBarry Smith . snes - the `SNES` context 1204b3cd9a81SMatthew G. Knepley 1205420bcc1bSBarry Smith Level: advanced 1206b3cd9a81SMatthew G. Knepley 12071cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESSetOptionsPrefix()` 1208b3cd9a81SMatthew G. Knepley @*/ 1209d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESResetFromOptions(SNES snes) 1210d71ae5a4SJacob Faibussowitsch { 1211b3cd9a81SMatthew G. Knepley PetscFunctionBegin; 12129566063dSJacob Faibussowitsch if (snes->setfromoptionscalled) PetscCall(SNESSetFromOptions(snes)); 12133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12149b94acceSBarry Smith } 12159b94acceSBarry Smith 1216bb9467b5SJed Brown /*@C 1217d25893d9SBarry Smith SNESSetComputeApplicationContext - Sets an optional function to compute a user-defined context for 1218d25893d9SBarry Smith the nonlinear solvers. 1219d25893d9SBarry Smith 1220dc4c0fb0SBarry Smith Logically Collective; No Fortran Support 1221d25893d9SBarry Smith 1222d25893d9SBarry Smith Input Parameters: 1223f6dfbefdSBarry Smith + snes - the `SNES` context 1224d25893d9SBarry Smith . compute - function to compute the context 122549abdd8aSBarry Smith - destroy - function to destroy the context, see `PetscCtxDestroyFn` for the calling sequence 1226d25893d9SBarry Smith 1227420bcc1bSBarry Smith Calling sequence of `compute`: 1228420bcc1bSBarry Smith + snes - the `SNES` context 1229420bcc1bSBarry Smith - ctx - context to be computed 1230420bcc1bSBarry Smith 1231d25893d9SBarry Smith Level: intermediate 1232d25893d9SBarry Smith 1233f6dfbefdSBarry Smith Note: 1234f6dfbefdSBarry Smith This routine is useful if you are performing grid sequencing or using `SNESFAS` and need the appropriate context generated for each level. 1235f6dfbefdSBarry Smith 1236f6dfbefdSBarry Smith Use `SNESSetApplicationContext()` to see the context immediately 1237f6dfbefdSBarry Smith 123849abdd8aSBarry Smith .seealso: [](ch_snes), `SNESGetApplicationContext()`, `SNESSetApplicationContext()`, `PetscCtxDestroyFn` 1239d25893d9SBarry Smith @*/ 124049abdd8aSBarry Smith PetscErrorCode SNESSetComputeApplicationContext(SNES snes, PetscErrorCode (*compute)(SNES snes, void **ctx), PetscCtxDestroyFn *destroy) 1241d71ae5a4SJacob Faibussowitsch { 1242d25893d9SBarry Smith PetscFunctionBegin; 1243d25893d9SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1244d25893d9SBarry Smith snes->ops->usercompute = compute; 124549abdd8aSBarry Smith snes->ops->ctxdestroy = destroy; 12463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1247d25893d9SBarry Smith } 1248a847f771SSatish Balay 1249b07ff414SBarry Smith /*@ 1250f6dfbefdSBarry Smith SNESSetApplicationContext - Sets the optional user-defined context for the nonlinear solvers. 12519b94acceSBarry Smith 1252c3339decSBarry Smith Logically Collective 1253fee21e36SBarry Smith 1254c7afd0dbSLois Curfman McInnes Input Parameters: 1255f6dfbefdSBarry Smith + snes - the `SNES` context 1256ce78bad3SBarry Smith - ctx - the user context 1257c7afd0dbSLois Curfman McInnes 125836851e7fSLois Curfman McInnes Level: intermediate 125936851e7fSLois Curfman McInnes 1260f6dfbefdSBarry Smith Notes: 1261ce78bad3SBarry Smith Users can provide a context when constructing the `SNES` options and then access it inside their function, Jacobian computation, or other evaluation function 1262f6dfbefdSBarry Smith with `SNESGetApplicationContext()` 1263f6dfbefdSBarry Smith 1264f6dfbefdSBarry Smith To provide a function that computes the context for you use `SNESSetComputeApplicationContext()` 1265f6dfbefdSBarry Smith 1266420bcc1bSBarry Smith Fortran Note: 1267ce78bad3SBarry 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 1268ce78bad3SBarry Smith function that tells the Fortran compiler the derived data type that is passed in as the `ctx` argument. See `SNESGetApplicationContext()` for 1269ce78bad3SBarry Smith an example. 1270daf670e6SBarry Smith 12711cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetComputeApplicationContext()`, `SNESGetApplicationContext()` 12729b94acceSBarry Smith @*/ 127349abdd8aSBarry Smith PetscErrorCode SNESSetApplicationContext(SNES snes, void *ctx) 1274d71ae5a4SJacob Faibussowitsch { 1275b07ff414SBarry Smith KSP ksp; 12761b2093e4SBarry Smith 12773a40ed3dSBarry Smith PetscFunctionBegin; 12780700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 12799566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 128049abdd8aSBarry Smith PetscCall(KSPSetApplicationContext(ksp, ctx)); 128149abdd8aSBarry Smith snes->ctx = ctx; 12823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12839b94acceSBarry Smith } 128474679c65SBarry Smith 1285b07ff414SBarry Smith /*@ 12869b94acceSBarry Smith SNESGetApplicationContext - Gets the user-defined context for the 1287420bcc1bSBarry Smith nonlinear solvers set with `SNESGetApplicationContext()` or `SNESSetComputeApplicationContext()` 12889b94acceSBarry Smith 1289c7afd0dbSLois Curfman McInnes Not Collective 1290c7afd0dbSLois Curfman McInnes 12919b94acceSBarry Smith Input Parameter: 1292f6dfbefdSBarry Smith . snes - `SNES` context 12939b94acceSBarry Smith 12949b94acceSBarry Smith Output Parameter: 129549abdd8aSBarry Smith . ctx - user context 12969b94acceSBarry Smith 129736851e7fSLois Curfman McInnes Level: intermediate 129836851e7fSLois Curfman McInnes 1299ce78bad3SBarry Smith Fortran Notes: 1300ce78bad3SBarry 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 1301ce78bad3SBarry Smith function that tells the Fortran compiler the derived data type that is returned as the `ctx` argument. For example, 1302ce78bad3SBarry Smith .vb 1303ce78bad3SBarry Smith Interface SNESGetApplicationContext 1304ce78bad3SBarry Smith Subroutine SNESGetApplicationContext(snes,ctx,ierr) 1305ce78bad3SBarry Smith #include <petsc/finclude/petscsnes.h> 1306ce78bad3SBarry Smith use petscsnes 1307ce78bad3SBarry Smith SNES snes 1308ce78bad3SBarry Smith type(tUsertype), pointer :: ctx 1309ce78bad3SBarry Smith PetscErrorCode ierr 1310ce78bad3SBarry Smith End Subroutine 1311ce78bad3SBarry Smith End Interface SNESGetApplicationContext 1312ce78bad3SBarry Smith .ve 1313ce78bad3SBarry Smith 1314bfe80ac4SPierre Jolivet The prototype for `ctx` must be 1315ce78bad3SBarry Smith .vb 1316ce78bad3SBarry Smith type(tUsertype), pointer :: ctx 1317ce78bad3SBarry Smith .ve 1318dc4c0fb0SBarry Smith 1319420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESSetApplicationContext()`, `SNESSetComputeApplicationContext()` 13209b94acceSBarry Smith @*/ 1321ce78bad3SBarry Smith PetscErrorCode SNESGetApplicationContext(SNES snes, PeCtx ctx) 1322d71ae5a4SJacob Faibussowitsch { 13233a40ed3dSBarry Smith PetscFunctionBegin; 13240700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 132549abdd8aSBarry Smith *(void **)ctx = snes->ctx; 13263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13279b94acceSBarry Smith } 132874679c65SBarry Smith 13299b94acceSBarry Smith /*@ 1330420bcc1bSBarry Smith SNESSetUseMatrixFree - indicates that `SNES` should use matrix-free finite difference matrix-vector products to apply the Jacobian. 13313565c898SBarry Smith 1332dc4c0fb0SBarry Smith Logically Collective 13333565c898SBarry Smith 13343565c898SBarry Smith Input Parameters: 1335f6dfbefdSBarry Smith + snes - `SNES` context 1336f6dfbefdSBarry Smith . mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used 1337f6dfbefdSBarry 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 1338420bcc1bSBarry Smith this option no matrix-element based preconditioners can be used in the linear solve since the matrix won't be explicitly available 13393565c898SBarry Smith 1340f6dfbefdSBarry Smith Options Database Keys: 134101c1178eSBarry Smith + -snes_mf_operator - use matrix-free only for the mat operator 1342f6dfbefdSBarry Smith . -snes_mf - use matrix-free for both the mat and pmat operator 1343ec5066bdSBarry Smith . -snes_fd_color - compute the Jacobian via coloring and finite differences. 1344ec5066bdSBarry Smith - -snes_fd - compute the Jacobian via finite differences (slow) 13453565c898SBarry Smith 13463565c898SBarry Smith Level: intermediate 13473565c898SBarry Smith 1348f6dfbefdSBarry Smith Note: 1349420bcc1bSBarry Smith `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`, 1350420bcc1bSBarry Smith and computing explicitly with 1351f6dfbefdSBarry Smith finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object. 1352ec5066bdSBarry Smith 1353420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetUseMatrixFree()`, `MatCreateSNESMF()`, `SNESComputeJacobianDefaultColor()`, `MatFDColoring` 13543565c898SBarry Smith @*/ 1355d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUseMatrixFree(SNES snes, PetscBool mf_operator, PetscBool mf) 1356d71ae5a4SJacob Faibussowitsch { 13573565c898SBarry Smith PetscFunctionBegin; 13583565c898SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 135988b4c220SStefano Zampini PetscValidLogicalCollectiveBool(snes, mf_operator, 2); 136088b4c220SStefano Zampini PetscValidLogicalCollectiveBool(snes, mf, 3); 13614ddffce6SLisandro Dalcin snes->mf = mf_operator ? PETSC_TRUE : mf; 13623565c898SBarry Smith snes->mf_operator = mf_operator; 13633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13643565c898SBarry Smith } 13653565c898SBarry Smith 13663565c898SBarry Smith /*@ 1367dc4c0fb0SBarry Smith SNESGetUseMatrixFree - indicates if the `SNES` uses matrix-free finite difference matrix vector products to apply the Jacobian. 13683565c898SBarry Smith 1369420bcc1bSBarry Smith Not Collective, but the resulting flags will be the same on all MPI processes 13703565c898SBarry Smith 13713565c898SBarry Smith Input Parameter: 1372f6dfbefdSBarry Smith . snes - `SNES` context 13733565c898SBarry Smith 13743565c898SBarry Smith Output Parameters: 1375f6dfbefdSBarry Smith + mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used 1376f6dfbefdSBarry 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 13773565c898SBarry Smith 13783565c898SBarry Smith Level: intermediate 13793565c898SBarry Smith 13801cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUseMatrixFree()`, `MatCreateSNESMF()` 13813565c898SBarry Smith @*/ 1382d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUseMatrixFree(SNES snes, PetscBool *mf_operator, PetscBool *mf) 1383d71ae5a4SJacob Faibussowitsch { 13843565c898SBarry Smith PetscFunctionBegin; 13853565c898SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 13863565c898SBarry Smith if (mf) *mf = snes->mf; 13873565c898SBarry Smith if (mf_operator) *mf_operator = snes->mf_operator; 13883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13893565c898SBarry Smith } 13903565c898SBarry Smith 13913565c898SBarry Smith /*@ 1392420bcc1bSBarry Smith SNESGetIterationNumber - Gets the number of nonlinear iterations completed in the current or most recent `SNESSolve()` 13939b94acceSBarry Smith 1394c7afd0dbSLois Curfman McInnes Not Collective 1395c7afd0dbSLois Curfman McInnes 13969b94acceSBarry Smith Input Parameter: 1397f6dfbefdSBarry Smith . snes - `SNES` context 13989b94acceSBarry Smith 13999b94acceSBarry Smith Output Parameter: 14009b94acceSBarry Smith . iter - iteration number 14019b94acceSBarry Smith 1402dc4c0fb0SBarry Smith Level: intermediate 1403dc4c0fb0SBarry Smith 1404c8228a4eSBarry Smith Notes: 1405c8228a4eSBarry Smith For example, during the computation of iteration 2 this would return 1. 1406c8228a4eSBarry Smith 1407c8228a4eSBarry Smith This is useful for using lagged Jacobians (where one does not recompute the 1408f6dfbefdSBarry Smith Jacobian at each `SNES` iteration). For example, the code 140908405cd6SLois Curfman McInnes .vb 141008405cd6SLois Curfman McInnes ierr = SNESGetIterationNumber(snes,&it); 141108405cd6SLois Curfman McInnes if (!(it % 2)) { 141208405cd6SLois Curfman McInnes [compute Jacobian here] 141308405cd6SLois Curfman McInnes } 141408405cd6SLois Curfman McInnes .ve 1415f6dfbefdSBarry Smith can be used in your function that computes the Jacobian to cause the Jacobian to be 1416f6dfbefdSBarry Smith recomputed every second `SNES` iteration. See also `SNESSetLagJacobian()` 1417c8228a4eSBarry Smith 1418f6dfbefdSBarry Smith After the `SNES` solve is complete this will return the number of nonlinear iterations used. 1419c04deec6SBarry Smith 1420420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetLagJacobian()`, `SNESGetLinearSolveIterations()`, `SNESSetMonitor()` 14219b94acceSBarry Smith @*/ 1422d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetIterationNumber(SNES snes, PetscInt *iter) 1423d71ae5a4SJacob Faibussowitsch { 14243a40ed3dSBarry Smith PetscFunctionBegin; 14250700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 14264f572ea9SToby Isaac PetscAssertPointer(iter, 2); 14279b94acceSBarry Smith *iter = snes->iter; 14283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14299b94acceSBarry Smith } 143074679c65SBarry Smith 1431360c497dSPeter Brune /*@ 1432360c497dSPeter Brune SNESSetIterationNumber - Sets the current iteration number. 1433360c497dSPeter Brune 1434360c497dSPeter Brune Not Collective 1435360c497dSPeter Brune 1436d8d19677SJose E. Roman Input Parameters: 1437f6dfbefdSBarry Smith + snes - `SNES` context 1438a2b725a8SWilliam Gropp - iter - iteration number 1439360c497dSPeter Brune 1440360c497dSPeter Brune Level: developer 1441360c497dSPeter Brune 1442420bcc1bSBarry Smith Note: 1443420bcc1bSBarry Smith This should only be called inside a `SNES` nonlinear solver. 1444420bcc1bSBarry Smith 14451cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetLinearSolveIterations()` 1446360c497dSPeter Brune @*/ 1447d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetIterationNumber(SNES snes, PetscInt iter) 1448d71ae5a4SJacob Faibussowitsch { 1449360c497dSPeter Brune PetscFunctionBegin; 1450360c497dSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 14519566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes)); 1452360c497dSPeter Brune snes->iter = iter; 14539566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes)); 14543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1455360c497dSPeter Brune } 1456360c497dSPeter Brune 14579b94acceSBarry Smith /*@ 1458b850b91aSLisandro Dalcin SNESGetNonlinearStepFailures - Gets the number of unsuccessful steps 1459420bcc1bSBarry Smith attempted by the nonlinear solver in the current or most recent `SNESSolve()` . 14609b94acceSBarry Smith 1461c7afd0dbSLois Curfman McInnes Not Collective 1462c7afd0dbSLois Curfman McInnes 14639b94acceSBarry Smith Input Parameter: 1464f6dfbefdSBarry Smith . snes - `SNES` context 14659b94acceSBarry Smith 14669b94acceSBarry Smith Output Parameter: 14679b94acceSBarry Smith . nfails - number of unsuccessful steps attempted 14689b94acceSBarry Smith 1469dc4c0fb0SBarry Smith Level: intermediate 1470dc4c0fb0SBarry Smith 1471f6dfbefdSBarry Smith Note: 1472f6dfbefdSBarry Smith This counter is reset to zero for each successive call to `SNESSolve()`. 1473c96a6f78SLois Curfman McInnes 14741cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, 1475db781477SPatrick Sanan `SNESSetMaxNonlinearStepFailures()`, `SNESGetMaxNonlinearStepFailures()` 14769b94acceSBarry Smith @*/ 1477d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNonlinearStepFailures(SNES snes, PetscInt *nfails) 1478d71ae5a4SJacob Faibussowitsch { 14793a40ed3dSBarry Smith PetscFunctionBegin; 14800700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 14814f572ea9SToby Isaac PetscAssertPointer(nfails, 2); 148250ffb88aSMatthew Knepley *nfails = snes->numFailures; 14833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 148450ffb88aSMatthew Knepley } 148550ffb88aSMatthew Knepley 148650ffb88aSMatthew Knepley /*@ 1487b850b91aSLisandro Dalcin SNESSetMaxNonlinearStepFailures - Sets the maximum number of unsuccessful steps 1488420bcc1bSBarry Smith attempted by the nonlinear solver before it gives up and returns unconverged or generates an error 148950ffb88aSMatthew Knepley 149050ffb88aSMatthew Knepley Not Collective 149150ffb88aSMatthew Knepley 149250ffb88aSMatthew Knepley Input Parameters: 1493f6dfbefdSBarry Smith + snes - `SNES` context 149477e5a1f9SBarry Smith - maxFails - maximum of unsuccessful steps allowed, use `PETSC_UNLIMITED` to have no limit on the number of failures 149550ffb88aSMatthew Knepley 1496420bcc1bSBarry Smith Options Database Key: 1497420bcc1bSBarry Smith . -snes_max_fail <n> - maximum number of unsuccessful steps allowed 1498420bcc1bSBarry Smith 149950ffb88aSMatthew Knepley Level: intermediate 150050ffb88aSMatthew Knepley 1501420bcc1bSBarry Smith Developer Note: 1502420bcc1bSBarry Smith The options database key is wrong for this function name 1503420bcc1bSBarry Smith 15041cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, 1505db781477SPatrick Sanan `SNESGetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()` 150650ffb88aSMatthew Knepley @*/ 1507d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxNonlinearStepFailures(SNES snes, PetscInt maxFails) 1508d71ae5a4SJacob Faibussowitsch { 150950ffb88aSMatthew Knepley PetscFunctionBegin; 15100700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 151177e5a1f9SBarry Smith 151277e5a1f9SBarry Smith if (maxFails == PETSC_UNLIMITED) { 15131690c2aeSBarry Smith snes->maxFailures = PETSC_INT_MAX; 151477e5a1f9SBarry Smith } else { 151577e5a1f9SBarry Smith PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures"); 151650ffb88aSMatthew Knepley snes->maxFailures = maxFails; 151777e5a1f9SBarry Smith } 15183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 151950ffb88aSMatthew Knepley } 152050ffb88aSMatthew Knepley 152150ffb88aSMatthew Knepley /*@ 1522b850b91aSLisandro Dalcin SNESGetMaxNonlinearStepFailures - Gets the maximum number of unsuccessful steps 1523420bcc1bSBarry Smith attempted by the nonlinear solver before it gives up and returns unconverged or generates an error 152450ffb88aSMatthew Knepley 152550ffb88aSMatthew Knepley Not Collective 152650ffb88aSMatthew Knepley 152750ffb88aSMatthew Knepley Input Parameter: 152820f4b53cSBarry Smith . snes - `SNES` context 152950ffb88aSMatthew Knepley 153050ffb88aSMatthew Knepley Output Parameter: 153150ffb88aSMatthew Knepley . maxFails - maximum of unsuccessful steps 153250ffb88aSMatthew Knepley 153350ffb88aSMatthew Knepley Level: intermediate 153450ffb88aSMatthew Knepley 15351cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, 1536db781477SPatrick Sanan `SNESSetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()` 153750ffb88aSMatthew Knepley @*/ 1538d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxNonlinearStepFailures(SNES snes, PetscInt *maxFails) 1539d71ae5a4SJacob Faibussowitsch { 154050ffb88aSMatthew Knepley PetscFunctionBegin; 15410700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 15424f572ea9SToby Isaac PetscAssertPointer(maxFails, 2); 154350ffb88aSMatthew Knepley *maxFails = snes->maxFailures; 15443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15459b94acceSBarry Smith } 1546a847f771SSatish Balay 15472541af92SBarry Smith /*@ 15482541af92SBarry Smith SNESGetNumberFunctionEvals - Gets the number of user provided function evaluations 1549420bcc1bSBarry Smith done by the `SNES` object in the current or most recent `SNESSolve()` 15502541af92SBarry Smith 15512541af92SBarry Smith Not Collective 15522541af92SBarry Smith 15532541af92SBarry Smith Input Parameter: 1554f6dfbefdSBarry Smith . snes - `SNES` context 15552541af92SBarry Smith 15562541af92SBarry Smith Output Parameter: 15572541af92SBarry Smith . nfuncs - number of evaluations 15582541af92SBarry Smith 15592541af92SBarry Smith Level: intermediate 15602541af92SBarry Smith 1561f6dfbefdSBarry Smith Note: 1562f6dfbefdSBarry Smith Reset every time `SNESSolve()` is called unless `SNESSetCountersReset()` is used. 1563971e163fSPeter Brune 15641cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, `SNESSetCountersReset()` 15652541af92SBarry Smith @*/ 1566d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNumberFunctionEvals(SNES snes, PetscInt *nfuncs) 1567d71ae5a4SJacob Faibussowitsch { 15682541af92SBarry Smith PetscFunctionBegin; 15690700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 15704f572ea9SToby Isaac PetscAssertPointer(nfuncs, 2); 15712541af92SBarry Smith *nfuncs = snes->nfuncs; 15723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15732541af92SBarry Smith } 15742541af92SBarry Smith 15753d4c4710SBarry Smith /*@ 15763d4c4710SBarry Smith SNESGetLinearSolveFailures - Gets the number of failed (non-converged) 1577420bcc1bSBarry Smith linear solvers in the current or most recent `SNESSolve()` 15783d4c4710SBarry Smith 15793d4c4710SBarry Smith Not Collective 15803d4c4710SBarry Smith 15813d4c4710SBarry Smith Input Parameter: 1582f6dfbefdSBarry Smith . snes - `SNES` context 15833d4c4710SBarry Smith 15843d4c4710SBarry Smith Output Parameter: 15853d4c4710SBarry Smith . nfails - number of failed solves 15863d4c4710SBarry Smith 1587f6dfbefdSBarry Smith Options Database Key: 15889d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated 15899d85da0cSMatthew G. Knepley 1590f6dfbefdSBarry Smith Level: intermediate 1591f6dfbefdSBarry Smith 1592f6dfbefdSBarry Smith Note: 1593f6dfbefdSBarry Smith This counter is reset to zero for each successive call to `SNESSolve()`. 15943d4c4710SBarry Smith 15951cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()` 15963d4c4710SBarry Smith @*/ 1597d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveFailures(SNES snes, PetscInt *nfails) 1598d71ae5a4SJacob Faibussowitsch { 15993d4c4710SBarry Smith PetscFunctionBegin; 16000700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 16014f572ea9SToby Isaac PetscAssertPointer(nfails, 2); 16023d4c4710SBarry Smith *nfails = snes->numLinearSolveFailures; 16033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16043d4c4710SBarry Smith } 16053d4c4710SBarry Smith 16063d4c4710SBarry Smith /*@ 16073d4c4710SBarry Smith SNESSetMaxLinearSolveFailures - the number of failed linear solve attempts 1608f6dfbefdSBarry Smith allowed before `SNES` returns with a diverged reason of `SNES_DIVERGED_LINEAR_SOLVE` 16093d4c4710SBarry Smith 1610c3339decSBarry Smith Logically Collective 16113d4c4710SBarry Smith 16123d4c4710SBarry Smith Input Parameters: 1613f6dfbefdSBarry Smith + snes - `SNES` context 161477e5a1f9SBarry Smith - maxFails - maximum allowed linear solve failures, use `PETSC_UNLIMITED` to have no limit on the number of failures 16153d4c4710SBarry Smith 1616f6dfbefdSBarry Smith Options Database Key: 16179d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated 16189d85da0cSMatthew G. Knepley 1619dc4c0fb0SBarry Smith Level: intermediate 1620dc4c0fb0SBarry Smith 1621f6dfbefdSBarry Smith Note: 1622f6dfbefdSBarry Smith By default this is 0; that is `SNES` returns on the first failed linear solve 16233d4c4710SBarry Smith 1624420bcc1bSBarry Smith Developer Note: 1625420bcc1bSBarry Smith The options database key is wrong for this function name 1626420bcc1bSBarry Smith 16271cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()` 16283d4c4710SBarry Smith @*/ 1629d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxLinearSolveFailures(SNES snes, PetscInt maxFails) 1630d71ae5a4SJacob Faibussowitsch { 16313d4c4710SBarry Smith PetscFunctionBegin; 16320700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1633c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, maxFails, 2); 163477e5a1f9SBarry Smith 163577e5a1f9SBarry Smith if (maxFails == PETSC_UNLIMITED) { 16361690c2aeSBarry Smith snes->maxLinearSolveFailures = PETSC_INT_MAX; 163777e5a1f9SBarry Smith } else { 163877e5a1f9SBarry Smith PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures"); 16393d4c4710SBarry Smith snes->maxLinearSolveFailures = maxFails; 164077e5a1f9SBarry Smith } 16413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16423d4c4710SBarry Smith } 16433d4c4710SBarry Smith 16443d4c4710SBarry Smith /*@ 16453d4c4710SBarry Smith SNESGetMaxLinearSolveFailures - gets the maximum number of linear solve failures that 1646f6dfbefdSBarry Smith are allowed before `SNES` returns as unsuccessful 16473d4c4710SBarry Smith 16483d4c4710SBarry Smith Not Collective 16493d4c4710SBarry Smith 16503d4c4710SBarry Smith Input Parameter: 1651f6dfbefdSBarry Smith . snes - `SNES` context 16523d4c4710SBarry Smith 16533d4c4710SBarry Smith Output Parameter: 16543d4c4710SBarry Smith . maxFails - maximum of unsuccessful solves allowed 16553d4c4710SBarry Smith 16563d4c4710SBarry Smith Level: intermediate 16573d4c4710SBarry Smith 1658f6dfbefdSBarry Smith Note: 1659f6dfbefdSBarry Smith By default this is 1; that is `SNES` returns on the first failed linear solve 16603d4c4710SBarry Smith 16611cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, 16623d4c4710SBarry Smith @*/ 1663d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxLinearSolveFailures(SNES snes, PetscInt *maxFails) 1664d71ae5a4SJacob Faibussowitsch { 16653d4c4710SBarry Smith PetscFunctionBegin; 16660700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 16674f572ea9SToby Isaac PetscAssertPointer(maxFails, 2); 16683d4c4710SBarry Smith *maxFails = snes->maxLinearSolveFailures; 16693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16703d4c4710SBarry Smith } 16713d4c4710SBarry Smith 1672c96a6f78SLois Curfman McInnes /*@ 1673b850b91aSLisandro Dalcin SNESGetLinearSolveIterations - Gets the total number of linear iterations 1674420bcc1bSBarry Smith used by the nonlinear solver in the most recent `SNESSolve()` 1675c96a6f78SLois Curfman McInnes 1676c7afd0dbSLois Curfman McInnes Not Collective 1677c7afd0dbSLois Curfman McInnes 1678c96a6f78SLois Curfman McInnes Input Parameter: 1679f6dfbefdSBarry Smith . snes - `SNES` context 1680c96a6f78SLois Curfman McInnes 1681c96a6f78SLois Curfman McInnes Output Parameter: 1682c96a6f78SLois Curfman McInnes . lits - number of linear iterations 1683c96a6f78SLois Curfman McInnes 1684dc4c0fb0SBarry Smith Level: intermediate 1685dc4c0fb0SBarry Smith 1686c96a6f78SLois Curfman McInnes Notes: 1687f6dfbefdSBarry Smith This counter is reset to zero for each successive call to `SNESSolve()` unless `SNESSetCountersReset()` is used. 1688c96a6f78SLois Curfman McInnes 1689f6dfbefdSBarry 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 1690f6dfbefdSBarry Smith then call `KSPGetIterationNumber()` after the failed solve. 1691010be392SBarry Smith 16921cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetIterationNumber()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESSetCountersReset()` 1693c96a6f78SLois Curfman McInnes @*/ 1694d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveIterations(SNES snes, PetscInt *lits) 1695d71ae5a4SJacob Faibussowitsch { 16963a40ed3dSBarry Smith PetscFunctionBegin; 16970700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 16984f572ea9SToby Isaac PetscAssertPointer(lits, 2); 1699c96a6f78SLois Curfman McInnes *lits = snes->linear_its; 17003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1701c96a6f78SLois Curfman McInnes } 1702c96a6f78SLois Curfman McInnes 1703971e163fSPeter Brune /*@ 1704971e163fSPeter Brune SNESSetCountersReset - Sets whether or not the counters for linear iterations and function evaluations 1705f6dfbefdSBarry Smith are reset every time `SNESSolve()` is called. 1706971e163fSPeter Brune 1707c3339decSBarry Smith Logically Collective 1708971e163fSPeter Brune 1709d8d19677SJose E. Roman Input Parameters: 1710f6dfbefdSBarry Smith + snes - `SNES` context 1711f6dfbefdSBarry Smith - reset - whether to reset the counters or not, defaults to `PETSC_TRUE` 1712971e163fSPeter Brune 1713971e163fSPeter Brune Level: developer 1714971e163fSPeter Brune 17151cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()` 1716971e163fSPeter Brune @*/ 1717d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCountersReset(SNES snes, PetscBool reset) 1718d71ae5a4SJacob Faibussowitsch { 1719971e163fSPeter Brune PetscFunctionBegin; 1720971e163fSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1721971e163fSPeter Brune PetscValidLogicalCollectiveBool(snes, reset, 2); 1722971e163fSPeter Brune snes->counters_reset = reset; 17233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1724971e163fSPeter Brune } 1725971e163fSPeter Brune 17262999313aSBarry Smith /*@ 172712b1dd1aSStefano Zampini SNESResetCounters - Reset counters for linear iterations and function evaluations. 172812b1dd1aSStefano Zampini 172912b1dd1aSStefano Zampini Logically Collective 173012b1dd1aSStefano Zampini 173112b1dd1aSStefano Zampini Input Parameters: 173212b1dd1aSStefano Zampini . snes - `SNES` context 173312b1dd1aSStefano Zampini 173412b1dd1aSStefano Zampini Level: developer 173512b1dd1aSStefano Zampini 173612b1dd1aSStefano Zampini Note: 173712b1dd1aSStefano Zampini It honors the flag set with `SNESSetCountersReset()` 173812b1dd1aSStefano Zampini 173912b1dd1aSStefano Zampini .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()` 174012b1dd1aSStefano Zampini @*/ 174112b1dd1aSStefano Zampini PetscErrorCode SNESResetCounters(SNES snes) 174212b1dd1aSStefano Zampini { 174312b1dd1aSStefano Zampini PetscFunctionBegin; 174412b1dd1aSStefano Zampini PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 174512b1dd1aSStefano Zampini if (snes->counters_reset) { 174612b1dd1aSStefano Zampini snes->nfuncs = 0; 174712b1dd1aSStefano Zampini snes->linear_its = 0; 174812b1dd1aSStefano Zampini snes->numFailures = 0; 174912b1dd1aSStefano Zampini } 175012b1dd1aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 175112b1dd1aSStefano Zampini } 175212b1dd1aSStefano Zampini 175312b1dd1aSStefano Zampini /*@ 1754f6dfbefdSBarry Smith SNESSetKSP - Sets a `KSP` context for the `SNES` object to use 17552999313aSBarry Smith 1756420bcc1bSBarry Smith Not Collective, but the `SNES` and `KSP` objects must live on the same `MPI_Comm` 17572999313aSBarry Smith 17582999313aSBarry Smith Input Parameters: 1759f6dfbefdSBarry Smith + snes - the `SNES` context 1760f6dfbefdSBarry Smith - ksp - the `KSP` context 17612999313aSBarry Smith 1762dc4c0fb0SBarry Smith Level: developer 1763dc4c0fb0SBarry Smith 17642999313aSBarry Smith Notes: 1765f6dfbefdSBarry Smith The `SNES` object already has its `KSP` object, you can obtain with `SNESGetKSP()` 17662999313aSBarry Smith so this routine is rarely needed. 17672999313aSBarry Smith 1768f6dfbefdSBarry Smith The `KSP` object that is already in the `SNES` object has its reference count 1769420bcc1bSBarry Smith decreased by one when this is called. 17702999313aSBarry Smith 177142747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `KSP`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()` 17722999313aSBarry Smith @*/ 1773d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetKSP(SNES snes, KSP ksp) 1774d71ae5a4SJacob Faibussowitsch { 17752999313aSBarry Smith PetscFunctionBegin; 17760700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 17770700a824SBarry Smith PetscValidHeaderSpecific(ksp, KSP_CLASSID, 2); 17782999313aSBarry Smith PetscCheckSameComm(snes, 1, ksp, 2); 17799566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)ksp)); 17809566063dSJacob Faibussowitsch if (snes->ksp) PetscCall(PetscObjectDereference((PetscObject)snes->ksp)); 17812999313aSBarry Smith snes->ksp = ksp; 17823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17832999313aSBarry Smith } 17842999313aSBarry Smith 178552baeb72SSatish Balay /*@ 178677e5a1f9SBarry Smith SNESParametersInitialize - Sets all the parameters in `snes` to their default value (when `SNESCreate()` was called) if they 178777e5a1f9SBarry Smith currently contain default values 178877e5a1f9SBarry Smith 178977e5a1f9SBarry Smith Collective 179077e5a1f9SBarry Smith 179177e5a1f9SBarry Smith Input Parameter: 179277e5a1f9SBarry Smith . snes - the `SNES` object 179377e5a1f9SBarry Smith 179477e5a1f9SBarry Smith Level: developer 179577e5a1f9SBarry Smith 179677e5a1f9SBarry Smith Developer Note: 179777e5a1f9SBarry Smith This is called by all the `SNESCreate_XXX()` routines. 179877e5a1f9SBarry Smith 179977e5a1f9SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`, 180077e5a1f9SBarry Smith `PetscObjectParameterSetDefault()` 180177e5a1f9SBarry Smith @*/ 180277e5a1f9SBarry Smith PetscErrorCode SNESParametersInitialize(SNES snes) 180377e5a1f9SBarry Smith { 180477e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, max_its, 50); 180577e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, max_funcs, 10000); 180677e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, rtol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8); 180777e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, abstol, PetscDefined(USE_REAL_SINGLE) ? 1.e-25 : 1.e-50); 180877e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, stol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8); 180977e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, divtol, 1.e4); 181077e5a1f9SBarry Smith return PETSC_SUCCESS; 181177e5a1f9SBarry Smith } 181277e5a1f9SBarry Smith 181377e5a1f9SBarry Smith /*@ 1814dc4c0fb0SBarry Smith SNESCreate - Creates a nonlinear solver context used to manage a set of nonlinear solves 18159b94acceSBarry Smith 1816d083f849SBarry Smith Collective 1817c7afd0dbSLois Curfman McInnes 1818f6dfbefdSBarry Smith Input Parameter: 1819906ed7ccSBarry Smith . comm - MPI communicator 18209b94acceSBarry Smith 18219b94acceSBarry Smith Output Parameter: 182220f4b53cSBarry Smith . outsnes - the new `SNES` context 18239b94acceSBarry Smith 1824c7afd0dbSLois Curfman McInnes Options Database Keys: 18257addb90fSBarry Smith + -snes_mf - Activates default matrix-free Jacobian-vector products, and no matrix to construct a preconditioner 18267addb90fSBarry Smith . -snes_mf_operator - Activates default matrix-free Jacobian-vector products, and a user-provided matrix as set by `SNESSetJacobian()` 1827dc4c0fb0SBarry Smith . -snes_fd_coloring - uses a relative fast computation of the Jacobian using finite differences and a graph coloring 1828c7afd0dbSLois Curfman McInnes - -snes_fd - Uses (slow!) finite differences to compute Jacobian 1829c1f60f51SBarry Smith 183036851e7fSLois Curfman McInnes Level: beginner 183136851e7fSLois Curfman McInnes 183295452b02SPatrick Sanan Developer Notes: 1833f6dfbefdSBarry Smith `SNES` always creates a `KSP` object even though many `SNES` methods do not use it. This is 1834efd4aadfSBarry Smith unfortunate and should be fixed at some point. The flag snes->usesksp indicates if the 1835f6dfbefdSBarry Smith particular method does use `KSP` and regulates if the information about the `KSP` is printed 1836f6dfbefdSBarry Smith in `SNESView()`. 1837efd4aadfSBarry Smith 1838f6dfbefdSBarry Smith `TSSetFromOptions()` does call `SNESSetFromOptions()` which can lead to users being confused 1839f6dfbefdSBarry Smith by help messages about meaningless `SNES` options. 1840f6dfbefdSBarry Smith 18417addb90fSBarry Smith `SNES` always creates the `snes->kspconvctx` even though it is used by only one type. This should be fixed. 1842efd4aadfSBarry Smith 1843e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()` 18449b94acceSBarry Smith @*/ 1845d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESCreate(MPI_Comm comm, SNES *outsnes) 1846d71ae5a4SJacob Faibussowitsch { 18479b94acceSBarry Smith SNES snes; 1848fa9f3622SBarry Smith SNESKSPEW *kctx; 184937fcc0dbSBarry Smith 18503a40ed3dSBarry Smith PetscFunctionBegin; 18514f572ea9SToby Isaac PetscAssertPointer(outsnes, 2); 18529566063dSJacob Faibussowitsch PetscCall(SNESInitializePackage()); 18538ba1e511SMatthew Knepley 18549566063dSJacob Faibussowitsch PetscCall(PetscHeaderCreate(snes, SNES_CLASSID, "SNES", "Nonlinear solver", "SNES", comm, SNESDestroy, SNESView)); 18558d359177SBarry Smith snes->ops->converged = SNESConvergedDefault; 18562c155ee1SBarry Smith snes->usesksp = PETSC_TRUE; 18579b94acceSBarry Smith snes->norm = 0.0; 1858c1e67a49SFande Kong snes->xnorm = 0.0; 1859c1e67a49SFande Kong snes->ynorm = 0.0; 1860365a6726SPeter Brune snes->normschedule = SNES_NORM_ALWAYS; 18616c67d002SPeter Brune snes->functype = SNES_FUNCTION_DEFAULT; 1862b4874afaSBarry Smith snes->ttol = 0.0; 186377e5a1f9SBarry Smith 1864e37c518bSBarry Smith snes->rnorm0 = 0; 18659b94acceSBarry Smith snes->nfuncs = 0; 186650ffb88aSMatthew Knepley snes->numFailures = 0; 186750ffb88aSMatthew Knepley snes->maxFailures = 1; 18687a00f4a9SLois Curfman McInnes snes->linear_its = 0; 1869e35cf81dSBarry Smith snes->lagjacobian = 1; 187037ec4e1aSPeter Brune snes->jac_iter = 0; 187137ec4e1aSPeter Brune snes->lagjac_persist = PETSC_FALSE; 1872a8054027SBarry Smith snes->lagpreconditioner = 1; 187337ec4e1aSPeter Brune snes->pre_iter = 0; 187437ec4e1aSPeter Brune snes->lagpre_persist = PETSC_FALSE; 1875639f9d9dSBarry Smith snes->numbermonitors = 0; 1876c4421ceaSFande Kong snes->numberreasonviews = 0; 18779e5d0892SLisandro Dalcin snes->data = NULL; 18784dc4c822SBarry Smith snes->setupcalled = PETSC_FALSE; 1879186905e3SBarry Smith snes->ksp_ewconv = PETSC_FALSE; 18806f24a144SLois Curfman McInnes snes->nwork = 0; 18819e5d0892SLisandro Dalcin snes->work = NULL; 188258c9b817SLisandro Dalcin snes->nvwork = 0; 18839e5d0892SLisandro Dalcin snes->vwork = NULL; 1884758f92a0SBarry Smith snes->conv_hist_len = 0; 1885758f92a0SBarry Smith snes->conv_hist_max = 0; 18860298fd71SBarry Smith snes->conv_hist = NULL; 18870298fd71SBarry Smith snes->conv_hist_its = NULL; 1888758f92a0SBarry Smith snes->conv_hist_reset = PETSC_TRUE; 1889971e163fSPeter Brune snes->counters_reset = PETSC_TRUE; 1890e4ed7901SPeter Brune snes->vec_func_init_set = PETSC_FALSE; 1891184914b5SBarry Smith snes->reason = SNES_CONVERGED_ITERATING; 1892efd4aadfSBarry Smith snes->npcside = PC_RIGHT; 1893b3cd9a81SMatthew G. Knepley snes->setfromoptionscalled = 0; 1894c40d0f55SPeter Brune 1895d8f46077SPeter Brune snes->mf = PETSC_FALSE; 1896d8f46077SPeter Brune snes->mf_operator = PETSC_FALSE; 1897d8f46077SPeter Brune snes->mf_version = 1; 1898d8f46077SPeter Brune 18993d4c4710SBarry Smith snes->numLinearSolveFailures = 0; 19003d4c4710SBarry Smith snes->maxLinearSolveFailures = 1; 19013d4c4710SBarry Smith 1902349187a7SBarry Smith snes->vizerotolerance = 1.e-8; 190376bd3646SJed Brown snes->checkjacdomainerror = PetscDefined(USE_DEBUG) ? PETSC_TRUE : PETSC_FALSE; 1904349187a7SBarry Smith 19054fc747eaSLawrence Mitchell /* Set this to true if the implementation of SNESSolve_XXX does compute the residual at the final solution. */ 19064fc747eaSLawrence Mitchell snes->alwayscomputesfinalresidual = PETSC_FALSE; 19074fc747eaSLawrence Mitchell 19089b94acceSBarry Smith /* Create context to compute Eisenstat-Walker relative tolerance for KSP */ 19094dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&kctx)); 1910f5af7f23SKarl Rupp 1911835f2295SStefano Zampini snes->kspconvctx = kctx; 19129b94acceSBarry Smith kctx->version = 2; 19130f0abf79SStefano Zampini kctx->rtol_0 = 0.3; /* Eisenstat and Walker suggest rtol_0=.5, but 19149b94acceSBarry Smith this was too large for some test cases */ 191575567043SBarry Smith kctx->rtol_last = 0.0; 19160f0abf79SStefano Zampini kctx->rtol_max = 0.9; 19179b94acceSBarry Smith kctx->gamma = 1.0; 19180f0abf79SStefano Zampini kctx->alpha = 0.5 * (1.0 + PetscSqrtReal(5.0)); 191971f87433Sdalcinl kctx->alpha2 = kctx->alpha; 19200f0abf79SStefano Zampini kctx->threshold = 0.1; 192175567043SBarry Smith kctx->lresid_last = 0.0; 192275567043SBarry Smith kctx->norm_last = 0.0; 19239b94acceSBarry Smith 19240f0abf79SStefano Zampini kctx->rk_last = 0.0; 19250f0abf79SStefano Zampini kctx->rk_last_2 = 0.0; 19260f0abf79SStefano Zampini kctx->rtol_last_2 = 0.0; 19270f0abf79SStefano Zampini kctx->v4_p1 = 0.1; 19280f0abf79SStefano Zampini kctx->v4_p2 = 0.4; 19290f0abf79SStefano Zampini kctx->v4_p3 = 0.7; 19300f0abf79SStefano Zampini kctx->v4_m1 = 0.8; 19310f0abf79SStefano Zampini kctx->v4_m2 = 0.5; 19320f0abf79SStefano Zampini kctx->v4_m3 = 0.1; 19330f0abf79SStefano Zampini kctx->v4_m4 = 0.5; 19340f0abf79SStefano Zampini 1935b50c806fSBarry Smith PetscCall(SNESParametersInitialize(snes)); 19369b94acceSBarry Smith *outsnes = snes; 19373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19389b94acceSBarry Smith } 19399b94acceSBarry Smith 19409b94acceSBarry Smith /*@C 19419b94acceSBarry Smith SNESSetFunction - Sets the function evaluation routine and function 1942f6dfbefdSBarry Smith vector for use by the `SNES` routines in solving systems of nonlinear 19439b94acceSBarry Smith equations. 19449b94acceSBarry Smith 1945c3339decSBarry Smith Logically Collective 1946fee21e36SBarry Smith 1947c7afd0dbSLois Curfman McInnes Input Parameters: 1948f6dfbefdSBarry Smith + snes - the `SNES` context 1949dc4c0fb0SBarry Smith . r - vector to store function values, may be `NULL` 19508434afd1SBarry Smith . f - function evaluation routine; for calling sequence see `SNESFunctionFn` 1951c7afd0dbSLois Curfman McInnes - ctx - [optional] user-defined context for private data for the 1952dc4c0fb0SBarry Smith function evaluation routine (may be `NULL`) 19539b94acceSBarry Smith 195436851e7fSLois Curfman McInnes Level: beginner 195536851e7fSLois Curfman McInnes 19568434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetPicard()`, `SNESFunctionFn` 19579b94acceSBarry Smith @*/ 19588434afd1SBarry Smith PetscErrorCode SNESSetFunction(SNES snes, Vec r, SNESFunctionFn *f, void *ctx) 1959d71ae5a4SJacob Faibussowitsch { 19606cab3a1bSJed Brown DM dm; 19616cab3a1bSJed Brown 19623a40ed3dSBarry Smith PetscFunctionBegin; 19630700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1964d2a683ecSLisandro Dalcin if (r) { 1965d2a683ecSLisandro Dalcin PetscValidHeaderSpecific(r, VEC_CLASSID, 2); 1966d2a683ecSLisandro Dalcin PetscCheckSameComm(snes, 1, r, 2); 19679566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)r)); 19689566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_func)); 196985385478SLisandro Dalcin snes->vec_func = r; 1970d2a683ecSLisandro Dalcin } 19719566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 19729566063dSJacob Faibussowitsch PetscCall(DMSNESSetFunction(dm, f, ctx)); 197348a46eb9SPierre Jolivet if (f == SNESPicardComputeFunction) PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx)); 19743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19759b94acceSBarry Smith } 19769b94acceSBarry Smith 1977e4ed7901SPeter Brune /*@C 19780b4db180SJacob Faibussowitsch SNESSetInitialFunction - Set an already computed function evaluation at the initial guess to be reused by `SNESSolve()`. 1979e4ed7901SPeter Brune 1980c3339decSBarry Smith Logically Collective 1981e4ed7901SPeter Brune 1982e4ed7901SPeter Brune Input Parameters: 1983f6dfbefdSBarry Smith + snes - the `SNES` context 1984e4ed7901SPeter Brune - f - vector to store function value 1985e4ed7901SPeter Brune 1986dc4c0fb0SBarry Smith Level: developer 1987dc4c0fb0SBarry Smith 1988e4ed7901SPeter Brune Notes: 1989e4ed7901SPeter Brune This should not be modified during the solution procedure. 1990e4ed7901SPeter Brune 1991f6dfbefdSBarry Smith This is used extensively in the `SNESFAS` hierarchy and in nonlinear preconditioning. 1992e4ed7901SPeter Brune 19931cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetInitialFunctionNorm()` 1994e4ed7901SPeter Brune @*/ 1995d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetInitialFunction(SNES snes, Vec f) 1996d71ae5a4SJacob Faibussowitsch { 1997e4ed7901SPeter Brune Vec vec_func; 1998e4ed7901SPeter Brune 1999e4ed7901SPeter Brune PetscFunctionBegin; 2000e4ed7901SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2001e4ed7901SPeter Brune PetscValidHeaderSpecific(f, VEC_CLASSID, 2); 2002e4ed7901SPeter Brune PetscCheckSameComm(snes, 1, f, 2); 2003efd4aadfSBarry Smith if (snes->npcside == PC_LEFT && snes->functype == SNES_FUNCTION_PRECONDITIONED) { 2004902f982fSPeter Brune snes->vec_func_init_set = PETSC_FALSE; 20053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2006902f982fSPeter Brune } 20079566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &vec_func, NULL, NULL)); 20089566063dSJacob Faibussowitsch PetscCall(VecCopy(f, vec_func)); 2009f5af7f23SKarl Rupp 2010217b9c2eSPeter Brune snes->vec_func_init_set = PETSC_TRUE; 20113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2012e4ed7901SPeter Brune } 2013e4ed7901SPeter Brune 2014534ebe21SPeter Brune /*@ 2015f6dfbefdSBarry Smith SNESSetNormSchedule - Sets the `SNESNormSchedule` used in convergence and monitoring 2016f6dfbefdSBarry Smith of the `SNES` method, when norms are computed in the solving process 2017534ebe21SPeter Brune 2018c3339decSBarry Smith Logically Collective 2019534ebe21SPeter Brune 2020534ebe21SPeter Brune Input Parameters: 2021f6dfbefdSBarry Smith + snes - the `SNES` context 2022365a6726SPeter Brune - normschedule - the frequency of norm computation 2023534ebe21SPeter Brune 2024517f1916SMatthew G. Knepley Options Database Key: 202567b8a455SSatish Balay . -snes_norm_schedule <none, always, initialonly, finalonly, initialfinalonly> - set the schedule 2026517f1916SMatthew G. Knepley 2027dc4c0fb0SBarry Smith Level: advanced 2028dc4c0fb0SBarry Smith 2029534ebe21SPeter Brune Notes: 2030f6dfbefdSBarry Smith Only certain `SNES` methods support certain `SNESNormSchedules`. Most require evaluation 2031534ebe21SPeter Brune of the nonlinear function and the taking of its norm at every iteration to 2032534ebe21SPeter Brune even ensure convergence at all. However, methods such as custom Gauss-Seidel methods 2033f6dfbefdSBarry Smith `SNESNGS` and the like do not require the norm of the function to be computed, and therefore 2034534ebe21SPeter Brune may either be monitored for convergence or not. As these are often used as nonlinear 2035534ebe21SPeter Brune preconditioners, monitoring the norm of their error is not a useful enterprise within 2036534ebe21SPeter Brune their solution. 2037534ebe21SPeter Brune 2038e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNESNormSchedule`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()` 2039534ebe21SPeter Brune @*/ 2040d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNormSchedule(SNES snes, SNESNormSchedule normschedule) 2041d71ae5a4SJacob Faibussowitsch { 2042534ebe21SPeter Brune PetscFunctionBegin; 2043534ebe21SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2044365a6726SPeter Brune snes->normschedule = normschedule; 20453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2046534ebe21SPeter Brune } 2047534ebe21SPeter Brune 2048534ebe21SPeter Brune /*@ 2049f6dfbefdSBarry Smith SNESGetNormSchedule - Gets the `SNESNormSchedule` used in convergence and monitoring 2050f6dfbefdSBarry Smith of the `SNES` method. 2051534ebe21SPeter Brune 2052c3339decSBarry Smith Logically Collective 2053534ebe21SPeter Brune 2054534ebe21SPeter Brune Input Parameters: 2055f6dfbefdSBarry Smith + snes - the `SNES` context 2056365a6726SPeter Brune - normschedule - the type of the norm used 2057534ebe21SPeter Brune 2058534ebe21SPeter Brune Level: advanced 2059534ebe21SPeter Brune 20601cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 2061534ebe21SPeter Brune @*/ 2062d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNormSchedule(SNES snes, SNESNormSchedule *normschedule) 2063d71ae5a4SJacob Faibussowitsch { 2064534ebe21SPeter Brune PetscFunctionBegin; 2065534ebe21SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2066365a6726SPeter Brune *normschedule = snes->normschedule; 20673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2068534ebe21SPeter Brune } 2069534ebe21SPeter Brune 2070c5ce4427SMatthew G. Knepley /*@ 2071c5ce4427SMatthew G. Knepley SNESSetFunctionNorm - Sets the last computed residual norm. 2072c5ce4427SMatthew G. Knepley 2073c3339decSBarry Smith Logically Collective 2074c5ce4427SMatthew G. Knepley 2075c5ce4427SMatthew G. Knepley Input Parameters: 2076f6dfbefdSBarry Smith + snes - the `SNES` context 2077f6dfbefdSBarry Smith - norm - the value of the norm 2078c5ce4427SMatthew G. Knepley 2079c5ce4427SMatthew G. Knepley Level: developer 2080c5ce4427SMatthew G. Knepley 20811cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 2082c5ce4427SMatthew G. Knepley @*/ 2083d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionNorm(SNES snes, PetscReal norm) 2084d71ae5a4SJacob Faibussowitsch { 2085c5ce4427SMatthew G. Knepley PetscFunctionBegin; 2086c5ce4427SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2087c5ce4427SMatthew G. Knepley snes->norm = norm; 20883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2089c5ce4427SMatthew G. Knepley } 2090c5ce4427SMatthew G. Knepley 2091c5ce4427SMatthew G. Knepley /*@ 2092c5ce4427SMatthew G. Knepley SNESGetFunctionNorm - Gets the last computed norm of the residual 2093c5ce4427SMatthew G. Knepley 2094c5ce4427SMatthew G. Knepley Not Collective 2095c5ce4427SMatthew G. Knepley 2096c5ce4427SMatthew G. Knepley Input Parameter: 2097f6dfbefdSBarry Smith . snes - the `SNES` context 2098c5ce4427SMatthew G. Knepley 2099c5ce4427SMatthew G. Knepley Output Parameter: 2100c5ce4427SMatthew G. Knepley . norm - the last computed residual norm 2101c5ce4427SMatthew G. Knepley 2102c5ce4427SMatthew G. Knepley Level: developer 2103c5ce4427SMatthew G. Knepley 21041cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 2105c5ce4427SMatthew G. Knepley @*/ 2106d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionNorm(SNES snes, PetscReal *norm) 2107d71ae5a4SJacob Faibussowitsch { 2108c5ce4427SMatthew G. Knepley PetscFunctionBegin; 2109c5ce4427SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 21104f572ea9SToby Isaac PetscAssertPointer(norm, 2); 2111c5ce4427SMatthew G. Knepley *norm = snes->norm; 21123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2113c5ce4427SMatthew G. Knepley } 2114c5ce4427SMatthew G. Knepley 2115c1e67a49SFande Kong /*@ 2116f6dfbefdSBarry Smith SNESGetUpdateNorm - Gets the last computed norm of the solution update 2117c1e67a49SFande Kong 2118c1e67a49SFande Kong Not Collective 2119c1e67a49SFande Kong 2120c1e67a49SFande Kong Input Parameter: 2121f6dfbefdSBarry Smith . snes - the `SNES` context 2122c1e67a49SFande Kong 2123c1e67a49SFande Kong Output Parameter: 2124c1e67a49SFande Kong . ynorm - the last computed update norm 2125c1e67a49SFande Kong 2126c1e67a49SFande Kong Level: developer 2127c1e67a49SFande Kong 2128f6dfbefdSBarry Smith Note: 2129f6dfbefdSBarry Smith The new solution is the current solution plus the update, so this norm is an indication of the size of the update 2130f6dfbefdSBarry Smith 21311cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()` 2132c1e67a49SFande Kong @*/ 2133d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUpdateNorm(SNES snes, PetscReal *ynorm) 2134d71ae5a4SJacob Faibussowitsch { 2135c1e67a49SFande Kong PetscFunctionBegin; 2136c1e67a49SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 21374f572ea9SToby Isaac PetscAssertPointer(ynorm, 2); 2138c1e67a49SFande Kong *ynorm = snes->ynorm; 21393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2140c1e67a49SFande Kong } 2141c1e67a49SFande Kong 2142c1e67a49SFande Kong /*@ 21434591eaf2SFande Kong SNESGetSolutionNorm - Gets the last computed norm of the solution 2144c1e67a49SFande Kong 2145c1e67a49SFande Kong Not Collective 2146c1e67a49SFande Kong 2147c1e67a49SFande Kong Input Parameter: 2148f6dfbefdSBarry Smith . snes - the `SNES` context 2149c1e67a49SFande Kong 2150c1e67a49SFande Kong Output Parameter: 2151c1e67a49SFande Kong . xnorm - the last computed solution norm 2152c1e67a49SFande Kong 2153c1e67a49SFande Kong Level: developer 2154c1e67a49SFande Kong 21551cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`, `SNESGetUpdateNorm()` 2156c1e67a49SFande Kong @*/ 2157d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionNorm(SNES snes, PetscReal *xnorm) 2158d71ae5a4SJacob Faibussowitsch { 2159c1e67a49SFande Kong PetscFunctionBegin; 2160c1e67a49SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 21614f572ea9SToby Isaac PetscAssertPointer(xnorm, 2); 2162c1e67a49SFande Kong *xnorm = snes->xnorm; 21633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2164c1e67a49SFande Kong } 2165c1e67a49SFande Kong 2166cc4c1da9SBarry Smith /*@ 2167f6dfbefdSBarry Smith SNESSetFunctionType - Sets the `SNESFunctionType` 2168f6dfbefdSBarry Smith of the `SNES` method. 216947073ea2SPeter Brune 2170c3339decSBarry Smith Logically Collective 217147073ea2SPeter Brune 217247073ea2SPeter Brune Input Parameters: 2173f6dfbefdSBarry Smith + snes - the `SNES` context 2174f6dfbefdSBarry Smith - type - the function type 217547073ea2SPeter Brune 217647073ea2SPeter Brune Level: developer 217747073ea2SPeter Brune 2178420bcc1bSBarry Smith Values of the function type\: 2179f6dfbefdSBarry Smith + `SNES_FUNCTION_DEFAULT` - the default for the given `SNESType` 2180f6dfbefdSBarry Smith . `SNES_FUNCTION_UNPRECONDITIONED` - an unpreconditioned function evaluation (this is the function provided with `SNESSetFunction()` 2181f6dfbefdSBarry Smith - `SNES_FUNCTION_PRECONDITIONED` - a transformation of the function provided with `SNESSetFunction()` 2182f6dfbefdSBarry Smith 2183420bcc1bSBarry Smith Note: 2184f6dfbefdSBarry Smith Different `SNESType`s use this value in different ways 2185f6dfbefdSBarry Smith 21861cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFunctionType`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 218747073ea2SPeter Brune @*/ 2188d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionType(SNES snes, SNESFunctionType type) 2189d71ae5a4SJacob Faibussowitsch { 219047073ea2SPeter Brune PetscFunctionBegin; 219147073ea2SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 219247073ea2SPeter Brune snes->functype = type; 21933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 219447073ea2SPeter Brune } 219547073ea2SPeter Brune 2196cc4c1da9SBarry Smith /*@ 2197f6dfbefdSBarry Smith SNESGetFunctionType - Gets the `SNESFunctionType` used in convergence and monitoring set with `SNESSetFunctionType()` 219847073ea2SPeter Brune of the SNES method. 219947073ea2SPeter Brune 2200c3339decSBarry Smith Logically Collective 220147073ea2SPeter Brune 220247073ea2SPeter Brune Input Parameters: 2203f6dfbefdSBarry Smith + snes - the `SNES` context 2204f6dfbefdSBarry Smith - type - the type of the function evaluation, see `SNESSetFunctionType()` 220547073ea2SPeter Brune 220647073ea2SPeter Brune Level: advanced 220747073ea2SPeter Brune 22081cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetFunctionType()`, `SNESFunctionType`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 220947073ea2SPeter Brune @*/ 2210d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionType(SNES snes, SNESFunctionType *type) 2211d71ae5a4SJacob Faibussowitsch { 221247073ea2SPeter Brune PetscFunctionBegin; 221347073ea2SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 221447073ea2SPeter Brune *type = snes->functype; 22153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2216534ebe21SPeter Brune } 2217534ebe21SPeter Brune 2218c79ef259SPeter Brune /*@C 2219be95d8f1SBarry Smith SNESSetNGS - Sets the user nonlinear Gauss-Seidel routine for 2220c79ef259SPeter Brune use with composed nonlinear solvers. 2221c79ef259SPeter Brune 2222c79ef259SPeter Brune Input Parameters: 22239bcc50f1SBarry Smith + snes - the `SNES` context, usually of the `SNESType` `SNESNGS` 22248434afd1SBarry Smith . f - function evaluation routine to apply Gauss-Seidel, see `SNESNGSFn` for calling sequence 222577e5a1f9SBarry Smith - ctx - [optional] user-defined context for private data for the smoother evaluation routine (may be `NULL`) 2226c79ef259SPeter Brune 2227dc4c0fb0SBarry Smith Level: intermediate 2228dc4c0fb0SBarry Smith 2229f6dfbefdSBarry Smith Note: 2230f6dfbefdSBarry Smith The `SNESNGS` routines are used by the composed nonlinear solver to generate 2231f6dfbefdSBarry Smith a problem appropriate update to the solution, particularly `SNESFAS`. 2232c79ef259SPeter Brune 22338434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGS`, `SNESGetNGS()`, `SNESNCG`, `SNESGetFunction()`, `SNESComputeNGS()`, `SNESNGSFn` 2234c79ef259SPeter Brune @*/ 22358434afd1SBarry Smith PetscErrorCode SNESSetNGS(SNES snes, SNESNGSFn *f, void *ctx) 2236d71ae5a4SJacob Faibussowitsch { 22376cab3a1bSJed Brown DM dm; 22386cab3a1bSJed Brown 2239646217ecSPeter Brune PetscFunctionBegin; 22406cab3a1bSJed Brown PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 22419566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 22429566063dSJacob Faibussowitsch PetscCall(DMSNESSetNGS(dm, f, ctx)); 22433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2244646217ecSPeter Brune } 2245646217ecSPeter Brune 2246bbc1464cSBarry Smith /* 2247bbc1464cSBarry Smith This is used for -snes_mf_operator; it uses a duplicate of snes->jacobian_pre because snes->jacobian_pre cannot be 2248bbc1464cSBarry Smith changed during the KSPSolve() 2249bbc1464cSBarry Smith */ 2250d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeMFFunction(SNES snes, Vec x, Vec f, void *ctx) 2251d71ae5a4SJacob Faibussowitsch { 2252bbc1464cSBarry Smith DM dm; 2253bbc1464cSBarry Smith DMSNES sdm; 2254bbc1464cSBarry Smith 2255bbc1464cSBarry Smith PetscFunctionBegin; 22569566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 22579566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 2258bbc1464cSBarry Smith /* A(x)*x - b(x) */ 2259bbc1464cSBarry Smith if (sdm->ops->computepfunction) { 2260792fecdfSBarry Smith PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx)); 22619566063dSJacob Faibussowitsch PetscCall(VecScale(f, -1.0)); 22620df40c35SBarry Smith /* Cannot share nonzero pattern because of the possible use of SNESComputeJacobianDefault() */ 2263ef1023bdSBarry Smith if (!snes->picard) PetscCall(MatDuplicate(snes->jacobian_pre, MAT_DO_NOT_COPY_VALUES, &snes->picard)); 2264792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx)); 22659566063dSJacob Faibussowitsch PetscCall(MatMultAdd(snes->picard, x, f, f)); 2266bbc1464cSBarry Smith } else { 2267792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx)); 22689566063dSJacob Faibussowitsch PetscCall(MatMult(snes->picard, x, f)); 2269bbc1464cSBarry Smith } 22703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2271bbc1464cSBarry Smith } 2272bbc1464cSBarry Smith 2273d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeFunction(SNES snes, Vec x, Vec f, void *ctx) 2274d71ae5a4SJacob Faibussowitsch { 2275e03ab78fSPeter Brune DM dm; 2276942e3340SBarry Smith DMSNES sdm; 22776cab3a1bSJed Brown 22788b0a5094SBarry Smith PetscFunctionBegin; 22799566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 22809566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 22818b0a5094SBarry Smith /* A(x)*x - b(x) */ 2282bbc1464cSBarry Smith if (sdm->ops->computepfunction) { 2283792fecdfSBarry Smith PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx)); 22849566063dSJacob Faibussowitsch PetscCall(VecScale(f, -1.0)); 2285792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx)); 22869566063dSJacob Faibussowitsch PetscCall(MatMultAdd(snes->jacobian_pre, x, f, f)); 2287bbc1464cSBarry Smith } else { 2288792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx)); 22899566063dSJacob Faibussowitsch PetscCall(MatMult(snes->jacobian_pre, x, f)); 2290bbc1464cSBarry Smith } 22913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22928b0a5094SBarry Smith } 22938b0a5094SBarry Smith 2294d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeJacobian(SNES snes, Vec x1, Mat J, Mat B, void *ctx) 2295d71ae5a4SJacob Faibussowitsch { 22968b0a5094SBarry Smith PetscFunctionBegin; 2297e03ab78fSPeter Brune /* the jacobian matrix should be pre-filled in SNESPicardComputeFunction */ 2298bbc1464cSBarry Smith /* must assembly if matrix-free to get the last SNES solution */ 22999566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 23009566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 23013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23028b0a5094SBarry Smith } 23038b0a5094SBarry Smith 23048b0a5094SBarry Smith /*@C 23051d27aa22SBarry Smith SNESSetPicard - Use `SNES` to solve the system $A(x) x = bp(x) + b $ via a Picard type iteration (Picard linearization) 23068b0a5094SBarry Smith 2307c3339decSBarry Smith Logically Collective 23088b0a5094SBarry Smith 23098b0a5094SBarry Smith Input Parameters: 2310f6dfbefdSBarry Smith + snes - the `SNES` context 2311dc4c0fb0SBarry Smith . r - vector to store function values, may be `NULL` 23128434afd1SBarry Smith . bp - function evaluation routine, may be `NULL`, for the calling sequence see `SNESFunctionFn` 231326a11704SBarry Smith . Amat - matrix with which $A(x) x - bp(x) - b$ is to be computed 2314dc4c0fb0SBarry Smith . Pmat - matrix from which preconditioner is computed (usually the same as `Amat`) 23158434afd1SBarry Smith . J - function to compute matrix values, for the calling sequence see `SNESJacobianFn` 2316dc4c0fb0SBarry Smith - ctx - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`) 2317dc4c0fb0SBarry Smith 2318dc4c0fb0SBarry Smith Level: intermediate 23198b0a5094SBarry Smith 23208b0a5094SBarry Smith Notes: 232126a11704SBarry Smith It is often better to provide the nonlinear function $F()$ and some approximation to its Jacobian directly and use 2322f450aa47SBarry 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. 2323f450aa47SBarry Smith 2324f6dfbefdSBarry Smith One can call `SNESSetPicard()` or `SNESSetFunction()` (and possibly `SNESSetJacobian()`) but cannot call both 23258b0a5094SBarry Smith 23261d27aa22SBarry 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}$. 23271d27aa22SBarry Smith When an exact solver is used this corresponds to the "classic" Picard $A(x^{n}) x^{n+1} = bp(x^{n}) + b$ iteration. 23288b0a5094SBarry Smith 232926a11704SBarry Smith Run with `-snes_mf_operator` to solve the system with Newton's method using $A(x^{n})$ to construct the preconditioner. 23308b0a5094SBarry Smith 23310d04baf8SBarry Smith We implement the defect correction form of the Picard iteration because it converges much more generally when inexact linear solvers are used then 23321d27aa22SBarry Smith the direct Picard iteration $A(x^n) x^{n+1} = bp(x^n) + b$ 23338b0a5094SBarry Smith 23348b0a5094SBarry 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 23351d27aa22SBarry 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 23361d27aa22SBarry Smith different please contact us at petsc-dev@mcs.anl.gov and we'll have an entirely new argument \:-). 23378b0a5094SBarry Smith 23381d27aa22SBarry 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 233926a11704SBarry Smith $A(x^{n})$ is used to build the preconditioner 23406b7fb656SBarry Smith 234115229ffcSPierre 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. 23426b7fb656SBarry Smith 2343dc4c0fb0SBarry 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 234426a11704SBarry 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 234526a11704SBarry 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`. 2346aaa8cc7dSPierre Jolivet See the comment in src/snes/tutorials/ex15.c. 2347bbc1464cSBarry Smith 23489bcc50f1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESGetPicard()`, `SNESLineSearchPreCheckPicard()`, 23498434afd1SBarry Smith `SNESFunctionFn`, `SNESJacobianFn` 23508b0a5094SBarry Smith @*/ 23518434afd1SBarry Smith PetscErrorCode SNESSetPicard(SNES snes, Vec r, SNESFunctionFn *bp, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx) 2352d71ae5a4SJacob Faibussowitsch { 2353e03ab78fSPeter Brune DM dm; 2354e03ab78fSPeter Brune 23558b0a5094SBarry Smith PetscFunctionBegin; 23568b0a5094SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 23579566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 23589566063dSJacob Faibussowitsch PetscCall(DMSNESSetPicard(dm, bp, J, ctx)); 23599566063dSJacob Faibussowitsch PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx)); 23609566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes, r, SNESPicardComputeFunction, ctx)); 23619566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESPicardComputeJacobian, ctx)); 23623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23638b0a5094SBarry Smith } 23648b0a5094SBarry Smith 23657971a8bfSPeter Brune /*@C 23667971a8bfSPeter Brune SNESGetPicard - Returns the context for the Picard iteration 23677971a8bfSPeter Brune 2368f6dfbefdSBarry Smith Not Collective, but `Vec` is parallel if `SNES` is parallel. Collective if `Vec` is requested, but has not been created yet. 23697971a8bfSPeter Brune 23707971a8bfSPeter Brune Input Parameter: 2371f6dfbefdSBarry Smith . snes - the `SNES` context 23727971a8bfSPeter Brune 2373d8d19677SJose E. Roman Output Parameters: 2374dc4c0fb0SBarry Smith + r - the function (or `NULL`) 23758434afd1SBarry Smith . f - the function (or `NULL`); for calling sequence see `SNESFunctionFn` 2376dc4c0fb0SBarry Smith . Amat - the matrix used to defined the operation A(x) x - b(x) (or `NULL`) 2377dc4c0fb0SBarry Smith . Pmat - the matrix from which the preconditioner will be constructed (or `NULL`) 23788434afd1SBarry Smith . J - the function for matrix evaluation (or `NULL`); for calling sequence see `SNESJacobianFn` 2379dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`) 23807971a8bfSPeter Brune 23817971a8bfSPeter Brune Level: advanced 23827971a8bfSPeter Brune 23838434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetFunction()`, `SNESSetPicard()`, `SNESGetFunction()`, `SNESGetJacobian()`, `SNESGetDM()`, `SNESFunctionFn`, `SNESJacobianFn` 23847971a8bfSPeter Brune @*/ 23858434afd1SBarry Smith PetscErrorCode SNESGetPicard(SNES snes, Vec *r, SNESFunctionFn **f, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx) 2386d71ae5a4SJacob Faibussowitsch { 23877971a8bfSPeter Brune DM dm; 23887971a8bfSPeter Brune 23897971a8bfSPeter Brune PetscFunctionBegin; 23907971a8bfSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 23919566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, r, NULL, NULL)); 23929566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL)); 23939566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 23949566063dSJacob Faibussowitsch PetscCall(DMSNESGetPicard(dm, f, J, ctx)); 23953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23967971a8bfSPeter Brune } 23977971a8bfSPeter Brune 2398d25893d9SBarry Smith /*@C 2399dc4c0fb0SBarry Smith SNESSetComputeInitialGuess - Sets a routine used to compute an initial guess for the nonlinear problem 2400d25893d9SBarry Smith 2401c3339decSBarry Smith Logically Collective 2402d25893d9SBarry Smith 2403d25893d9SBarry Smith Input Parameters: 2404f6dfbefdSBarry Smith + snes - the `SNES` context 24058434afd1SBarry Smith . func - function evaluation routine, see `SNESInitialGuessFn` for the calling sequence 2406d25893d9SBarry Smith - ctx - [optional] user-defined context for private data for the 2407dc4c0fb0SBarry Smith function evaluation routine (may be `NULL`) 2408d25893d9SBarry Smith 2409d25893d9SBarry Smith Level: intermediate 2410d25893d9SBarry Smith 24118434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESInitialGuessFn` 2412d25893d9SBarry Smith @*/ 24138434afd1SBarry Smith PetscErrorCode SNESSetComputeInitialGuess(SNES snes, SNESInitialGuessFn *func, void *ctx) 2414d71ae5a4SJacob Faibussowitsch { 2415d25893d9SBarry Smith PetscFunctionBegin; 2416d25893d9SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2417d25893d9SBarry Smith if (func) snes->ops->computeinitialguess = func; 2418d25893d9SBarry Smith if (ctx) snes->initialguessP = ctx; 24193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2420d25893d9SBarry Smith } 2421d25893d9SBarry Smith 24221096aae1SMatthew Knepley /*@C 2423dc4c0fb0SBarry Smith SNESGetRhs - Gets the vector for solving F(x) = `rhs`. If `rhs` is not set 2424dd8e379bSPierre Jolivet it assumes a zero right-hand side. 24251096aae1SMatthew Knepley 2426c3339decSBarry Smith Logically Collective 24271096aae1SMatthew Knepley 24281096aae1SMatthew Knepley Input Parameter: 2429f6dfbefdSBarry Smith . snes - the `SNES` context 24301096aae1SMatthew Knepley 24311096aae1SMatthew Knepley Output Parameter: 2432dd8e379bSPierre Jolivet . rhs - the right-hand side vector or `NULL` if there is no right-hand side vector 24331096aae1SMatthew Knepley 24341096aae1SMatthew Knepley Level: intermediate 24351096aae1SMatthew Knepley 24361cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetFunction()` 24371096aae1SMatthew Knepley @*/ 2438d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetRhs(SNES snes, Vec *rhs) 2439d71ae5a4SJacob Faibussowitsch { 24401096aae1SMatthew Knepley PetscFunctionBegin; 24410700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 24424f572ea9SToby Isaac PetscAssertPointer(rhs, 2); 244385385478SLisandro Dalcin *rhs = snes->vec_rhs; 24443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24451096aae1SMatthew Knepley } 24461096aae1SMatthew Knepley 24479b94acceSBarry Smith /*@ 2448f6dfbefdSBarry Smith SNESComputeFunction - Calls the function that has been set with `SNESSetFunction()`. 24499b94acceSBarry Smith 2450c3339decSBarry Smith Collective 2451c7afd0dbSLois Curfman McInnes 24529b94acceSBarry Smith Input Parameters: 2453f6dfbefdSBarry Smith + snes - the `SNES` context 2454c7afd0dbSLois Curfman McInnes - x - input vector 24559b94acceSBarry Smith 24569b94acceSBarry Smith Output Parameter: 2457f6dfbefdSBarry Smith . y - function vector, as set by `SNESSetFunction()` 24589b94acceSBarry Smith 2459dc4c0fb0SBarry Smith Level: developer 2460dc4c0fb0SBarry Smith 246100677de2SStefano Zampini Notes: 2462f6dfbefdSBarry Smith `SNESComputeFunction()` is typically used within nonlinear solvers 2463bbc1464cSBarry Smith implementations, so users would not generally call this routine themselves. 246436851e7fSLois Curfman McInnes 246500677de2SStefano Zampini When solving for $F(x) = b$, this routine computes $y = F(x) - b$. 246600677de2SStefano Zampini 24671cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeMFFunction()` 24689b94acceSBarry Smith @*/ 2469d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeFunction(SNES snes, Vec x, Vec y) 2470d71ae5a4SJacob Faibussowitsch { 24716cab3a1bSJed Brown DM dm; 2472942e3340SBarry Smith DMSNES sdm; 24739b94acceSBarry Smith 24743a40ed3dSBarry Smith PetscFunctionBegin; 24750700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 24760700a824SBarry Smith PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 24770700a824SBarry Smith PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2478c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, x, 2); 2479c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, y, 3); 2480e0f629ddSJacob Faibussowitsch PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2481184914b5SBarry Smith 24829566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 24839566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 24840fdf79fbSJacob 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()."); 248532f3f7c2SPeter Brune if (sdm->ops->computefunction) { 248648a46eb9SPierre Jolivet if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0)); 24879566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(x)); 24888ddeebeaSSteve Benbow /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */ 24898ddeebeaSSteve Benbow snes->domainerror = PETSC_FALSE; 2490800f99ffSJeremy L Thompson { 2491800f99ffSJeremy L Thompson void *ctx; 24928434afd1SBarry Smith SNESFunctionFn *computefunction; 2493800f99ffSJeremy L Thompson PetscCall(DMSNESGetFunction(dm, &computefunction, &ctx)); 2494800f99ffSJeremy L Thompson PetscCallBack("SNES callback function", (*computefunction)(snes, x, y, ctx)); 2495800f99ffSJeremy L Thompson } 24969566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(x)); 249748a46eb9SPierre Jolivet if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0)); 24980fdf79fbSJacob Faibussowitsch } else /* if (snes->vec_rhs) */ { 24999566063dSJacob Faibussowitsch PetscCall(MatMult(snes->jacobian, x, y)); 25000fdf79fbSJacob Faibussowitsch } 25011baa6e33SBarry Smith if (snes->vec_rhs) PetscCall(VecAXPY(y, -1.0, snes->vec_rhs)); 2502ae3c334cSLois Curfman McInnes snes->nfuncs++; 2503422a814eSBarry Smith /* 2504422a814eSBarry Smith domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will 2505422a814eSBarry Smith propagate the value to all processes 2506422a814eSBarry Smith */ 2507f480ea8aSBarry Smith PetscCall(VecFlag(y, snes->domainerror)); 25083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 25099b94acceSBarry Smith } 25109b94acceSBarry Smith 2511c79ef259SPeter Brune /*@ 25120b4b7b1cSBarry Smith SNESComputeMFFunction - Calls the function that has been set with `DMSNESSetMFFunction()`. 2513bbc1464cSBarry Smith 2514c3339decSBarry Smith Collective 2515bbc1464cSBarry Smith 2516bbc1464cSBarry Smith Input Parameters: 2517f6dfbefdSBarry Smith + snes - the `SNES` context 2518bbc1464cSBarry Smith - x - input vector 2519bbc1464cSBarry Smith 2520bbc1464cSBarry Smith Output Parameter: 25210b4b7b1cSBarry Smith . y - output vector 2522bbc1464cSBarry Smith 2523dc4c0fb0SBarry Smith Level: developer 2524dc4c0fb0SBarry Smith 2525bbc1464cSBarry Smith Notes: 2526420bcc1bSBarry Smith `SNESComputeMFFunction()` is used within the matrix-vector products called by the matrix created with `MatCreateSNESMF()` 2527bbc1464cSBarry Smith so users would not generally call this routine themselves. 2528bbc1464cSBarry Smith 2529dd8e379bSPierre Jolivet Since this function is intended for use with finite differencing it does not subtract the right-hand side vector provided with `SNESSolve()` 2530f6dfbefdSBarry Smith while `SNESComputeFunction()` does. As such, this routine cannot be used with `MatMFFDSetBase()` with a provided F function value even if it applies the 2531dd8e379bSPierre 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. 2532bbc1464cSBarry Smith 25330b4b7b1cSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `MatCreateSNESMF()`, `DMSNESSetMFFunction()` 2534bbc1464cSBarry Smith @*/ 2535d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeMFFunction(SNES snes, Vec x, Vec y) 2536d71ae5a4SJacob Faibussowitsch { 2537bbc1464cSBarry Smith DM dm; 2538bbc1464cSBarry Smith DMSNES sdm; 2539bbc1464cSBarry Smith 2540bbc1464cSBarry Smith PetscFunctionBegin; 2541bbc1464cSBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2542bbc1464cSBarry Smith PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2543bbc1464cSBarry Smith PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2544bbc1464cSBarry Smith PetscCheckSameComm(snes, 1, x, 2); 2545bbc1464cSBarry Smith PetscCheckSameComm(snes, 1, y, 3); 2546e0f629ddSJacob Faibussowitsch PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2547bbc1464cSBarry Smith 25489566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 25499566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 25509566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0)); 25519566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(x)); 2552bbc1464cSBarry Smith /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */ 2553bbc1464cSBarry Smith snes->domainerror = PETSC_FALSE; 2554792fecdfSBarry Smith PetscCallBack("SNES callback function", (*sdm->ops->computemffunction)(snes, x, y, sdm->mffunctionctx)); 25559566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(x)); 25569566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0)); 2557bbc1464cSBarry Smith snes->nfuncs++; 2558bbc1464cSBarry Smith /* 2559bbc1464cSBarry Smith domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will 2560bbc1464cSBarry Smith propagate the value to all processes 2561bbc1464cSBarry Smith */ 2562f480ea8aSBarry Smith PetscCall(VecFlag(y, snes->domainerror)); 25633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2564bbc1464cSBarry Smith } 2565bbc1464cSBarry Smith 2566bbc1464cSBarry Smith /*@ 2567f6dfbefdSBarry Smith SNESComputeNGS - Calls the Gauss-Seidel function that has been set with `SNESSetNGS()`. 2568c79ef259SPeter Brune 2569c3339decSBarry Smith Collective 2570c79ef259SPeter Brune 2571c79ef259SPeter Brune Input Parameters: 2572f6dfbefdSBarry Smith + snes - the `SNES` context 2573c79ef259SPeter Brune . x - input vector 2574c79ef259SPeter Brune - b - rhs vector 2575c79ef259SPeter Brune 2576c79ef259SPeter Brune Output Parameter: 2577c79ef259SPeter Brune . x - new solution vector 2578c79ef259SPeter Brune 2579dc4c0fb0SBarry Smith Level: developer 2580dc4c0fb0SBarry Smith 2581f6dfbefdSBarry Smith Note: 2582f6dfbefdSBarry Smith `SNESComputeNGS()` is typically used within composed nonlinear solver 2583c79ef259SPeter Brune implementations, so most users would not generally call this routine 2584c79ef259SPeter Brune themselves. 2585c79ef259SPeter Brune 25868434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGSFn`, `SNESSetNGS()`, `SNESComputeFunction()`, `SNESNGS` 2587c79ef259SPeter Brune @*/ 2588d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeNGS(SNES snes, Vec b, Vec x) 2589d71ae5a4SJacob Faibussowitsch { 25906cab3a1bSJed Brown DM dm; 2591942e3340SBarry Smith DMSNES sdm; 2592646217ecSPeter Brune 2593646217ecSPeter Brune PetscFunctionBegin; 2594646217ecSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2595064a246eSJacob Faibussowitsch PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 2596064a246eSJacob Faibussowitsch if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 2597064a246eSJacob Faibussowitsch PetscCheckSameComm(snes, 1, x, 3); 2598064a246eSJacob Faibussowitsch if (b) PetscCheckSameComm(snes, 1, b, 2); 2599e0f629ddSJacob Faibussowitsch if (b) PetscCall(VecValidValues_Internal(b, 2, PETSC_TRUE)); 26009566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_NGSEval, snes, x, b, 0)); 26019566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 26029566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 26030fdf79fbSJacob Faibussowitsch PetscCheck(sdm->ops->computegs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetNGS() before SNESComputeNGS(), likely called from SNESSolve()."); 26049566063dSJacob Faibussowitsch if (b) PetscCall(VecLockReadPush(b)); 2605792fecdfSBarry Smith PetscCallBack("SNES callback NGS", (*sdm->ops->computegs)(snes, x, b, sdm->gsctx)); 26069566063dSJacob Faibussowitsch if (b) PetscCall(VecLockReadPop(b)); 26079566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_NGSEval, snes, x, b, 0)); 26083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2609646217ecSPeter Brune } 2610646217ecSPeter Brune 2611494a190aSStefano Zampini static PetscErrorCode SNESComputeFunction_FD(SNES snes, Vec Xin, Vec G) 2612494a190aSStefano Zampini { 2613494a190aSStefano Zampini Vec X; 2614494a190aSStefano Zampini PetscScalar *g; 2615494a190aSStefano Zampini PetscReal f, f2; 2616494a190aSStefano Zampini PetscInt low, high, N, i; 2617494a190aSStefano Zampini PetscBool flg; 2618494a190aSStefano Zampini PetscReal h = .5 * PETSC_SQRT_MACHINE_EPSILON; 2619494a190aSStefano Zampini 2620494a190aSStefano Zampini PetscFunctionBegin; 2621494a190aSStefano Zampini PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_fd_delta", &h, &flg)); 2622494a190aSStefano Zampini PetscCall(VecDuplicate(Xin, &X)); 2623494a190aSStefano Zampini PetscCall(VecCopy(Xin, X)); 2624494a190aSStefano Zampini PetscCall(VecGetSize(X, &N)); 2625494a190aSStefano Zampini PetscCall(VecGetOwnershipRange(X, &low, &high)); 2626494a190aSStefano Zampini PetscCall(VecSetOption(X, VEC_IGNORE_OFF_PROC_ENTRIES, PETSC_TRUE)); 2627494a190aSStefano Zampini PetscCall(VecGetArray(G, &g)); 2628494a190aSStefano Zampini for (i = 0; i < N; i++) { 2629494a190aSStefano Zampini PetscCall(VecSetValue(X, i, -h, ADD_VALUES)); 2630494a190aSStefano Zampini PetscCall(VecAssemblyBegin(X)); 2631494a190aSStefano Zampini PetscCall(VecAssemblyEnd(X)); 2632494a190aSStefano Zampini PetscCall(SNESComputeObjective(snes, X, &f)); 2633494a190aSStefano Zampini PetscCall(VecSetValue(X, i, 2.0 * h, ADD_VALUES)); 2634494a190aSStefano Zampini PetscCall(VecAssemblyBegin(X)); 2635494a190aSStefano Zampini PetscCall(VecAssemblyEnd(X)); 2636494a190aSStefano Zampini PetscCall(SNESComputeObjective(snes, X, &f2)); 2637494a190aSStefano Zampini PetscCall(VecSetValue(X, i, -h, ADD_VALUES)); 2638494a190aSStefano Zampini PetscCall(VecAssemblyBegin(X)); 2639494a190aSStefano Zampini PetscCall(VecAssemblyEnd(X)); 2640494a190aSStefano Zampini if (i >= low && i < high) g[i - low] = (f2 - f) / (2.0 * h); 2641494a190aSStefano Zampini } 2642494a190aSStefano Zampini PetscCall(VecRestoreArray(G, &g)); 2643494a190aSStefano Zampini PetscCall(VecDestroy(&X)); 2644494a190aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2645494a190aSStefano Zampini } 2646494a190aSStefano Zampini 2647494a190aSStefano Zampini PetscErrorCode SNESTestFunction(SNES snes) 2648494a190aSStefano Zampini { 2649494a190aSStefano Zampini Vec x, g1, g2, g3; 2650494a190aSStefano Zampini PetscBool complete_print = PETSC_FALSE, test = PETSC_FALSE; 2651494a190aSStefano Zampini PetscReal hcnorm, fdnorm, hcmax, fdmax, diffmax, diffnorm; 2652494a190aSStefano Zampini PetscScalar dot; 2653494a190aSStefano Zampini MPI_Comm comm; 2654494a190aSStefano Zampini PetscViewer viewer, mviewer; 2655494a190aSStefano Zampini PetscViewerFormat format; 2656494a190aSStefano Zampini PetscInt tabs; 2657494a190aSStefano Zampini static PetscBool directionsprinted = PETSC_FALSE; 26588434afd1SBarry Smith SNESObjectiveFn *objective; 2659494a190aSStefano Zampini 2660494a190aSStefano Zampini PetscFunctionBegin; 2661494a190aSStefano Zampini PetscCall(SNESGetObjective(snes, &objective, NULL)); 2662494a190aSStefano Zampini if (!objective) PetscFunctionReturn(PETSC_SUCCESS); 2663494a190aSStefano Zampini 2664494a190aSStefano Zampini PetscObjectOptionsBegin((PetscObject)snes); 2665494a190aSStefano Zampini PetscCall(PetscOptionsName("-snes_test_function", "Compare hand-coded and finite difference function", "None", &test)); 2666494a190aSStefano Zampini PetscCall(PetscOptionsViewer("-snes_test_function_view", "View difference between hand-coded and finite difference function element entries", "None", &mviewer, &format, &complete_print)); 2667494a190aSStefano Zampini PetscOptionsEnd(); 2668494a190aSStefano Zampini if (!test) { 2669494a190aSStefano Zampini if (complete_print) PetscCall(PetscViewerDestroy(&mviewer)); 2670494a190aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2671494a190aSStefano Zampini } 2672494a190aSStefano Zampini 2673494a190aSStefano Zampini PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 2674494a190aSStefano Zampini PetscCall(PetscViewerASCIIGetStdout(comm, &viewer)); 2675494a190aSStefano Zampini PetscCall(PetscViewerASCIIGetTab(viewer, &tabs)); 2676494a190aSStefano Zampini PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel)); 2677494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Function -------------\n")); 2678494a190aSStefano Zampini if (!complete_print && !directionsprinted) { 2679494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Run with -snes_test_function_view and optionally -snes_test_function <threshold> to show difference\n")); 2680494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " of hand-coded and finite difference function entries greater than <threshold>.\n")); 2681494a190aSStefano Zampini } 2682494a190aSStefano Zampini if (!directionsprinted) { 2683494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Testing hand-coded Function, if (for double precision runs) ||F - Ffd||/||F|| is\n")); 2684494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " O(1.e-8), the hand-coded Function is probably correct.\n")); 2685494a190aSStefano Zampini directionsprinted = PETSC_TRUE; 2686494a190aSStefano Zampini } 2687494a190aSStefano Zampini if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format)); 2688494a190aSStefano Zampini 2689494a190aSStefano Zampini PetscCall(SNESGetSolution(snes, &x)); 2690494a190aSStefano Zampini PetscCall(VecDuplicate(x, &g1)); 2691494a190aSStefano Zampini PetscCall(VecDuplicate(x, &g2)); 2692494a190aSStefano Zampini PetscCall(VecDuplicate(x, &g3)); 2693494a190aSStefano Zampini PetscCall(SNESComputeFunction(snes, x, g1)); 2694494a190aSStefano Zampini PetscCall(SNESComputeFunction_FD(snes, x, g2)); 2695494a190aSStefano Zampini 2696494a190aSStefano Zampini PetscCall(VecNorm(g2, NORM_2, &fdnorm)); 2697494a190aSStefano Zampini PetscCall(VecNorm(g1, NORM_2, &hcnorm)); 2698494a190aSStefano Zampini PetscCall(VecNorm(g2, NORM_INFINITY, &fdmax)); 2699494a190aSStefano Zampini PetscCall(VecNorm(g1, NORM_INFINITY, &hcmax)); 2700494a190aSStefano Zampini PetscCall(VecDot(g1, g2, &dot)); 2701494a190aSStefano Zampini PetscCall(VecCopy(g1, g3)); 2702494a190aSStefano Zampini PetscCall(VecAXPY(g3, -1.0, g2)); 2703494a190aSStefano Zampini PetscCall(VecNorm(g3, NORM_2, &diffnorm)); 2704494a190aSStefano Zampini PetscCall(VecNorm(g3, NORM_INFINITY, &diffmax)); 2705494a190aSStefano 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)))); 2706494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " 2-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffnorm / PetscMax(hcnorm, fdnorm)), (double)diffnorm)); 2707494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " max-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffmax / PetscMax(hcmax, fdmax)), (double)diffmax)); 2708494a190aSStefano Zampini 2709494a190aSStefano Zampini if (complete_print) { 2710494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded function ----------\n")); 2711494a190aSStefano Zampini PetscCall(VecView(g1, mviewer)); 2712494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Finite difference function ----------\n")); 2713494a190aSStefano Zampini PetscCall(VecView(g2, mviewer)); 2714494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded minus finite-difference function ----------\n")); 2715494a190aSStefano Zampini PetscCall(VecView(g3, mviewer)); 2716494a190aSStefano Zampini } 2717494a190aSStefano Zampini PetscCall(VecDestroy(&g1)); 2718494a190aSStefano Zampini PetscCall(VecDestroy(&g2)); 2719494a190aSStefano Zampini PetscCall(VecDestroy(&g3)); 2720494a190aSStefano Zampini 2721494a190aSStefano Zampini if (complete_print) { 2722494a190aSStefano Zampini PetscCall(PetscViewerPopFormat(mviewer)); 2723494a190aSStefano Zampini PetscCall(PetscViewerDestroy(&mviewer)); 2724494a190aSStefano Zampini } 2725494a190aSStefano Zampini PetscCall(PetscViewerASCIISetTab(viewer, tabs)); 2726494a190aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2727494a190aSStefano Zampini } 2728494a190aSStefano Zampini 2729d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestJacobian(SNES snes) 2730d71ae5a4SJacob Faibussowitsch { 273112837594SBarry Smith Mat A, B, C, D, jacobian; 27324df93895SStefano Zampini Vec x = snes->vec_sol, f; 2733e885f1abSBarry Smith PetscReal nrm, gnorm; 273481e7118cSBarry Smith PetscReal threshold = 1.e-5; 27350e276705SLisandro Dalcin MatType mattype; 2736e885f1abSBarry Smith PetscInt m, n, M, N; 2737e885f1abSBarry Smith void *functx; 27382cd624f9SStefano Zampini PetscBool complete_print = PETSC_FALSE, threshold_print = PETSC_FALSE, test = PETSC_FALSE, flg, istranspose; 27393325ff46SBarry Smith PetscViewer viewer, mviewer; 2740e885f1abSBarry Smith MPI_Comm comm; 2741e885f1abSBarry Smith PetscInt tabs; 274212837594SBarry Smith static PetscBool directionsprinted = PETSC_FALSE; 27433325ff46SBarry Smith PetscViewerFormat format; 2744e885f1abSBarry Smith 2745e885f1abSBarry Smith PetscFunctionBegin; 2746d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)snes); 27479566063dSJacob Faibussowitsch PetscCall(PetscOptionsName("-snes_test_jacobian", "Compare hand-coded and finite difference Jacobians", "None", &test)); 27489566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-snes_test_jacobian", "Threshold for element difference between hand-coded and finite difference being meaningful", "None", threshold, &threshold, NULL)); 27499566063dSJacob Faibussowitsch PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display", "-snes_test_jacobian_view", "3.13", NULL)); 27504ead3382SBarry Smith PetscCall(PetscOptionsViewer("-snes_test_jacobian_view", "View difference between hand-coded and finite difference Jacobians element entries", "None", &mviewer, &format, &complete_print)); 27519566063dSJacob Faibussowitsch PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display_threshold", "-snes_test_jacobian", "3.13", "-snes_test_jacobian accepts an optional threshold (since v3.10)")); 27529566063dSJacob 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)); 2753d0609cedSBarry Smith PetscOptionsEnd(); 27543ba16761SJacob Faibussowitsch if (!test) PetscFunctionReturn(PETSC_SUCCESS); 2755e885f1abSBarry Smith 27569566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 27579566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(comm, &viewer)); 27589566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetTab(viewer, &tabs)); 27599566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel)); 27609566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Jacobian -------------\n")); 276112837594SBarry Smith if (!complete_print && !directionsprinted) { 27629566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Run with -snes_test_jacobian_view and optionally -snes_test_jacobian <threshold> to show difference\n")); 27639566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " of hand-coded and finite difference Jacobian entries greater than <threshold>.\n")); 276412837594SBarry Smith } 276512837594SBarry Smith if (!directionsprinted) { 27669566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Testing hand-coded Jacobian, if (for double precision runs) ||J - Jfd||_F/||J||_F is\n")); 27679566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " O(1.e-8), the hand-coded Jacobian is probably correct.\n")); 276812837594SBarry Smith directionsprinted = PETSC_TRUE; 2769e885f1abSBarry Smith } 27701baa6e33SBarry Smith if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format)); 2771e885f1abSBarry Smith 27729566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes->jacobian, MATMFFD, &flg)); 277312837594SBarry Smith if (!flg) jacobian = snes->jacobian; 277412837594SBarry Smith else jacobian = snes->jacobian_pre; 277512837594SBarry Smith 27764df93895SStefano Zampini if (!x) PetscCall(MatCreateVecs(jacobian, &x, NULL)); 27774df93895SStefano Zampini else PetscCall(PetscObjectReference((PetscObject)x)); 27789566063dSJacob Faibussowitsch PetscCall(VecDuplicate(x, &f)); 27794df93895SStefano Zampini 2780a82339d0SMatthew G. Knepley /* evaluate the function at this point because SNESComputeJacobianDefault() assumes that the function has been evaluated and put into snes->vec_func */ 27819566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, x, f)); 27829566063dSJacob Faibussowitsch PetscCall(VecDestroy(&f)); 27839566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESKSPTRANSPOSEONLY, &istranspose)); 278412837594SBarry Smith while (jacobian) { 27852cd624f9SStefano Zampini Mat JT = NULL, Jsave = NULL; 27862cd624f9SStefano Zampini 27872cd624f9SStefano Zampini if (istranspose) { 27889566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(jacobian, &JT)); 27892cd624f9SStefano Zampini Jsave = jacobian; 27902cd624f9SStefano Zampini jacobian = JT; 27912cd624f9SStefano Zampini } 27929566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)jacobian, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, "")); 279312837594SBarry Smith if (flg) { 279412837594SBarry Smith A = jacobian; 27959566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 279612837594SBarry Smith } else { 27979566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(jacobian, MATAIJ, &A)); 279812837594SBarry Smith } 2799e885f1abSBarry Smith 28009566063dSJacob Faibussowitsch PetscCall(MatGetType(A, &mattype)); 28019566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &M, &N)); 28029566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &m, &n)); 28039566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B)); 28049566063dSJacob Faibussowitsch PetscCall(MatSetType(B, mattype)); 28059566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, m, n, M, N)); 28069566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(B, A, A)); 28079566063dSJacob Faibussowitsch PetscCall(MatSetUp(B)); 28089566063dSJacob Faibussowitsch PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 2809e885f1abSBarry Smith 28109566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, NULL, &functx)); 28119566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobianDefault(snes, x, B, B, functx)); 281212837594SBarry Smith 28139566063dSJacob Faibussowitsch PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &D)); 28149566063dSJacob Faibussowitsch PetscCall(MatAYPX(D, -1.0, A, DIFFERENT_NONZERO_PATTERN)); 28159566063dSJacob Faibussowitsch PetscCall(MatNorm(D, NORM_FROBENIUS, &nrm)); 28169566063dSJacob Faibussowitsch PetscCall(MatNorm(A, NORM_FROBENIUS, &gnorm)); 28179566063dSJacob Faibussowitsch PetscCall(MatDestroy(&D)); 281812837594SBarry Smith if (!gnorm) gnorm = 1; /* just in case */ 28199566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " ||J - Jfd||_F/||J||_F = %g, ||J - Jfd||_F = %g\n", (double)(nrm / gnorm), (double)nrm)); 282012837594SBarry Smith 2821e885f1abSBarry Smith if (complete_print) { 28229566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded Jacobian ----------\n")); 28239566063dSJacob Faibussowitsch PetscCall(MatView(A, mviewer)); 28249566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Finite difference Jacobian ----------\n")); 28259566063dSJacob Faibussowitsch PetscCall(MatView(B, mviewer)); 2826e885f1abSBarry Smith } 2827e885f1abSBarry Smith 2828df10fb39SFande Kong if (threshold_print || complete_print) { 2829e885f1abSBarry Smith PetscInt Istart, Iend, *ccols, bncols, cncols, j, row; 2830e885f1abSBarry Smith PetscScalar *cvals; 2831e885f1abSBarry Smith const PetscInt *bcols; 2832e885f1abSBarry Smith const PetscScalar *bvals; 2833e885f1abSBarry Smith 28349566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C)); 28359566063dSJacob Faibussowitsch PetscCall(MatSetType(C, mattype)); 28369566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, m, n, M, N)); 28379566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(C, A, A)); 28389566063dSJacob Faibussowitsch PetscCall(MatSetUp(C)); 28399566063dSJacob Faibussowitsch PetscCall(MatSetOption(C, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 28400e276705SLisandro Dalcin 28419566063dSJacob Faibussowitsch PetscCall(MatAYPX(B, -1.0, A, DIFFERENT_NONZERO_PATTERN)); 28429566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(B, &Istart, &Iend)); 2843e885f1abSBarry Smith 2844e885f1abSBarry Smith for (row = Istart; row < Iend; row++) { 28459566063dSJacob Faibussowitsch PetscCall(MatGetRow(B, row, &bncols, &bcols, &bvals)); 28469566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(bncols, &ccols, bncols, &cvals)); 2847e885f1abSBarry Smith for (j = 0, cncols = 0; j < bncols; j++) { 284823a52b1dSBarry Smith if (PetscAbsScalar(bvals[j]) > threshold) { 2849e885f1abSBarry Smith ccols[cncols] = bcols[j]; 2850e885f1abSBarry Smith cvals[cncols] = bvals[j]; 2851e885f1abSBarry Smith cncols += 1; 2852e885f1abSBarry Smith } 2853e885f1abSBarry Smith } 285448a46eb9SPierre Jolivet if (cncols) PetscCall(MatSetValues(C, 1, &row, cncols, ccols, cvals, INSERT_VALUES)); 28559566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(B, row, &bncols, &bcols, &bvals)); 28569566063dSJacob Faibussowitsch PetscCall(PetscFree2(ccols, cvals)); 2857e885f1abSBarry Smith } 28589566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 28599566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 28609566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded minus finite-difference Jacobian with tolerance %g ----------\n", (double)threshold)); 28619566063dSJacob Faibussowitsch PetscCall(MatView(C, complete_print ? mviewer : viewer)); 28629566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C)); 2863e885f1abSBarry Smith } 28649566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A)); 28659566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 28669566063dSJacob Faibussowitsch PetscCall(MatDestroy(&JT)); 28672cd624f9SStefano Zampini if (Jsave) jacobian = Jsave; 286812837594SBarry Smith if (jacobian != snes->jacobian_pre) { 286912837594SBarry Smith jacobian = snes->jacobian_pre; 28709566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Jacobian for preconditioner -------------\n")); 28719371c9d4SSatish Balay } else jacobian = NULL; 287212837594SBarry Smith } 28739566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); 28741baa6e33SBarry Smith if (complete_print) PetscCall(PetscViewerPopFormat(mviewer)); 2875648c30bcSBarry Smith if (mviewer) PetscCall(PetscViewerDestroy(&mviewer)); 28769566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISetTab(viewer, tabs)); 28773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2878e885f1abSBarry Smith } 2879e885f1abSBarry Smith 288062fef451SLois Curfman McInnes /*@ 2881f6dfbefdSBarry Smith SNESComputeJacobian - Computes the Jacobian matrix that has been set with `SNESSetJacobian()`. 288262fef451SLois Curfman McInnes 2883c3339decSBarry Smith Collective 2884c7afd0dbSLois Curfman McInnes 288562fef451SLois Curfman McInnes Input Parameters: 2886f6dfbefdSBarry Smith + snes - the `SNES` context 2887e4094ef1SJacob Faibussowitsch - X - input vector 288862fef451SLois Curfman McInnes 288962fef451SLois Curfman McInnes Output Parameters: 2890c7afd0dbSLois Curfman McInnes + A - Jacobian matrix 2891420bcc1bSBarry Smith - B - optional matrix for building the preconditioner, usually the same as `A` 2892fee21e36SBarry Smith 2893e35cf81dSBarry Smith Options Database Keys: 289467b8a455SSatish Balay + -snes_lag_preconditioner <lag> - how often to rebuild preconditioner 289567b8a455SSatish Balay . -snes_lag_jacobian <lag> - how often to rebuild Jacobian 2896455a5933SJed 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. 2897455a5933SJed 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 2898693365a8SJed Brown . -snes_compare_explicit - Compare the computed Jacobian to the finite difference Jacobian and output the differences 2899693365a8SJed Brown . -snes_compare_explicit_draw - Compare the computed Jacobian to the finite difference Jacobian and draw the result 2900693365a8SJed Brown . -snes_compare_explicit_contour - Compare the computed Jacobian to the finite difference Jacobian and draw a contour plot with the result 29017addb90fSBarry Smith . -snes_compare_operator - Make the comparison options above use the operator instead of the matrix used to construct the preconditioner 290294d6a431SBarry Smith . -snes_compare_coloring - Compute the finite difference Jacobian using coloring and display norms of difference 2903a5b23f4aSJose E. Roman . -snes_compare_coloring_display - Compute the finite difference Jacobian using coloring and display verbose differences 2904c01495d3SJed Brown . -snes_compare_coloring_threshold - Display only those matrix entries that differ by more than a given threshold 2905dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_atol - Absolute tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold` 2906dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_rtol - Relative tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold` 2907a5b23f4aSJose E. Roman . -snes_compare_coloring_draw - Compute the finite difference Jacobian using coloring and draw differences 2908a5b23f4aSJose E. Roman - -snes_compare_coloring_draw_contour - Compute the finite difference Jacobian using coloring and show contours of matrices and differences 2909c01495d3SJed Brown 2910dc4c0fb0SBarry Smith Level: developer 2911dc4c0fb0SBarry Smith 2912f6dfbefdSBarry Smith Note: 291362fef451SLois Curfman McInnes Most users should not need to explicitly call this routine, as it 291462fef451SLois Curfman McInnes is used internally within the nonlinear solvers. 291562fef451SLois Curfman McInnes 2916420bcc1bSBarry Smith Developer Note: 2917dc4c0fb0SBarry 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 2918420bcc1bSBarry Smith with the `SNESType` of test that has been removed. 2919e885f1abSBarry Smith 29201cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetJacobian()`, `KSPSetOperators()`, `MatStructure`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()` 292162fef451SLois Curfman McInnes @*/ 2922d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeJacobian(SNES snes, Vec X, Mat A, Mat B) 2923d71ae5a4SJacob Faibussowitsch { 2924ace3abfcSBarry Smith PetscBool flag; 29256cab3a1bSJed Brown DM dm; 2926942e3340SBarry Smith DMSNES sdm; 2927e0e3a89bSBarry Smith KSP ksp; 29283a40ed3dSBarry Smith 29293a40ed3dSBarry Smith PetscFunctionBegin; 29300700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 29310700a824SBarry Smith PetscValidHeaderSpecific(X, VEC_CLASSID, 2); 2932c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, X, 2); 2933e0f629ddSJacob Faibussowitsch PetscCall(VecValidValues_Internal(X, 2, PETSC_TRUE)); 29349566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 29359566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 29363232da50SPeter Brune 293701c1178eSBarry Smith /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix-free */ 2938fe3ffe1eSBarry Smith if (snes->lagjacobian == -2) { 2939fe3ffe1eSBarry Smith snes->lagjacobian = -1; 2940f5af7f23SKarl Rupp 29419566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n")); 2942fe3ffe1eSBarry Smith } else if (snes->lagjacobian == -1) { 29439566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is -1\n")); 29449566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag)); 2945ebd3b9afSBarry Smith if (flag) { 29469566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 29479566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 2948ebd3b9afSBarry Smith } 29493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 295037ec4e1aSPeter Brune } else if (snes->lagjacobian > 1 && (snes->iter + snes->jac_iter) % snes->lagjacobian) { 295163a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagjacobian, snes->iter)); 29529566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag)); 2953ebd3b9afSBarry Smith if (flag) { 29549566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 29559566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 2956ebd3b9afSBarry Smith } 29573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2958e35cf81dSBarry Smith } 2959efd4aadfSBarry Smith if (snes->npc && snes->npcside == PC_LEFT) { 29609566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 29619566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 29623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2963d728fb7dSPeter Brune } 2964e35cf81dSBarry Smith 29659566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_JacobianEval, snes, X, A, B)); 29669566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(X)); 2967800f99ffSJeremy L Thompson { 2968800f99ffSJeremy L Thompson void *ctx; 29698434afd1SBarry Smith SNESJacobianFn *J; 2970800f99ffSJeremy L Thompson PetscCall(DMSNESGetJacobian(dm, &J, &ctx)); 2971800f99ffSJeremy L Thompson PetscCallBack("SNES callback Jacobian", (*J)(snes, X, A, B, ctx)); 2972800f99ffSJeremy L Thompson } 29739566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(X)); 29749566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_JacobianEval, snes, X, A, B)); 297528d58a37SPierre Jolivet 29767addb90fSBarry Smith /* attach latest linearization point to the matrix used to construct the preconditioner */ 29779566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)B, "__SNES_latest_X", (PetscObject)X)); 2978a8054027SBarry Smith 2979e0e3a89bSBarry Smith /* the next line ensures that snes->ksp exists */ 29809566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 29813b4f5425SBarry Smith if (snes->lagpreconditioner == -2) { 29829566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Rebuilding preconditioner exactly once since lag is -2\n")); 29839566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE)); 29843b4f5425SBarry Smith snes->lagpreconditioner = -1; 29853b4f5425SBarry Smith } else if (snes->lagpreconditioner == -1) { 29869566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is -1\n")); 29879566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE)); 298837ec4e1aSPeter Brune } else if (snes->lagpreconditioner > 1 && (snes->iter + snes->pre_iter) % snes->lagpreconditioner) { 298963a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagpreconditioner, snes->iter)); 29909566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE)); 2991d1e9a80fSBarry Smith } else { 29929566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Rebuilding preconditioner\n")); 29939566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE)); 2994a8054027SBarry Smith } 2995a8054027SBarry Smith 29964df93895SStefano Zampini /* monkey business to allow testing Jacobians in multilevel solvers. 29974df93895SStefano Zampini This is needed because the SNESTestXXX interface does not accept vectors and matrices */ 29984df93895SStefano Zampini { 29994df93895SStefano Zampini Vec xsave = snes->vec_sol; 30004df93895SStefano Zampini Mat jacobiansave = snes->jacobian; 30014df93895SStefano Zampini Mat jacobian_presave = snes->jacobian_pre; 30024df93895SStefano Zampini 30034df93895SStefano Zampini snes->vec_sol = X; 30044df93895SStefano Zampini snes->jacobian = A; 30054df93895SStefano Zampini snes->jacobian_pre = B; 3006494a190aSStefano Zampini PetscCall(SNESTestFunction(snes)); 30079566063dSJacob Faibussowitsch PetscCall(SNESTestJacobian(snes)); 3008494a190aSStefano Zampini 30094df93895SStefano Zampini snes->vec_sol = xsave; 30104df93895SStefano Zampini snes->jacobian = jacobiansave; 30114df93895SStefano Zampini snes->jacobian_pre = jacobian_presave; 30124df93895SStefano Zampini } 30134df93895SStefano Zampini 3014693365a8SJed Brown { 3015693365a8SJed Brown PetscBool flag = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_operator = PETSC_FALSE; 3016648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit", NULL, NULL, &flag)); 3017648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw", NULL, NULL, &flag_draw)); 3018648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw_contour", NULL, NULL, &flag_contour)); 3019648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_operator", NULL, NULL, &flag_operator)); 3020693365a8SJed Brown if (flag || flag_draw || flag_contour) { 30210298fd71SBarry Smith Mat Bexp_mine = NULL, Bexp, FDexp; 3022693365a8SJed Brown PetscViewer vdraw, vstdout; 30236b3a5b13SJed Brown PetscBool flg; 3024693365a8SJed Brown if (flag_operator) { 30259566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(A, MATAIJ, &Bexp_mine)); 3026693365a8SJed Brown Bexp = Bexp_mine; 3027693365a8SJed Brown } else { 30287addb90fSBarry Smith /* See if the matrix used to construct the preconditioner can be viewed and added directly */ 30299566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)B, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPIBAIJ, "")); 303094ab13aaSBarry Smith if (flg) Bexp = B; 3031693365a8SJed Brown else { 3032693365a8SJed Brown /* If the "preconditioning" matrix is itself MATSHELL or some other type without direct support */ 30339566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(B, MATAIJ, &Bexp_mine)); 3034693365a8SJed Brown Bexp = Bexp_mine; 3035693365a8SJed Brown } 3036693365a8SJed Brown } 30379566063dSJacob Faibussowitsch PetscCall(MatConvert(Bexp, MATSAME, MAT_INITIAL_MATRIX, &FDexp)); 30389566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobianDefault(snes, X, FDexp, FDexp, NULL)); 30399566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout)); 3040693365a8SJed Brown if (flag_draw || flag_contour) { 30419566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Explicit Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw)); 30429566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 30430298fd71SBarry Smith } else vdraw = NULL; 30449566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit %s\n", flag_operator ? "Jacobian" : "preconditioning Jacobian")); 30459566063dSJacob Faibussowitsch if (flag) PetscCall(MatView(Bexp, vstdout)); 30469566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(Bexp, vdraw)); 30479566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Finite difference Jacobian\n")); 30489566063dSJacob Faibussowitsch if (flag) PetscCall(MatView(FDexp, vstdout)); 30499566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(FDexp, vdraw)); 30509566063dSJacob Faibussowitsch PetscCall(MatAYPX(FDexp, -1.0, Bexp, SAME_NONZERO_PATTERN)); 30519566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian\n")); 30529566063dSJacob Faibussowitsch if (flag) PetscCall(MatView(FDexp, vstdout)); 3053693365a8SJed Brown if (vdraw) { /* Always use contour for the difference */ 30549566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 30559566063dSJacob Faibussowitsch PetscCall(MatView(FDexp, vdraw)); 30569566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(vdraw)); 3057693365a8SJed Brown } 30589566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw)); 30599566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&vdraw)); 30609566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bexp_mine)); 30619566063dSJacob Faibussowitsch PetscCall(MatDestroy(&FDexp)); 3062693365a8SJed Brown } 3063693365a8SJed Brown } 30644c30e9fbSJed Brown { 30656719d8e4SJed Brown PetscBool flag = PETSC_FALSE, flag_display = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_threshold = PETSC_FALSE; 30666719d8e4SJed Brown PetscReal threshold_atol = PETSC_SQRT_MACHINE_EPSILON, threshold_rtol = 10 * PETSC_SQRT_MACHINE_EPSILON; 3067648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring", NULL, NULL, &flag)); 3068648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_display", NULL, NULL, &flag_display)); 3069648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw", NULL, NULL, &flag_draw)); 3070648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw_contour", NULL, NULL, &flag_contour)); 3071648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold", NULL, NULL, &flag_threshold)); 307227b0f280SBarry Smith if (flag_threshold) { 30739566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_rtol", &threshold_rtol, NULL)); 30749566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_atol", &threshold_atol, NULL)); 307527b0f280SBarry Smith } 30766719d8e4SJed Brown if (flag || flag_display || flag_draw || flag_contour || flag_threshold) { 30774c30e9fbSJed Brown Mat Bfd; 30784c30e9fbSJed Brown PetscViewer vdraw, vstdout; 3079335efc43SPeter Brune MatColoring coloring; 30804c30e9fbSJed Brown ISColoring iscoloring; 30814c30e9fbSJed Brown MatFDColoring matfdcoloring; 30828434afd1SBarry Smith SNESFunctionFn *func; 30834c30e9fbSJed Brown void *funcctx; 30846719d8e4SJed Brown PetscReal norm1, norm2, normmax; 30854c30e9fbSJed Brown 30869566063dSJacob Faibussowitsch PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &Bfd)); 30879566063dSJacob Faibussowitsch PetscCall(MatColoringCreate(Bfd, &coloring)); 30889566063dSJacob Faibussowitsch PetscCall(MatColoringSetType(coloring, MATCOLORINGSL)); 30899566063dSJacob Faibussowitsch PetscCall(MatColoringSetFromOptions(coloring)); 30909566063dSJacob Faibussowitsch PetscCall(MatColoringApply(coloring, &iscoloring)); 30919566063dSJacob Faibussowitsch PetscCall(MatColoringDestroy(&coloring)); 30929566063dSJacob Faibussowitsch PetscCall(MatFDColoringCreate(Bfd, iscoloring, &matfdcoloring)); 30939566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFromOptions(matfdcoloring)); 30949566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetUp(Bfd, iscoloring, matfdcoloring)); 30959566063dSJacob Faibussowitsch PetscCall(ISColoringDestroy(&iscoloring)); 30964c30e9fbSJed Brown 30974c30e9fbSJed Brown /* This method of getting the function is currently unreliable since it doesn't work for DM local functions. */ 30989566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, &func, &funcctx)); 30999566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFunction(matfdcoloring, (PetscErrorCode (*)(void))func, funcctx)); 31009566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)matfdcoloring, ((PetscObject)snes)->prefix)); 31019566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)matfdcoloring, "coloring_")); 31029566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFromOptions(matfdcoloring)); 31039566063dSJacob Faibussowitsch PetscCall(MatFDColoringApply(Bfd, matfdcoloring, X, snes)); 31049566063dSJacob Faibussowitsch PetscCall(MatFDColoringDestroy(&matfdcoloring)); 31054c30e9fbSJed Brown 31069566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout)); 31074c30e9fbSJed Brown if (flag_draw || flag_contour) { 31089566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Colored Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw)); 31099566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 31100298fd71SBarry Smith } else vdraw = NULL; 31119566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit preconditioning Jacobian\n")); 31129566063dSJacob Faibussowitsch if (flag_display) PetscCall(MatView(B, vstdout)); 31139566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(B, vdraw)); 31149566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Colored Finite difference Jacobian\n")); 31159566063dSJacob Faibussowitsch if (flag_display) PetscCall(MatView(Bfd, vstdout)); 31169566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(Bfd, vdraw)); 31179566063dSJacob Faibussowitsch PetscCall(MatAYPX(Bfd, -1.0, B, SAME_NONZERO_PATTERN)); 31189566063dSJacob Faibussowitsch PetscCall(MatNorm(Bfd, NORM_1, &norm1)); 31199566063dSJacob Faibussowitsch PetscCall(MatNorm(Bfd, NORM_FROBENIUS, &norm2)); 31209566063dSJacob Faibussowitsch PetscCall(MatNorm(Bfd, NORM_MAX, &normmax)); 31219566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian, norm1=%g normFrob=%g normmax=%g\n", (double)norm1, (double)norm2, (double)normmax)); 31229566063dSJacob Faibussowitsch if (flag_display) PetscCall(MatView(Bfd, vstdout)); 31234c30e9fbSJed Brown if (vdraw) { /* Always use contour for the difference */ 31249566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 31259566063dSJacob Faibussowitsch PetscCall(MatView(Bfd, vdraw)); 31269566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(vdraw)); 31274c30e9fbSJed Brown } 31289566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw)); 31296719d8e4SJed Brown 31306719d8e4SJed Brown if (flag_threshold) { 31316719d8e4SJed Brown PetscInt bs, rstart, rend, i; 31329566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(B, &bs)); 31339566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(B, &rstart, &rend)); 31346719d8e4SJed Brown for (i = rstart; i < rend; i++) { 31356719d8e4SJed Brown const PetscScalar *ba, *ca; 31366719d8e4SJed Brown const PetscInt *bj, *cj; 31376719d8e4SJed Brown PetscInt bn, cn, j, maxentrycol = -1, maxdiffcol = -1, maxrdiffcol = -1; 31386719d8e4SJed Brown PetscReal maxentry = 0, maxdiff = 0, maxrdiff = 0; 31399566063dSJacob Faibussowitsch PetscCall(MatGetRow(B, i, &bn, &bj, &ba)); 31409566063dSJacob Faibussowitsch PetscCall(MatGetRow(Bfd, i, &cn, &cj, &ca)); 31415f80ce2aSJacob Faibussowitsch PetscCheck(bn == cn, ((PetscObject)A)->comm, PETSC_ERR_PLIB, "Unexpected different nonzero pattern in -snes_compare_coloring_threshold"); 31426719d8e4SJed Brown for (j = 0; j < bn; j++) { 31436719d8e4SJed Brown PetscReal rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j])); 31446719d8e4SJed Brown if (PetscAbsScalar(ba[j]) > PetscAbs(maxentry)) { 31456719d8e4SJed Brown maxentrycol = bj[j]; 31466719d8e4SJed Brown maxentry = PetscRealPart(ba[j]); 31476719d8e4SJed Brown } 31486719d8e4SJed Brown if (PetscAbsScalar(ca[j]) > PetscAbs(maxdiff)) { 31496719d8e4SJed Brown maxdiffcol = bj[j]; 31506719d8e4SJed Brown maxdiff = PetscRealPart(ca[j]); 31516719d8e4SJed Brown } 31526719d8e4SJed Brown if (rdiff > maxrdiff) { 31536719d8e4SJed Brown maxrdiffcol = bj[j]; 31546719d8e4SJed Brown maxrdiff = rdiff; 31556719d8e4SJed Brown } 31566719d8e4SJed Brown } 31576719d8e4SJed Brown if (maxrdiff > 1) { 315863a3b9bcSJacob 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)); 31596719d8e4SJed Brown for (j = 0; j < bn; j++) { 31606719d8e4SJed Brown PetscReal rdiff; 31616719d8e4SJed Brown rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j])); 316248a46eb9SPierre Jolivet if (rdiff > 1) PetscCall(PetscViewerASCIIPrintf(vstdout, " (%" PetscInt_FMT ",%g:%g)", bj[j], (double)PetscRealPart(ba[j]), (double)PetscRealPart(ca[j]))); 31636719d8e4SJed Brown } 316463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "\n")); 31656719d8e4SJed Brown } 31669566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(B, i, &bn, &bj, &ba)); 31679566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(Bfd, i, &cn, &cj, &ca)); 31686719d8e4SJed Brown } 31696719d8e4SJed Brown } 31709566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&vdraw)); 31719566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bfd)); 31724c30e9fbSJed Brown } 31734c30e9fbSJed Brown } 31743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 31759b94acceSBarry Smith } 31769b94acceSBarry Smith 31779b94acceSBarry Smith /*@C 31789b94acceSBarry Smith SNESSetJacobian - Sets the function to compute Jacobian as well as the 3179044dda88SLois Curfman McInnes location to store the matrix. 31809b94acceSBarry Smith 3181c3339decSBarry Smith Logically Collective 3182c7afd0dbSLois Curfman McInnes 31839b94acceSBarry Smith Input Parameters: 3184f6dfbefdSBarry Smith + snes - the `SNES` context 3185e5d3d808SBarry Smith . Amat - the matrix that defines the (approximate) Jacobian 3186dc4c0fb0SBarry Smith . Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`. 31878434afd1SBarry Smith . J - Jacobian evaluation routine (if `NULL` then `SNES` retains any previously set value), see `SNESJacobianFn` for details 3188c7afd0dbSLois Curfman McInnes - ctx - [optional] user-defined context for private data for the 3189dc4c0fb0SBarry Smith Jacobian evaluation routine (may be `NULL`) (if `NULL` then `SNES` retains any previously set value) 3190dc4c0fb0SBarry Smith 3191dc4c0fb0SBarry Smith Level: beginner 31929b94acceSBarry Smith 31939b94acceSBarry Smith Notes: 3194dc4c0fb0SBarry Smith If the `Amat` matrix and `Pmat` matrix are different you must call `MatAssemblyBegin()`/`MatAssemblyEnd()` on 319516913363SBarry Smith each matrix. 319616913363SBarry Smith 3197dc4c0fb0SBarry Smith If you know the operator `Amat` has a null space you can use `MatSetNullSpace()` and `MatSetTransposeNullSpace()` to supply the null 3198dc4c0fb0SBarry Smith space to `Amat` and the `KSP` solvers will automatically use that null space as needed during the solution process. 3199895c21f2SBarry Smith 3200dc4c0fb0SBarry Smith If using `SNESComputeJacobianDefaultColor()` to assemble a Jacobian, the `ctx` argument 3201f6dfbefdSBarry Smith must be a `MatFDColoring`. 3202a8a26c1eSJed Brown 3203c3cc8fd1SJed Brown Other defect-correction schemes can be used by computing a different matrix in place of the Jacobian. One common 3204f6dfbefdSBarry Smith example is to use the "Picard linearization" which only differentiates through the highest order parts of each term using `SNESSetPicard()` 3205c3cc8fd1SJed Brown 32061cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSPSetOperators()`, `SNESSetFunction()`, `MatMFFDComputeJacobian()`, `SNESComputeJacobianDefaultColor()`, `MatStructure`, 32078434afd1SBarry Smith `SNESSetPicard()`, `SNESJacobianFn`, `SNESFunctionFn` 32089b94acceSBarry Smith @*/ 32098434afd1SBarry Smith PetscErrorCode SNESSetJacobian(SNES snes, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx) 3210d71ae5a4SJacob Faibussowitsch { 32116cab3a1bSJed Brown DM dm; 32123a7fca6bSBarry Smith 32133a40ed3dSBarry Smith PetscFunctionBegin; 32140700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3215e5d3d808SBarry Smith if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2); 3216e5d3d808SBarry Smith if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3); 3217e5d3d808SBarry Smith if (Amat) PetscCheckSameComm(snes, 1, Amat, 2); 3218e5d3d808SBarry Smith if (Pmat) PetscCheckSameComm(snes, 1, Pmat, 3); 32199566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 32209566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, J, ctx)); 3221e5d3d808SBarry Smith if (Amat) { 32229566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)Amat)); 32239566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian)); 3224f5af7f23SKarl Rupp 3225e5d3d808SBarry Smith snes->jacobian = Amat; 32263a7fca6bSBarry Smith } 3227e5d3d808SBarry Smith if (Pmat) { 32289566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)Pmat)); 32299566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian_pre)); 3230f5af7f23SKarl Rupp 3231e5d3d808SBarry Smith snes->jacobian_pre = Pmat; 32323a7fca6bSBarry Smith } 32333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 32349b94acceSBarry Smith } 323562fef451SLois Curfman McInnes 3236c2aafc4cSSatish Balay /*@C 3237b4fd4287SBarry Smith SNESGetJacobian - Returns the Jacobian matrix and optionally the user 3238b4fd4287SBarry Smith provided context for evaluating the Jacobian. 3239b4fd4287SBarry Smith 3240420bcc1bSBarry Smith Not Collective, but `Mat` object will be parallel if `SNES` is 3241c7afd0dbSLois Curfman McInnes 3242b4fd4287SBarry Smith Input Parameter: 3243b4fd4287SBarry Smith . snes - the nonlinear solver context 3244b4fd4287SBarry Smith 3245b4fd4287SBarry Smith Output Parameters: 3246dc4c0fb0SBarry Smith + Amat - location to stash (approximate) Jacobian matrix (or `NULL`) 3247dc4c0fb0SBarry Smith . Pmat - location to stash matrix used to compute the preconditioner (or `NULL`) 32488434afd1SBarry Smith . J - location to put Jacobian function (or `NULL`), for calling sequence see `SNESJacobianFn` 3249dc4c0fb0SBarry Smith - ctx - location to stash Jacobian ctx (or `NULL`) 3250fee21e36SBarry Smith 325136851e7fSLois Curfman McInnes Level: advanced 325236851e7fSLois Curfman McInnes 32538434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `Mat`, `SNESSetJacobian()`, `SNESComputeJacobian()`, `SNESJacobianFn`, `SNESGetFunction()` 3254b4fd4287SBarry Smith @*/ 32558434afd1SBarry Smith PetscErrorCode SNESGetJacobian(SNES snes, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx) 3256d71ae5a4SJacob Faibussowitsch { 32576cab3a1bSJed Brown DM dm; 32586cab3a1bSJed Brown 32593a40ed3dSBarry Smith PetscFunctionBegin; 32600700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3261e5d3d808SBarry Smith if (Amat) *Amat = snes->jacobian; 3262e5d3d808SBarry Smith if (Pmat) *Pmat = snes->jacobian_pre; 32639566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 3264800f99ffSJeremy L Thompson PetscCall(DMSNESGetJacobian(dm, J, ctx)); 32653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3266b4fd4287SBarry Smith } 3267b4fd4287SBarry Smith 3268d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetDefaultComputeJacobian(SNES snes) 3269d71ae5a4SJacob Faibussowitsch { 327058b371f3SBarry Smith DM dm; 327158b371f3SBarry Smith DMSNES sdm; 327258b371f3SBarry Smith 327358b371f3SBarry Smith PetscFunctionBegin; 32749566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 32759566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 327658b371f3SBarry Smith if (!sdm->ops->computejacobian && snes->jacobian_pre) { 327758b371f3SBarry Smith DM dm; 327858b371f3SBarry Smith PetscBool isdense, ismf; 327958b371f3SBarry Smith 32809566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 32819566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &isdense, MATSEQDENSE, MATMPIDENSE, MATDENSE, NULL)); 32829566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &ismf, MATMFFD, MATSHELL, NULL)); 328358b371f3SBarry Smith if (isdense) { 32849566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefault, NULL)); 328558b371f3SBarry Smith } else if (!ismf) { 32869566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefaultColor, NULL)); 328758b371f3SBarry Smith } 328858b371f3SBarry Smith } 32893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 329058b371f3SBarry Smith } 329158b371f3SBarry Smith 32929b94acceSBarry Smith /*@ 32939b94acceSBarry Smith SNESSetUp - Sets up the internal data structures for the later use 32940b4b7b1cSBarry Smith of a nonlinear solver `SNESSolve()`. 32959b94acceSBarry Smith 3296c3339decSBarry Smith Collective 3297fee21e36SBarry Smith 32982fe279fdSBarry Smith Input Parameter: 3299f6dfbefdSBarry Smith . snes - the `SNES` context 3300c7afd0dbSLois Curfman McInnes 3301dc4c0fb0SBarry Smith Level: advanced 3302dc4c0fb0SBarry Smith 3303f6dfbefdSBarry Smith Note: 33040b4b7b1cSBarry Smith For basic use of the `SNES` solvers the user does not need to explicitly call 3305f6dfbefdSBarry Smith `SNESSetUp()`, since these actions will automatically occur during 3306f6dfbefdSBarry Smith the call to `SNESSolve()`. However, if one wishes to control this 3307f6dfbefdSBarry Smith phase separately, `SNESSetUp()` should be called after `SNESCreate()` 3308f6dfbefdSBarry Smith and optional routines of the form SNESSetXXX(), but before `SNESSolve()`. 3309272ac6f2SLois Curfman McInnes 33100b4b7b1cSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`, `SNESDestroy()`, `SNESSetFromOptions()` 33119b94acceSBarry Smith @*/ 3312d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUp(SNES snes) 3313d71ae5a4SJacob Faibussowitsch { 33146cab3a1bSJed Brown DM dm; 3315942e3340SBarry Smith DMSNES sdm; 3316c35f09e5SBarry Smith SNESLineSearch linesearch, pclinesearch; 33176e2a1849SPeter Brune void *lsprectx, *lspostctx; 33189b5c1c08SStefano Zampini PetscBool mf_operator, mf; 33199b5c1c08SStefano Zampini Vec f, fpc; 33209b5c1c08SStefano Zampini void *funcctx; 33219b5c1c08SStefano Zampini void *jacctx, *appctx; 33229b5c1c08SStefano Zampini Mat j, jpre; 33236b2b7091SBarry Smith PetscErrorCode (*precheck)(SNESLineSearch, Vec, Vec, PetscBool *, void *); 33246b2b7091SBarry Smith PetscErrorCode (*postcheck)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *); 33258434afd1SBarry Smith SNESFunctionFn *func; 33268434afd1SBarry Smith SNESJacobianFn *jac; 33273a40ed3dSBarry Smith 33283a40ed3dSBarry Smith PetscFunctionBegin; 33290700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 33303ba16761SJacob Faibussowitsch if (snes->setupcalled) PetscFunctionReturn(PETSC_SUCCESS); 3331fc8bc0e3SRichard Tran Mills PetscCall(PetscLogEventBegin(SNES_SetUp, snes, 0, 0, 0)); 33329b94acceSBarry Smith 333348a46eb9SPierre Jolivet if (!((PetscObject)snes)->type_name) PetscCall(SNESSetType(snes, SNESNEWTONLS)); 333485385478SLisandro Dalcin 33359566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &snes->vec_func, NULL, NULL)); 333658c9b817SLisandro Dalcin 33379566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 33389566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 33399566063dSJacob Faibussowitsch PetscCall(SNESSetDefaultComputeJacobian(snes)); 334058b371f3SBarry Smith 334148a46eb9SPierre Jolivet if (!snes->vec_func) PetscCall(DMCreateGlobalVector(dm, &snes->vec_func)); 3342efd51863SBarry Smith 334348a46eb9SPierre Jolivet if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 3344b710008aSBarry Smith 3345d8d34be6SBarry Smith if (snes->linesearch) { 33469566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 33479566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetFunction(snes->linesearch, SNESComputeFunction)); 3348d8d34be6SBarry Smith } 33499e764e56SPeter Brune 33509b5c1c08SStefano Zampini PetscCall(SNESGetUseMatrixFree(snes, &mf_operator, &mf)); 3351b552625fSStefano Zampini if (snes->npc && snes->npcside == PC_LEFT) { 3352172a4300SPeter Brune snes->mf = PETSC_TRUE; 3353172a4300SPeter Brune snes->mf_operator = PETSC_FALSE; 3354172a4300SPeter Brune } 3355d8f46077SPeter Brune 3356efd4aadfSBarry Smith if (snes->npc) { 33576e2a1849SPeter Brune /* copy the DM over */ 33589566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 33599566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes->npc, dm)); 33606e2a1849SPeter Brune 33619566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &f, &func, &funcctx)); 33629566063dSJacob Faibussowitsch PetscCall(VecDuplicate(f, &fpc)); 33639566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes->npc, fpc, func, funcctx)); 33649566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, &j, &jpre, &jac, &jacctx)); 33659566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes->npc, j, jpre, jac, jacctx)); 33669566063dSJacob Faibussowitsch PetscCall(SNESGetApplicationContext(snes, &appctx)); 33679566063dSJacob Faibussowitsch PetscCall(SNESSetApplicationContext(snes->npc, appctx)); 33689b5c1c08SStefano Zampini PetscCall(SNESSetUseMatrixFree(snes->npc, mf_operator, mf)); 33699566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fpc)); 33706e2a1849SPeter Brune 33716e2a1849SPeter Brune /* copy the function pointers over */ 33729566063dSJacob Faibussowitsch PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)snes->npc)); 33736e2a1849SPeter Brune 33746e2a1849SPeter Brune /* default to 1 iteration */ 33759566063dSJacob Faibussowitsch PetscCall(SNESSetTolerances(snes->npc, 0.0, 0.0, 0.0, 1, snes->npc->max_funcs)); 3376efd4aadfSBarry Smith if (snes->npcside == PC_RIGHT) { 33779566063dSJacob Faibussowitsch PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_FINAL_ONLY)); 3378a9936a0cSPeter Brune } else { 33799566063dSJacob Faibussowitsch PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_NONE)); 3380a9936a0cSPeter Brune } 33819566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes->npc)); 33826e2a1849SPeter Brune 33836e2a1849SPeter Brune /* copy the line search context over */ 3384d8d34be6SBarry Smith if (snes->linesearch && snes->npc->linesearch) { 33859566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &linesearch)); 33869566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes->npc, &pclinesearch)); 33879566063dSJacob Faibussowitsch PetscCall(SNESLineSearchGetPreCheck(linesearch, &precheck, &lsprectx)); 33889566063dSJacob Faibussowitsch PetscCall(SNESLineSearchGetPostCheck(linesearch, &postcheck, &lspostctx)); 33899566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetPreCheck(pclinesearch, precheck, lsprectx)); 33909566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetPostCheck(pclinesearch, postcheck, lspostctx)); 33919566063dSJacob Faibussowitsch PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch)); 33926e2a1849SPeter Brune } 3393d8d34be6SBarry Smith } 33941baa6e33SBarry Smith if (snes->mf) PetscCall(SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version)); 3395835f2295SStefano Zampini if (snes->ops->usercompute && !snes->ctx) PetscCallBack("SNES callback compute application context", (*snes->ops->usercompute)(snes, &snes->ctx)); 33966e2a1849SPeter Brune 339737ec4e1aSPeter Brune snes->jac_iter = 0; 339837ec4e1aSPeter Brune snes->pre_iter = 0; 339937ec4e1aSPeter Brune 3400dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, setup); 340158c9b817SLisandro Dalcin 34029566063dSJacob Faibussowitsch PetscCall(SNESSetDefaultComputeJacobian(snes)); 340358b371f3SBarry Smith 3404b552625fSStefano Zampini if (snes->npc && snes->npcside == PC_LEFT) { 34056c67d002SPeter Brune if (snes->functype == SNES_FUNCTION_PRECONDITIONED) { 3406d8d34be6SBarry Smith if (snes->linesearch) { 34079566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &linesearch)); 34089566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunctionDefaultNPC)); 34096c67d002SPeter Brune } 34106c67d002SPeter Brune } 3411d8d34be6SBarry Smith } 3412fc8bc0e3SRichard Tran Mills PetscCall(PetscLogEventEnd(SNES_SetUp, snes, 0, 0, 0)); 34137aaed0d8SBarry Smith snes->setupcalled = PETSC_TRUE; 34143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 34159b94acceSBarry Smith } 34169b94acceSBarry Smith 341737596af1SLisandro Dalcin /*@ 34180b4b7b1cSBarry 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 341937596af1SLisandro Dalcin 3420c3339decSBarry Smith Collective 342137596af1SLisandro Dalcin 342237596af1SLisandro Dalcin Input Parameter: 34230b4b7b1cSBarry Smith . snes - the nonlinear iterative solver context obtained from `SNESCreate()` 342437596af1SLisandro Dalcin 3425d25893d9SBarry Smith Level: intermediate 3426d25893d9SBarry Smith 342795452b02SPatrick Sanan Notes: 34280b4b7b1cSBarry Smith Any options set on the `SNES` object, including those set with `SNESSetFromOptions()` remain. 34290b4b7b1cSBarry Smith 3430f6dfbefdSBarry Smith Call this if you wish to reuse a `SNES` but with different size vectors 343137596af1SLisandro Dalcin 3432f6dfbefdSBarry Smith Also calls the application context destroy routine set with `SNESSetComputeApplicationContext()` 3433f6dfbefdSBarry Smith 34341cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESDestroy()`, `SNESCreate()`, `SNESSetUp()`, `SNESSolve()` 343537596af1SLisandro Dalcin @*/ 3436d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESReset(SNES snes) 3437d71ae5a4SJacob Faibussowitsch { 343837596af1SLisandro Dalcin PetscFunctionBegin; 343937596af1SLisandro Dalcin PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 344049abdd8aSBarry Smith if (snes->ops->ctxdestroy && snes->ctx) { 3441835f2295SStefano Zampini PetscCallBack("SNES callback destroy application context", (*snes->ops->ctxdestroy)(&snes->ctx)); 344249abdd8aSBarry Smith snes->ctx = NULL; 3443d25893d9SBarry Smith } 34441baa6e33SBarry Smith if (snes->npc) PetscCall(SNESReset(snes->npc)); 34458a23116dSBarry Smith 3446dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, reset); 34471baa6e33SBarry Smith if (snes->ksp) PetscCall(KSPReset(snes->ksp)); 34489e764e56SPeter Brune 34491baa6e33SBarry Smith if (snes->linesearch) PetscCall(SNESLineSearchReset(snes->linesearch)); 34509e764e56SPeter Brune 34519566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_rhs)); 34529566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol)); 34539566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol_update)); 34549566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_func)); 34559566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian)); 34569566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian_pre)); 34579566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->picard)); 34589566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(snes->nwork, &snes->work)); 34599566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(snes->nvwork, &snes->vwork)); 3460f5af7f23SKarl Rupp 346140fdac6aSLawrence Mitchell snes->alwayscomputesfinalresidual = PETSC_FALSE; 346240fdac6aSLawrence Mitchell 346337596af1SLisandro Dalcin snes->nwork = snes->nvwork = 0; 346437596af1SLisandro Dalcin snes->setupcalled = PETSC_FALSE; 34653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 346637596af1SLisandro Dalcin } 346737596af1SLisandro Dalcin 346852baeb72SSatish Balay /*@ 346936d43d94SBarry Smith SNESConvergedReasonViewCancel - Clears all the reason view functions for a `SNES` object provided with `SNESConvergedReasonViewSet()` also 347036d43d94SBarry Smith removes the default viewer. 3471c4421ceaSFande Kong 3472c3339decSBarry Smith Collective 3473c4421ceaSFande Kong 3474c4421ceaSFande Kong Input Parameter: 34750b4b7b1cSBarry Smith . snes - the nonlinear iterative solver context obtained from `SNESCreate()` 3476c4421ceaSFande Kong 3477c4421ceaSFande Kong Level: intermediate 3478c4421ceaSFande Kong 3479420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESReset()`, `SNESConvergedReasonViewSet()` 3480c4421ceaSFande Kong @*/ 3481d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewCancel(SNES snes) 3482d71ae5a4SJacob Faibussowitsch { 3483c4421ceaSFande Kong PetscInt i; 3484c4421ceaSFande Kong 3485c4421ceaSFande Kong PetscFunctionBegin; 3486c4421ceaSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3487c4421ceaSFande Kong for (i = 0; i < snes->numberreasonviews; i++) { 348848a46eb9SPierre Jolivet if (snes->reasonviewdestroy[i]) PetscCall((*snes->reasonviewdestroy[i])(&snes->reasonviewcontext[i])); 3489c4421ceaSFande Kong } 3490c4421ceaSFande Kong snes->numberreasonviews = 0; 3491648c30bcSBarry Smith PetscCall(PetscViewerDestroy(&snes->convergedreasonviewer)); 34923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3493c4421ceaSFande Kong } 3494c4421ceaSFande Kong 34950764c050SBarry Smith /*@ 34969b94acceSBarry Smith SNESDestroy - Destroys the nonlinear solver context that was created 3497f6dfbefdSBarry Smith with `SNESCreate()`. 34989b94acceSBarry Smith 3499c3339decSBarry Smith Collective 3500c7afd0dbSLois Curfman McInnes 35019b94acceSBarry Smith Input Parameter: 3502f6dfbefdSBarry Smith . snes - the `SNES` context 35039b94acceSBarry Smith 350436851e7fSLois Curfman McInnes Level: beginner 350536851e7fSLois Curfman McInnes 35061cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()` 35079b94acceSBarry Smith @*/ 3508d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESDestroy(SNES *snes) 3509d71ae5a4SJacob Faibussowitsch { 351092e852f7SPablo Brubeck DM dm; 351192e852f7SPablo Brubeck 35123a40ed3dSBarry Smith PetscFunctionBegin; 35133ba16761SJacob Faibussowitsch if (!*snes) PetscFunctionReturn(PETSC_SUCCESS); 3514f4f49eeaSPierre Jolivet PetscValidHeaderSpecific(*snes, SNES_CLASSID, 1); 3515f4f49eeaSPierre Jolivet if (--((PetscObject)*snes)->refct > 0) { 35169371c9d4SSatish Balay *snes = NULL; 35173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 35189371c9d4SSatish Balay } 3519d4bb536fSBarry Smith 3520f4f49eeaSPierre Jolivet PetscCall(SNESReset(*snes)); 35219566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&(*snes)->npc)); 35226b8b9a38SLisandro Dalcin 3523e04113cfSBarry Smith /* if memory was published with SAWs then destroy it */ 35249566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsViewOff((PetscObject)*snes)); 3525f4f49eeaSPierre Jolivet PetscTryTypeMethod(*snes, destroy); 35266d4c513bSLisandro Dalcin 352792e852f7SPablo Brubeck dm = (*snes)->dm; 352892e852f7SPablo Brubeck while (dm) { 352992e852f7SPablo Brubeck PetscCall(DMCoarsenHookRemove(dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, *snes)); 353092e852f7SPablo Brubeck PetscCall(DMGetCoarseDM(dm, &dm)); 353192e852f7SPablo Brubeck } 353292e852f7SPablo Brubeck 35339566063dSJacob Faibussowitsch PetscCall(DMDestroy(&(*snes)->dm)); 35349566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&(*snes)->ksp)); 35359566063dSJacob Faibussowitsch PetscCall(SNESLineSearchDestroy(&(*snes)->linesearch)); 35366b8b9a38SLisandro Dalcin 35379566063dSJacob Faibussowitsch PetscCall(PetscFree((*snes)->kspconvctx)); 353848a46eb9SPierre Jolivet if ((*snes)->ops->convergeddestroy) PetscCall((*(*snes)->ops->convergeddestroy)((*snes)->cnvP)); 353948a46eb9SPierre Jolivet if ((*snes)->conv_hist_alloc) PetscCall(PetscFree2((*snes)->conv_hist, (*snes)->conv_hist_its)); 3540f4f49eeaSPierre Jolivet PetscCall(SNESMonitorCancel(*snes)); 3541f4f49eeaSPierre Jolivet PetscCall(SNESConvergedReasonViewCancel(*snes)); 35429566063dSJacob Faibussowitsch PetscCall(PetscHeaderDestroy(snes)); 35433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 35449b94acceSBarry Smith } 35459b94acceSBarry Smith 35469b94acceSBarry Smith /* ----------- Routines to set solver parameters ---------- */ 35479b94acceSBarry Smith 3548a8054027SBarry Smith /*@ 35490b4b7b1cSBarry Smith SNESSetLagPreconditioner - Sets when the preconditioner is rebuilt in the nonlinear solve `SNESSolve()`. 3550a8054027SBarry Smith 3551c3339decSBarry Smith Logically Collective 3552a8054027SBarry Smith 3553a8054027SBarry Smith Input Parameters: 3554f6dfbefdSBarry Smith + snes - the `SNES` context 3555d8e291bfSBarry Smith - lag - 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time 35563b4f5425SBarry Smith the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that 3557a8054027SBarry Smith 3558a8054027SBarry Smith Options Database Keys: 3559420bcc1bSBarry Smith + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple `SNESSolve()` 35603d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 3561420bcc1bSBarry Smith . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple `SNESSolve()` 35623d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 3563a8054027SBarry Smith 3564dc4c0fb0SBarry Smith Level: intermediate 3565dc4c0fb0SBarry Smith 3566420bcc1bSBarry Smith Notes: 3567a8054027SBarry Smith The default is 1 3568420bcc1bSBarry Smith 3569f6dfbefdSBarry Smith The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagPreconditionerPersists()` was called 3570d8e291bfSBarry Smith 3571f6dfbefdSBarry Smith `SNESSetLagPreconditionerPersists()` allows using the same uniform lagging (for example every second linear solve) across multiple nonlinear solves. 3572a8054027SBarry Smith 35733201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetLagPreconditionerPersists()`, 3574f6dfbefdSBarry Smith `SNESSetLagJacobianPersists()`, `SNES`, `SNESSolve()` 3575a8054027SBarry Smith @*/ 3576d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditioner(SNES snes, PetscInt lag) 3577d71ae5a4SJacob Faibussowitsch { 3578a8054027SBarry Smith PetscFunctionBegin; 35790700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 35805f80ce2aSJacob Faibussowitsch PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater"); 35815f80ce2aSJacob Faibussowitsch PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0"); 3582c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, lag, 2); 3583a8054027SBarry Smith snes->lagpreconditioner = lag; 35843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3585a8054027SBarry Smith } 3586a8054027SBarry Smith 3587efd51863SBarry Smith /*@ 3588f6dfbefdSBarry Smith SNESSetGridSequence - sets the number of steps of grid sequencing that `SNES` will do 3589efd51863SBarry Smith 3590c3339decSBarry Smith Logically Collective 3591efd51863SBarry Smith 3592efd51863SBarry Smith Input Parameters: 3593f6dfbefdSBarry Smith + snes - the `SNES` context 3594efd51863SBarry Smith - steps - the number of refinements to do, defaults to 0 3595efd51863SBarry Smith 3596f6dfbefdSBarry Smith Options Database Key: 359767b8a455SSatish Balay . -snes_grid_sequence <steps> - Use grid sequencing to generate initial guess 3598efd51863SBarry Smith 3599efd51863SBarry Smith Level: intermediate 3600efd51863SBarry Smith 36010b4b7b1cSBarry Smith Notes: 36020b4b7b1cSBarry Smith Once grid sequencing is turned on `SNESSolve()` will automatically perform the solve on each grid refinement. 36030b4b7b1cSBarry Smith 3604f6dfbefdSBarry Smith Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing. 3605c0df2a02SJed Brown 36063201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetGridSequence()`, 360754c05997SPierre Jolivet `SNESSetDM()`, `SNESSolve()` 3608efd51863SBarry Smith @*/ 3609d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetGridSequence(SNES snes, PetscInt steps) 3610d71ae5a4SJacob Faibussowitsch { 3611efd51863SBarry Smith PetscFunctionBegin; 3612efd51863SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3613efd51863SBarry Smith PetscValidLogicalCollectiveInt(snes, steps, 2); 3614efd51863SBarry Smith snes->gridsequence = steps; 36153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3616efd51863SBarry Smith } 3617efd51863SBarry Smith 3618fa19ca70SBarry Smith /*@ 3619f6dfbefdSBarry Smith SNESGetGridSequence - gets the number of steps of grid sequencing that `SNES` will do 3620fa19ca70SBarry Smith 3621c3339decSBarry Smith Logically Collective 3622fa19ca70SBarry Smith 3623fa19ca70SBarry Smith Input Parameter: 3624f6dfbefdSBarry Smith . snes - the `SNES` context 3625fa19ca70SBarry Smith 3626fa19ca70SBarry Smith Output Parameter: 3627fa19ca70SBarry Smith . steps - the number of refinements to do, defaults to 0 3628fa19ca70SBarry Smith 3629fa19ca70SBarry Smith Level: intermediate 3630fa19ca70SBarry Smith 36313201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetGridSequence()` 3632fa19ca70SBarry Smith @*/ 3633d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetGridSequence(SNES snes, PetscInt *steps) 3634d71ae5a4SJacob Faibussowitsch { 3635fa19ca70SBarry Smith PetscFunctionBegin; 3636fa19ca70SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3637fa19ca70SBarry Smith *steps = snes->gridsequence; 36383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3639fa19ca70SBarry Smith } 3640fa19ca70SBarry Smith 3641a8054027SBarry Smith /*@ 3642f6dfbefdSBarry Smith SNESGetLagPreconditioner - Return how often the preconditioner is rebuilt 3643a8054027SBarry Smith 36443f9fe445SBarry Smith Not Collective 3645a8054027SBarry Smith 3646a8054027SBarry Smith Input Parameter: 3647f6dfbefdSBarry Smith . snes - the `SNES` context 3648a8054027SBarry Smith 3649a8054027SBarry Smith Output Parameter: 3650a8054027SBarry 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 36513b4f5425SBarry Smith the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that 3652a8054027SBarry Smith 3653dc4c0fb0SBarry Smith Level: intermediate 3654dc4c0fb0SBarry Smith 3655a8054027SBarry Smith Notes: 3656a8054027SBarry Smith The default is 1 3657f6dfbefdSBarry Smith 3658a8054027SBarry Smith The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 3659a8054027SBarry Smith 36603201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3661a8054027SBarry Smith @*/ 3662d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagPreconditioner(SNES snes, PetscInt *lag) 3663d71ae5a4SJacob Faibussowitsch { 3664a8054027SBarry Smith PetscFunctionBegin; 36650700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3666a8054027SBarry Smith *lag = snes->lagpreconditioner; 36673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3668a8054027SBarry Smith } 3669a8054027SBarry Smith 3670e35cf81dSBarry Smith /*@ 3671f6dfbefdSBarry Smith SNESSetLagJacobian - Set when the Jacobian is rebuilt in the nonlinear solve. See `SNESSetLagPreconditioner()` for determining how 3672e35cf81dSBarry Smith often the preconditioner is rebuilt. 3673e35cf81dSBarry Smith 3674c3339decSBarry Smith Logically Collective 3675e35cf81dSBarry Smith 3676e35cf81dSBarry Smith Input Parameters: 3677f6dfbefdSBarry Smith + snes - the `SNES` context 3678e35cf81dSBarry 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 3679fe3ffe1eSBarry Smith the Jacobian is built etc. -2 means rebuild at next chance but then never again 3680e35cf81dSBarry Smith 3681e35cf81dSBarry Smith Options Database Keys: 368279a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 36833d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 368479a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 36853d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag. 3686e35cf81dSBarry Smith 3687dc4c0fb0SBarry Smith Level: intermediate 3688dc4c0fb0SBarry Smith 3689e35cf81dSBarry Smith Notes: 3690e35cf81dSBarry Smith The default is 1 3691f6dfbefdSBarry Smith 3692e35cf81dSBarry Smith The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 3693f6dfbefdSBarry Smith 3694fe3ffe1eSBarry 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 3695fe3ffe1eSBarry Smith at the next Newton step but never again (unless it is reset to another value) 3696e35cf81dSBarry Smith 36973201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagPreconditioner()`, `SNESGetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3698e35cf81dSBarry Smith @*/ 3699d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobian(SNES snes, PetscInt lag) 3700d71ae5a4SJacob Faibussowitsch { 3701e35cf81dSBarry Smith PetscFunctionBegin; 37020700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 37035f80ce2aSJacob Faibussowitsch PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater"); 37045f80ce2aSJacob Faibussowitsch PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0"); 3705c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, lag, 2); 3706e35cf81dSBarry Smith snes->lagjacobian = lag; 37073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3708e35cf81dSBarry Smith } 3709e35cf81dSBarry Smith 3710e35cf81dSBarry Smith /*@ 3711f6dfbefdSBarry Smith SNESGetLagJacobian - Get how often the Jacobian is rebuilt. See `SNESGetLagPreconditioner()` to determine when the preconditioner is rebuilt 3712e35cf81dSBarry Smith 37133f9fe445SBarry Smith Not Collective 3714e35cf81dSBarry Smith 3715e35cf81dSBarry Smith Input Parameter: 3716f6dfbefdSBarry Smith . snes - the `SNES` context 3717e35cf81dSBarry Smith 3718e35cf81dSBarry Smith Output Parameter: 3719e35cf81dSBarry 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 3720e35cf81dSBarry Smith the Jacobian is built etc. 3721e35cf81dSBarry Smith 3722dc4c0fb0SBarry Smith Level: intermediate 3723dc4c0fb0SBarry Smith 3724e35cf81dSBarry Smith Notes: 3725e35cf81dSBarry Smith The default is 1 3726f6dfbefdSBarry Smith 3727f6dfbefdSBarry Smith The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagJacobianPersists()` was called. 3728e35cf81dSBarry Smith 37293201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobian()`, `SNESSetLagPreconditioner()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3730e35cf81dSBarry Smith 3731e35cf81dSBarry Smith @*/ 3732d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagJacobian(SNES snes, PetscInt *lag) 3733d71ae5a4SJacob Faibussowitsch { 3734e35cf81dSBarry Smith PetscFunctionBegin; 37350700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3736e35cf81dSBarry Smith *lag = snes->lagjacobian; 37373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3738e35cf81dSBarry Smith } 3739e35cf81dSBarry Smith 374037ec4e1aSPeter Brune /*@ 3741f6dfbefdSBarry Smith SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple nonlinear solves 374237ec4e1aSPeter Brune 3743c3339decSBarry Smith Logically collective 374437ec4e1aSPeter Brune 3745d8d19677SJose E. Roman Input Parameters: 3746f6dfbefdSBarry Smith + snes - the `SNES` context 37479d7e2deaSPeter Brune - flg - jacobian lagging persists if true 374837ec4e1aSPeter Brune 374937ec4e1aSPeter Brune Options Database Keys: 375079a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 37513d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 375279a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 37533d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 37543d5a8a6aSBarry Smith 3755dc4c0fb0SBarry Smith Level: advanced 3756dc4c0fb0SBarry Smith 375795452b02SPatrick Sanan Notes: 3758420bcc1bSBarry Smith Normally when `SNESSetLagJacobian()` is used, the Jacobian is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior 3759f6dfbefdSBarry Smith 376095452b02SPatrick Sanan This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by 376137ec4e1aSPeter Brune several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several 376237ec4e1aSPeter Brune timesteps may present huge efficiency gains. 376337ec4e1aSPeter Brune 376442747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditionerPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()` 376537ec4e1aSPeter Brune @*/ 3766d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobianPersists(SNES snes, PetscBool flg) 3767d71ae5a4SJacob Faibussowitsch { 376837ec4e1aSPeter Brune PetscFunctionBegin; 376937ec4e1aSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 377037ec4e1aSPeter Brune PetscValidLogicalCollectiveBool(snes, flg, 2); 377137ec4e1aSPeter Brune snes->lagjac_persist = flg; 37723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 377337ec4e1aSPeter Brune } 377437ec4e1aSPeter Brune 377537ec4e1aSPeter Brune /*@ 3776d8e291bfSBarry Smith SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple nonlinear solves 377737ec4e1aSPeter Brune 3778c3339decSBarry Smith Logically Collective 377937ec4e1aSPeter Brune 3780d8d19677SJose E. Roman Input Parameters: 3781f6dfbefdSBarry Smith + snes - the `SNES` context 37829d7e2deaSPeter Brune - flg - preconditioner lagging persists if true 378337ec4e1aSPeter Brune 378437ec4e1aSPeter Brune Options Database Keys: 378579a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 37863d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 378779a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 37883d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 378937ec4e1aSPeter Brune 3790dc4c0fb0SBarry Smith Level: developer 3791dc4c0fb0SBarry Smith 379295452b02SPatrick Sanan Notes: 3793420bcc1bSBarry Smith Normally when `SNESSetLagPreconditioner()` is used, the preconditioner is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior 3794f6dfbefdSBarry Smith 379595452b02SPatrick Sanan This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale 379637ec4e1aSPeter Brune by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over 379737ec4e1aSPeter Brune several timesteps may present huge efficiency gains. 379837ec4e1aSPeter Brune 37991cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobianPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagPreconditioner()` 380037ec4e1aSPeter Brune @*/ 3801d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes, PetscBool flg) 3802d71ae5a4SJacob Faibussowitsch { 380337ec4e1aSPeter Brune PetscFunctionBegin; 380437ec4e1aSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 380537ec4e1aSPeter Brune PetscValidLogicalCollectiveBool(snes, flg, 2); 380637ec4e1aSPeter Brune snes->lagpre_persist = flg; 38073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 380837ec4e1aSPeter Brune } 380937ec4e1aSPeter Brune 38109b94acceSBarry Smith /*@ 3811f6dfbefdSBarry Smith SNESSetForceIteration - force `SNESSolve()` to take at least one iteration regardless of the initial residual norm 3812be5caee7SBarry Smith 3813c3339decSBarry Smith Logically Collective 3814be5caee7SBarry Smith 3815be5caee7SBarry Smith Input Parameters: 3816f6dfbefdSBarry Smith + snes - the `SNES` context 3817f6dfbefdSBarry Smith - force - `PETSC_TRUE` require at least one iteration 3818be5caee7SBarry Smith 3819f6dfbefdSBarry Smith Options Database Key: 3820be5caee7SBarry Smith . -snes_force_iteration <force> - Sets forcing an iteration 3821be5caee7SBarry Smith 3822dc4c0fb0SBarry Smith Level: intermediate 3823dc4c0fb0SBarry Smith 3824f6dfbefdSBarry Smith Note: 3825f6dfbefdSBarry Smith This is used sometimes with `TS` to prevent `TS` from detecting a false steady state solution 3826be5caee7SBarry Smith 38273201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `TS`, `SNESSetDivergenceTolerance()` 3828be5caee7SBarry Smith @*/ 3829d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetForceIteration(SNES snes, PetscBool force) 3830d71ae5a4SJacob Faibussowitsch { 3831be5caee7SBarry Smith PetscFunctionBegin; 3832be5caee7SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3833be5caee7SBarry Smith snes->forceiteration = force; 38343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3835be5caee7SBarry Smith } 3836be5caee7SBarry Smith 383785216dc7SFande Kong /*@ 3838f6dfbefdSBarry Smith SNESGetForceIteration - Check whether or not `SNESSolve()` take at least one iteration regardless of the initial residual norm 383985216dc7SFande Kong 3840c3339decSBarry Smith Logically Collective 384185216dc7SFande Kong 38422fe279fdSBarry Smith Input Parameter: 3843f6dfbefdSBarry Smith . snes - the `SNES` context 384485216dc7SFande Kong 384585216dc7SFande Kong Output Parameter: 3846dc4c0fb0SBarry Smith . force - `PETSC_TRUE` requires at least one iteration. 384785216dc7SFande Kong 384806dd6b0eSSatish Balay Level: intermediate 384906dd6b0eSSatish Balay 38503201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetForceIteration()`, `SNESSetDivergenceTolerance()` 385185216dc7SFande Kong @*/ 3852d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetForceIteration(SNES snes, PetscBool *force) 3853d71ae5a4SJacob Faibussowitsch { 385485216dc7SFande Kong PetscFunctionBegin; 385585216dc7SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 385685216dc7SFande Kong *force = snes->forceiteration; 38573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 385885216dc7SFande Kong } 3859be5caee7SBarry Smith 3860be5caee7SBarry Smith /*@ 38610b4b7b1cSBarry Smith SNESSetTolerances - Sets various parameters used in `SNES` convergence tests. 38629b94acceSBarry Smith 3863c3339decSBarry Smith Logically Collective 3864c7afd0dbSLois Curfman McInnes 38659b94acceSBarry Smith Input Parameters: 3866f6dfbefdSBarry Smith + snes - the `SNES` context 38670b4b7b1cSBarry Smith . abstol - the absolute convergence tolerance, $ F(x^n) \le abstol $ 38680b4b7b1cSBarry Smith . rtol - the relative convergence tolerance, $ F(x^n) \le reltol * F(x^0) $ 38695358d0d4SBarry Smith . stol - convergence tolerance in terms of the norm of the change in the solution between steps, || delta x || < stol*|| x || 38700b4b7b1cSBarry Smith . maxit - the maximum number of iterations allowed in the solver, default 50. 38710b4b7b1cSBarry Smith - maxf - the maximum number of function evaluations allowed in the solver (use `PETSC_UNLIMITED` indicates no limit), default 10,000 3872fee21e36SBarry Smith 387333174efeSLois Curfman McInnes Options Database Keys: 387477e5a1f9SBarry Smith + -snes_atol <abstol> - Sets `abstol` 387577e5a1f9SBarry Smith . -snes_rtol <rtol> - Sets `rtol` 387677e5a1f9SBarry Smith . -snes_stol <stol> - Sets `stol` 387777e5a1f9SBarry Smith . -snes_max_it <maxit> - Sets `maxit` 387877e5a1f9SBarry Smith - -snes_max_funcs <maxf> - Sets `maxf` (use `unlimited` to have no maximum) 38799b94acceSBarry Smith 388036851e7fSLois Curfman McInnes Level: intermediate 388136851e7fSLois Curfman McInnes 388277e5a1f9SBarry Smith Note: 388377e5a1f9SBarry Smith All parameters must be non-negative 388477e5a1f9SBarry Smith 388577e5a1f9SBarry Smith Use `PETSC_CURRENT` to retain the current value of any parameter and `PETSC_DETERMINE` to use the default value for the given `SNES`. 388677e5a1f9SBarry Smith The default value is the value in the object when its type is set. 388777e5a1f9SBarry Smith 388877e5a1f9SBarry Smith Use `PETSC_UNLIMITED` on `maxit` or `maxf` to indicate there is no bound on the number of iterations or number of function evaluations. 388977e5a1f9SBarry Smith 389077e5a1f9SBarry Smith Fortran Note: 389177e5a1f9SBarry Smith Use `PETSC_CURRENT_INTEGER`, `PETSC_CURRENT_REAL`, `PETSC_UNLIMITED_INTEGER`, `PETSC_DETERMINE_INTEGER`, or `PETSC_DETERMINE_REAL` 389277e5a1f9SBarry Smith 38933201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESSolve()`, `SNES`, `SNESSetDivergenceTolerance()`, `SNESSetForceIteration()` 38949b94acceSBarry Smith @*/ 3895d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTolerances(SNES snes, PetscReal abstol, PetscReal rtol, PetscReal stol, PetscInt maxit, PetscInt maxf) 3896d71ae5a4SJacob Faibussowitsch { 38973a40ed3dSBarry Smith PetscFunctionBegin; 38980700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3899c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, abstol, 2); 3900c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, rtol, 3); 3901c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, stol, 4); 3902c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, maxit, 5); 3903c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, maxf, 6); 3904c5eb9154SBarry Smith 390577e5a1f9SBarry Smith if (abstol == (PetscReal)PETSC_DETERMINE) { 390677e5a1f9SBarry Smith snes->abstol = snes->default_abstol; 390777e5a1f9SBarry Smith } else if (abstol != (PetscReal)PETSC_CURRENT) { 39085f80ce2aSJacob Faibussowitsch PetscCheck(abstol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)abstol); 3909ab54825eSJed Brown snes->abstol = abstol; 3910ab54825eSJed Brown } 391177e5a1f9SBarry Smith 391277e5a1f9SBarry Smith if (rtol == (PetscReal)PETSC_DETERMINE) { 391377e5a1f9SBarry Smith snes->rtol = snes->default_rtol; 391477e5a1f9SBarry Smith } else if (rtol != (PetscReal)PETSC_CURRENT) { 39155f80ce2aSJacob 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); 3916ab54825eSJed Brown snes->rtol = rtol; 3917ab54825eSJed Brown } 391877e5a1f9SBarry Smith 391977e5a1f9SBarry Smith if (stol == (PetscReal)PETSC_DETERMINE) { 392077e5a1f9SBarry Smith snes->stol = snes->default_stol; 392177e5a1f9SBarry Smith } else if (stol != (PetscReal)PETSC_CURRENT) { 39225f80ce2aSJacob Faibussowitsch PetscCheck(stol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Step tolerance %g must be non-negative", (double)stol); 3923c60f73f4SPeter Brune snes->stol = stol; 3924ab54825eSJed Brown } 392577e5a1f9SBarry Smith 3926835f2295SStefano Zampini if (maxit == PETSC_DETERMINE) { 392777e5a1f9SBarry Smith snes->max_its = snes->default_max_its; 3928835f2295SStefano Zampini } else if (maxit == PETSC_UNLIMITED) { 392977e5a1f9SBarry Smith snes->max_its = PETSC_INT_MAX; 393077e5a1f9SBarry Smith } else if (maxit != PETSC_CURRENT) { 393163a3b9bcSJacob Faibussowitsch PetscCheck(maxit >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", maxit); 3932ab54825eSJed Brown snes->max_its = maxit; 3933ab54825eSJed Brown } 393477e5a1f9SBarry Smith 3935835f2295SStefano Zampini if (maxf == PETSC_DETERMINE) { 393677e5a1f9SBarry Smith snes->max_funcs = snes->default_max_funcs; 3937835f2295SStefano Zampini } else if (maxf == PETSC_UNLIMITED || maxf == -1) { 393877e5a1f9SBarry Smith snes->max_funcs = PETSC_UNLIMITED; 393977e5a1f9SBarry Smith } else if (maxf != PETSC_CURRENT) { 394077e5a1f9SBarry Smith PetscCheck(maxf >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations %" PetscInt_FMT " must be nonnegative", maxf); 3941ab54825eSJed Brown snes->max_funcs = maxf; 3942ab54825eSJed Brown } 39433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 39449b94acceSBarry Smith } 39459b94acceSBarry Smith 3946e4d06f11SPatrick Farrell /*@ 3947f6dfbefdSBarry Smith SNESSetDivergenceTolerance - Sets the divergence tolerance used for the `SNES` divergence test. 3948e4d06f11SPatrick Farrell 3949c3339decSBarry Smith Logically Collective 3950e4d06f11SPatrick Farrell 3951e4d06f11SPatrick Farrell Input Parameters: 3952f6dfbefdSBarry Smith + snes - the `SNES` context 39530b4b7b1cSBarry 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 39540b4b7b1cSBarry Smith is stopped due to divergence. 3955e4d06f11SPatrick Farrell 3956f6dfbefdSBarry Smith Options Database Key: 3957dc4c0fb0SBarry Smith . -snes_divergence_tolerance <divtol> - Sets `divtol` 3958e4d06f11SPatrick Farrell 3959e4d06f11SPatrick Farrell Level: intermediate 3960e4d06f11SPatrick Farrell 396177e5a1f9SBarry Smith Notes: 396277e5a1f9SBarry Smith Use `PETSC_DETERMINE` to use the default value from when the object's type was set. 3963e5cd489fSStefano Zampini 396477e5a1f9SBarry Smith Fortran Note: 396577e5a1f9SBarry Smith Use ``PETSC_DETERMINE_REAL` or `PETSC_UNLIMITED_REAL` 396677e5a1f9SBarry Smith 396777e5a1f9SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetTolerances()`, `SNESGetDivergenceTolerance()` 3968e4d06f11SPatrick Farrell @*/ 3969d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDivergenceTolerance(SNES snes, PetscReal divtol) 3970d71ae5a4SJacob Faibussowitsch { 3971e4d06f11SPatrick Farrell PetscFunctionBegin; 3972e4d06f11SPatrick Farrell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3973e4d06f11SPatrick Farrell PetscValidLogicalCollectiveReal(snes, divtol, 2); 397477e5a1f9SBarry Smith 397577e5a1f9SBarry Smith if (divtol == (PetscReal)PETSC_DETERMINE) { 397677e5a1f9SBarry Smith snes->divtol = snes->default_divtol; 397777e5a1f9SBarry Smith } else if (divtol == (PetscReal)PETSC_UNLIMITED || divtol == -1) { 397877e5a1f9SBarry Smith snes->divtol = PETSC_UNLIMITED; 397977e5a1f9SBarry Smith } else if (divtol != (PetscReal)PETSC_CURRENT) { 398077e5a1f9SBarry Smith PetscCheck(divtol >= 1.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Divergence tolerance %g must be greater than 1.0", (double)divtol); 398177e5a1f9SBarry Smith snes->divtol = divtol; 398277e5a1f9SBarry Smith } 39833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3984e4d06f11SPatrick Farrell } 3985e4d06f11SPatrick Farrell 39869b94acceSBarry Smith /*@ 39870b4b7b1cSBarry Smith SNESGetTolerances - Gets various parameters used in `SNES` convergence tests. 398833174efeSLois Curfman McInnes 3989c7afd0dbSLois Curfman McInnes Not Collective 3990c7afd0dbSLois Curfman McInnes 399177e5a1f9SBarry Smith Input Parameter: 399277e5a1f9SBarry Smith . snes - the `SNES` context 399377e5a1f9SBarry Smith 399477e5a1f9SBarry Smith Output Parameters: 39950b4b7b1cSBarry Smith + atol - the absolute convergence tolerance 39960b4b7b1cSBarry Smith . rtol - the relative convergence tolerance 399777e5a1f9SBarry Smith . stol - convergence tolerance in terms of the norm of the change in the solution between steps 39980b4b7b1cSBarry Smith . maxit - the maximum number of iterations allowed 39990b4b7b1cSBarry Smith - maxf - the maximum number of function evaluations allowed, `PETSC_UNLIMITED` indicates no bound 4000fee21e36SBarry Smith 400136851e7fSLois Curfman McInnes Level: intermediate 400236851e7fSLois Curfman McInnes 40030b4b7b1cSBarry Smith Notes: 40040b4b7b1cSBarry Smith See `SNESSetTolerances()` for details on the parameters. 40050b4b7b1cSBarry Smith 4006dc4c0fb0SBarry Smith The user can specify `NULL` for any parameter that is not needed. 4007dc4c0fb0SBarry Smith 40081cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTolerances()` 400933174efeSLois Curfman McInnes @*/ 4010d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetTolerances(SNES snes, PetscReal *atol, PetscReal *rtol, PetscReal *stol, PetscInt *maxit, PetscInt *maxf) 4011d71ae5a4SJacob Faibussowitsch { 40123a40ed3dSBarry Smith PetscFunctionBegin; 40130700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 401485385478SLisandro Dalcin if (atol) *atol = snes->abstol; 401533174efeSLois Curfman McInnes if (rtol) *rtol = snes->rtol; 4016c60f73f4SPeter Brune if (stol) *stol = snes->stol; 401733174efeSLois Curfman McInnes if (maxit) *maxit = snes->max_its; 401833174efeSLois Curfman McInnes if (maxf) *maxf = snes->max_funcs; 40193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 402033174efeSLois Curfman McInnes } 402133174efeSLois Curfman McInnes 4022e4d06f11SPatrick Farrell /*@ 4023e4d06f11SPatrick Farrell SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test. 4024e4d06f11SPatrick Farrell 4025e4d06f11SPatrick Farrell Not Collective 4026e4d06f11SPatrick Farrell 4027e4d06f11SPatrick Farrell Input Parameters: 4028f6dfbefdSBarry Smith + snes - the `SNES` context 4029e4d06f11SPatrick Farrell - divtol - divergence tolerance 4030e4d06f11SPatrick Farrell 4031e4d06f11SPatrick Farrell Level: intermediate 4032e4d06f11SPatrick Farrell 40331cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetDivergenceTolerance()` 4034e4d06f11SPatrick Farrell @*/ 4035d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDivergenceTolerance(SNES snes, PetscReal *divtol) 4036d71ae5a4SJacob Faibussowitsch { 4037e4d06f11SPatrick Farrell PetscFunctionBegin; 4038e4d06f11SPatrick Farrell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4039e4d06f11SPatrick Farrell if (divtol) *divtol = snes->divtol; 40403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4041e4d06f11SPatrick Farrell } 4042e4d06f11SPatrick Farrell 40436ba87a44SLisandro Dalcin PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *); 40446ba87a44SLisandro Dalcin 4045d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorLGRange(SNES snes, PetscInt n, PetscReal rnorm, void *monctx) 4046d71ae5a4SJacob Faibussowitsch { 4047b271bb04SBarry Smith PetscDrawLG lg; 4048b271bb04SBarry Smith PetscReal x, y, per; 4049b271bb04SBarry Smith PetscViewer v = (PetscViewer)monctx; 4050b271bb04SBarry Smith static PetscReal prev; /* should be in the context */ 4051b271bb04SBarry Smith PetscDraw draw; 4052b271bb04SBarry Smith 4053459f5d12SBarry Smith PetscFunctionBegin; 40544d4332d5SBarry Smith PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 4); 40559566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 0, &lg)); 40569566063dSJacob Faibussowitsch if (!n) PetscCall(PetscDrawLGReset(lg)); 40579566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 40589566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "Residual norm")); 4059b271bb04SBarry Smith x = (PetscReal)n; 406077b4d14cSPeter Brune if (rnorm > 0.0) y = PetscLog10Real(rnorm); 406194c9c6d3SKarl Rupp else y = -15.0; 40629566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 40636934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 40649566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 40659566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 4066b271bb04SBarry Smith } 4067b271bb04SBarry Smith 40689566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 1, &lg)); 40699566063dSJacob Faibussowitsch if (!n) PetscCall(PetscDrawLGReset(lg)); 40709566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 4071aaa8cc7dSPierre Jolivet PetscCall(PetscDrawSetTitle(draw, "% elements > .2*max element")); 40729566063dSJacob Faibussowitsch PetscCall(SNESMonitorRange_Private(snes, n, &per)); 4073b271bb04SBarry Smith x = (PetscReal)n; 4074b271bb04SBarry Smith y = 100.0 * per; 40759566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 40766934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 40779566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 40789566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 4079b271bb04SBarry Smith } 4080b271bb04SBarry Smith 40819566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 2, &lg)); 40829371c9d4SSatish Balay if (!n) { 40839371c9d4SSatish Balay prev = rnorm; 40849371c9d4SSatish Balay PetscCall(PetscDrawLGReset(lg)); 40859371c9d4SSatish Balay } 40869566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 40879566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm")); 4088b271bb04SBarry Smith x = (PetscReal)n; 4089b271bb04SBarry Smith y = (prev - rnorm) / prev; 40909566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 40916934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 40929566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 40939566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 4094b271bb04SBarry Smith } 4095b271bb04SBarry Smith 40969566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 3, &lg)); 40979566063dSJacob Faibussowitsch if (!n) PetscCall(PetscDrawLGReset(lg)); 40989566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 40999566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm*(% > .2 max)")); 4100b271bb04SBarry Smith x = (PetscReal)n; 4101b271bb04SBarry Smith y = (prev - rnorm) / (prev * per); 4102b271bb04SBarry Smith if (n > 2) { /*skip initial crazy value */ 41039566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 4104b271bb04SBarry Smith } 41056934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 41069566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 41079566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 4108b271bb04SBarry Smith } 4109b271bb04SBarry Smith prev = rnorm; 41103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4111b271bb04SBarry Smith } 4112b271bb04SBarry Smith 4113228d79bcSJed Brown /*@ 41142d157150SStefano Zampini SNESConverged - Run the convergence test and update the `SNESConvergedReason`. 41152d157150SStefano Zampini 41162d157150SStefano Zampini Collective 41172d157150SStefano Zampini 41182d157150SStefano Zampini Input Parameters: 41192d157150SStefano Zampini + snes - the `SNES` context 41202d157150SStefano Zampini . it - current iteration 41212d157150SStefano Zampini . xnorm - 2-norm of current iterate 41222d157150SStefano Zampini . snorm - 2-norm of current step 41232d157150SStefano Zampini - fnorm - 2-norm of function 41242d157150SStefano Zampini 41252d157150SStefano Zampini Level: developer 41262d157150SStefano Zampini 41272d157150SStefano Zampini Note: 4128420bcc1bSBarry Smith This routine is called by the `SNESSolve()` implementations. 41292d157150SStefano Zampini It does not typically need to be called by the user. 41302d157150SStefano Zampini 4131c948abdaSPierre Jolivet .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()` 41322d157150SStefano Zampini @*/ 41332d157150SStefano Zampini PetscErrorCode SNESConverged(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm) 41342d157150SStefano Zampini { 41352d157150SStefano Zampini PetscFunctionBegin; 41362d157150SStefano Zampini if (!snes->reason) { 41372d157150SStefano Zampini if (snes->normschedule == SNES_NORM_ALWAYS) PetscUseTypeMethod(snes, converged, it, xnorm, snorm, fnorm, &snes->reason, snes->cnvP); 41382d157150SStefano Zampini if (it == snes->max_its && !snes->reason) { 41392d157150SStefano Zampini if (snes->normschedule == SNES_NORM_ALWAYS) { 41402d157150SStefano Zampini PetscCall(PetscInfo(snes, "Maximum number of iterations has been reached: %" PetscInt_FMT "\n", snes->max_its)); 41412d157150SStefano Zampini snes->reason = SNES_DIVERGED_MAX_IT; 41422d157150SStefano Zampini } else snes->reason = SNES_CONVERGED_ITS; 41432d157150SStefano Zampini } 41442d157150SStefano Zampini } 41452d157150SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 41462d157150SStefano Zampini } 41472d157150SStefano Zampini 41482d157150SStefano Zampini /*@ 41490b4b7b1cSBarry Smith SNESMonitor - runs any `SNES` monitor routines provided with `SNESMonitor()` or the options database 4150228d79bcSJed Brown 4151c3339decSBarry Smith Collective 4152228d79bcSJed Brown 4153228d79bcSJed Brown Input Parameters: 4154f6dfbefdSBarry Smith + snes - nonlinear solver context obtained from `SNESCreate()` 41550b4b7b1cSBarry Smith . iter - current iteration number 41560b4b7b1cSBarry Smith - rnorm - current relative norm of the residual 4157228d79bcSJed Brown 4158dc4c0fb0SBarry Smith Level: developer 4159dc4c0fb0SBarry Smith 4160f6dfbefdSBarry Smith Note: 4161420bcc1bSBarry Smith This routine is called by the `SNESSolve()` implementations. 4162228d79bcSJed Brown It does not typically need to be called by the user. 4163228d79bcSJed Brown 41641cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorSet()` 4165228d79bcSJed Brown @*/ 4166d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitor(SNES snes, PetscInt iter, PetscReal rnorm) 4167d71ae5a4SJacob Faibussowitsch { 41687a03ce2fSLisandro Dalcin PetscInt i, n = snes->numbermonitors; 41697a03ce2fSLisandro Dalcin 41707a03ce2fSLisandro Dalcin PetscFunctionBegin; 41715f3c5e7aSBarry Smith if (n > 0) SNESCheckFunctionNorm(snes, rnorm); 41729566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(snes->vec_sol)); 417348a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall((*snes->monitor[i])(snes, iter, rnorm, snes->monitorcontext[i])); 41749566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(snes->vec_sol)); 41753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 41767a03ce2fSLisandro Dalcin } 41777a03ce2fSLisandro Dalcin 41789b94acceSBarry Smith /* ------------ Routines to set performance monitoring options ----------- */ 41799b94acceSBarry Smith 4180bf388a1fSBarry Smith /*MC 4181f6dfbefdSBarry Smith SNESMonitorFunction - functional form passed to `SNESMonitorSet()` to monitor convergence of nonlinear solver 4182bf388a1fSBarry Smith 4183bf388a1fSBarry Smith Synopsis: 4184aaa7dc30SBarry Smith #include <petscsnes.h> 418537fdd005SBarry Smith PetscErrorCode SNESMonitorFunction(SNES snes, PetscInt its, PetscReal norm, void *mctx) 4186bf388a1fSBarry Smith 4187c3339decSBarry Smith Collective 41881843f636SBarry Smith 41891843f636SBarry Smith Input Parameters: 4190f6dfbefdSBarry Smith + snes - the `SNES` context 4191bf388a1fSBarry Smith . its - iteration number 4192bf388a1fSBarry Smith . norm - 2-norm function value (may be estimated) 4193bf388a1fSBarry Smith - mctx - [optional] monitoring context 4194bf388a1fSBarry Smith 4195878cb397SSatish Balay Level: advanced 4196878cb397SSatish Balay 41971cc06b55SBarry Smith .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSet()`, `SNESMonitorGet()` 4198bf388a1fSBarry Smith M*/ 4199bf388a1fSBarry Smith 42009b94acceSBarry Smith /*@C 4201a6570f20SBarry Smith SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every 42020b4b7b1cSBarry Smith iteration of the `SNES` nonlinear solver to display the iteration's 42039b94acceSBarry Smith progress. 42049b94acceSBarry Smith 4205c3339decSBarry Smith Logically Collective 4206fee21e36SBarry Smith 4207c7afd0dbSLois Curfman McInnes Input Parameters: 4208f6dfbefdSBarry Smith + snes - the `SNES` context 420920f4b53cSBarry Smith . f - the monitor function, for the calling sequence see `SNESMonitorFunction` 4210420bcc1bSBarry Smith . mctx - [optional] user-defined context for private data for the monitor routine (use `NULL` if no context is desired) 421149abdd8aSBarry Smith - monitordestroy - [optional] routine that frees monitor context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence 42129b94acceSBarry Smith 42139665c990SLois Curfman McInnes Options Database Keys: 4214f6dfbefdSBarry Smith + -snes_monitor - sets `SNESMonitorDefault()` 4215798534f6SMatthew G. Knepley . -snes_monitor draw::draw_lg - sets line graph monitor, 4216dc4c0fb0SBarry 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 4217c7afd0dbSLois Curfman McInnes the options database. 42189665c990SLois Curfman McInnes 4219dc4c0fb0SBarry Smith Level: intermediate 4220dc4c0fb0SBarry Smith 4221f6dfbefdSBarry Smith Note: 42226bc08f3fSLois Curfman McInnes Several different monitoring routines may be set by calling 4223f6dfbefdSBarry Smith `SNESMonitorSet()` multiple times; all will be called in the 42246bc08f3fSLois Curfman McInnes order in which they were set. 4225639f9d9dSBarry Smith 4226420bcc1bSBarry Smith Fortran Note: 4227f6dfbefdSBarry Smith Only a single monitor function can be set for each `SNES` object 4228025f1a04SBarry Smith 422949abdd8aSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESMonitorDefault()`, `SNESMonitorCancel()`, `SNESMonitorFunction`, `PetscCtxDestroyFn` 42309b94acceSBarry Smith @*/ 423149abdd8aSBarry Smith PetscErrorCode SNESMonitorSet(SNES snes, PetscErrorCode (*f)(SNES, PetscInt, PetscReal, void *), void *mctx, PetscCtxDestroyFn *monitordestroy) 4232d71ae5a4SJacob Faibussowitsch { 4233b90d0a6eSBarry Smith PetscInt i; 423478064530SBarry Smith PetscBool identical; 4235b90d0a6eSBarry Smith 42363a40ed3dSBarry Smith PetscFunctionBegin; 42370700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4238b90d0a6eSBarry Smith for (i = 0; i < snes->numbermonitors; i++) { 42399566063dSJacob Faibussowitsch PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))f, mctx, monitordestroy, (PetscErrorCode (*)(void))snes->monitor[i], snes->monitorcontext[i], snes->monitordestroy[i], &identical)); 42403ba16761SJacob Faibussowitsch if (identical) PetscFunctionReturn(PETSC_SUCCESS); 4241649052a6SBarry Smith } 42425f80ce2aSJacob Faibussowitsch PetscCheck(snes->numbermonitors < MAXSNESMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set"); 42436e4dcb14SBarry Smith snes->monitor[snes->numbermonitors] = f; 4244b8a78c4aSBarry Smith snes->monitordestroy[snes->numbermonitors] = monitordestroy; 4245835f2295SStefano Zampini snes->monitorcontext[snes->numbermonitors++] = mctx; 42463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 42479b94acceSBarry Smith } 42489b94acceSBarry Smith 4249a278d85bSSatish Balay /*@ 4250f6dfbefdSBarry Smith SNESMonitorCancel - Clears all the monitor functions for a `SNES` object. 42515cd90555SBarry Smith 4252c3339decSBarry Smith Logically Collective 4253c7afd0dbSLois Curfman McInnes 42542fe279fdSBarry Smith Input Parameter: 4255f6dfbefdSBarry Smith . snes - the `SNES` context 42565cd90555SBarry Smith 42571a480d89SAdministrator Options Database Key: 4258a6570f20SBarry Smith . -snes_monitor_cancel - cancels all monitors that have been hardwired 4259dc4c0fb0SBarry Smith into a code by calls to `SNESMonitorSet()`, but does not cancel those 4260c7afd0dbSLois Curfman McInnes set via the options database 42615cd90555SBarry Smith 4262dc4c0fb0SBarry Smith Level: intermediate 4263dc4c0fb0SBarry Smith 4264f6dfbefdSBarry Smith Note: 4265f6dfbefdSBarry Smith There is no way to clear one specific monitor from a `SNES` object. 42665cd90555SBarry Smith 42671cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorGet()`, `SNESMonitorDefault()`, `SNESMonitorSet()` 42685cd90555SBarry Smith @*/ 4269d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorCancel(SNES snes) 4270d71ae5a4SJacob Faibussowitsch { 4271d952e501SBarry Smith PetscInt i; 4272d952e501SBarry Smith 42735cd90555SBarry Smith PetscFunctionBegin; 42740700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4275d952e501SBarry Smith for (i = 0; i < snes->numbermonitors; i++) { 427648a46eb9SPierre Jolivet if (snes->monitordestroy[i]) PetscCall((*snes->monitordestroy[i])(&snes->monitorcontext[i])); 4277d952e501SBarry Smith } 42785cd90555SBarry Smith snes->numbermonitors = 0; 42793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 42805cd90555SBarry Smith } 42815cd90555SBarry Smith 4282bf388a1fSBarry Smith /*MC 4283bf388a1fSBarry Smith SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver 4284bf388a1fSBarry Smith 4285bf388a1fSBarry Smith Synopsis: 4286aaa7dc30SBarry Smith #include <petscsnes.h> 428737fdd005SBarry Smith PetscErrorCode SNESConvergenceTest(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *cctx) 4288bf388a1fSBarry Smith 4289c3339decSBarry Smith Collective 42901843f636SBarry Smith 42911843f636SBarry Smith Input Parameters: 4292f6dfbefdSBarry Smith + snes - the `SNES` context 4293bf388a1fSBarry Smith . it - current iteration (0 is the first and is before any Newton step) 4294bf388a1fSBarry Smith . xnorm - 2-norm of current iterate 4295bf388a1fSBarry Smith . gnorm - 2-norm of current step 42961843f636SBarry Smith . f - 2-norm of function 42971843f636SBarry Smith - cctx - [optional] convergence context 42981843f636SBarry Smith 42991843f636SBarry Smith Output Parameter: 43001843f636SBarry Smith . reason - reason for convergence/divergence, only needs to be set when convergence or divergence is detected 4301bf388a1fSBarry Smith 4302878cb397SSatish Balay Level: intermediate 4303bf388a1fSBarry Smith 4304c948abdaSPierre Jolivet .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()` 4305bf388a1fSBarry Smith M*/ 4306bf388a1fSBarry Smith 43079b94acceSBarry Smith /*@C 43089b94acceSBarry Smith SNESSetConvergenceTest - Sets the function that is to be used 43099b94acceSBarry Smith to test for convergence of the nonlinear iterative solution. 43109b94acceSBarry Smith 4311c3339decSBarry Smith Logically Collective 4312fee21e36SBarry Smith 4313c7afd0dbSLois Curfman McInnes Input Parameters: 4314f6dfbefdSBarry Smith + snes - the `SNES` context 4315e4094ef1SJacob Faibussowitsch . SNESConvergenceTestFunction - routine to test for convergence 4316dc4c0fb0SBarry Smith . cctx - [optional] context for private data for the convergence routine (may be `NULL`) 4317dc4c0fb0SBarry Smith - destroy - [optional] destructor for the context (may be `NULL`; `PETSC_NULL_FUNCTION` in Fortran) 43189b94acceSBarry Smith 431936851e7fSLois Curfman McInnes Level: advanced 432036851e7fSLois Curfman McInnes 43211cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedDefault()`, `SNESConvergedSkip()`, `SNESConvergenceTestFunction` 43229b94acceSBarry Smith @*/ 4323d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceTest(SNES snes, PetscErrorCode (*SNESConvergenceTestFunction)(SNES, PetscInt, PetscReal, PetscReal, PetscReal, SNESConvergedReason *, void *), void *cctx, PetscErrorCode (*destroy)(void *)) 4324d71ae5a4SJacob Faibussowitsch { 43253a40ed3dSBarry Smith PetscFunctionBegin; 43260700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4327e2a6519dSDmitry Karpeev if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip; 43281baa6e33SBarry Smith if (snes->ops->convergeddestroy) PetscCall((*snes->ops->convergeddestroy)(snes->cnvP)); 4329bf388a1fSBarry Smith snes->ops->converged = SNESConvergenceTestFunction; 43307f7931b9SBarry Smith snes->ops->convergeddestroy = destroy; 433185385478SLisandro Dalcin snes->cnvP = cctx; 43323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 43339b94acceSBarry Smith } 43349b94acceSBarry Smith 433552baeb72SSatish Balay /*@ 43360b4b7b1cSBarry Smith SNESGetConvergedReason - Gets the reason the `SNES` iteration was stopped, which may be due to convergence, divergence, or stagnation 4337184914b5SBarry Smith 4338184914b5SBarry Smith Not Collective 4339184914b5SBarry Smith 4340184914b5SBarry Smith Input Parameter: 4341f6dfbefdSBarry Smith . snes - the `SNES` context 4342184914b5SBarry Smith 4343184914b5SBarry Smith Output Parameter: 4344f6dfbefdSBarry Smith . reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` for the individual convergence tests for complete lists 4345184914b5SBarry Smith 4346f6dfbefdSBarry Smith Options Database Key: 43476a4d7782SBarry Smith . -snes_converged_reason - prints the reason to standard out 43486a4d7782SBarry Smith 4349184914b5SBarry Smith Level: intermediate 4350184914b5SBarry Smith 4351f6dfbefdSBarry Smith Note: 4352f6dfbefdSBarry Smith Should only be called after the call the `SNESSolve()` is complete, if it is called earlier it returns the value `SNES__CONVERGED_ITERATING`. 4353184914b5SBarry Smith 43541cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESSetConvergedReason()`, `SNESConvergedReason`, `SNESGetConvergedReasonString()` 4355184914b5SBarry Smith @*/ 4356d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReason(SNES snes, SNESConvergedReason *reason) 4357d71ae5a4SJacob Faibussowitsch { 4358184914b5SBarry Smith PetscFunctionBegin; 43590700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 43604f572ea9SToby Isaac PetscAssertPointer(reason, 2); 4361184914b5SBarry Smith *reason = snes->reason; 43623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4363184914b5SBarry Smith } 4364184914b5SBarry Smith 4365c4421ceaSFande Kong /*@C 4366f6dfbefdSBarry Smith SNESGetConvergedReasonString - Return a human readable string for `SNESConvergedReason` 4367c4421ceaSFande Kong 4368c4421ceaSFande Kong Not Collective 4369c4421ceaSFande Kong 4370c4421ceaSFande Kong Input Parameter: 4371f6dfbefdSBarry Smith . snes - the `SNES` context 4372c4421ceaSFande Kong 4373c4421ceaSFande Kong Output Parameter: 4374dc4c0fb0SBarry Smith . strreason - a human readable string that describes `SNES` converged reason 4375c4421ceaSFande Kong 437699c90e12SSatish Balay Level: beginner 4377c4421ceaSFande Kong 43781cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetConvergedReason()` 4379c4421ceaSFande Kong @*/ 4380d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReasonString(SNES snes, const char **strreason) 4381d71ae5a4SJacob Faibussowitsch { 4382c4421ceaSFande Kong PetscFunctionBegin; 4383c4421ceaSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 43844f572ea9SToby Isaac PetscAssertPointer(strreason, 2); 4385c4421ceaSFande Kong *strreason = SNESConvergedReasons[snes->reason]; 43863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4387c4421ceaSFande Kong } 4388c4421ceaSFande Kong 438933866048SMatthew G. Knepley /*@ 4390f6dfbefdSBarry Smith SNESSetConvergedReason - Sets the reason the `SNES` iteration was stopped. 439133866048SMatthew G. Knepley 439233866048SMatthew G. Knepley Not Collective 439333866048SMatthew G. Knepley 439433866048SMatthew G. Knepley Input Parameters: 4395f6dfbefdSBarry Smith + snes - the `SNES` context 4396f6dfbefdSBarry Smith - reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` or the 439733866048SMatthew G. Knepley manual pages for the individual convergence tests for complete lists 439833866048SMatthew G. Knepley 4399f6dfbefdSBarry Smith Level: developer 4400f6dfbefdSBarry Smith 4401420bcc1bSBarry Smith Developer Note: 4402f6dfbefdSBarry Smith Called inside the various `SNESSolve()` implementations 440333866048SMatthew G. Knepley 44041cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetConvergedReason()`, `SNESSetConvergenceTest()`, `SNESConvergedReason` 440533866048SMatthew G. Knepley @*/ 4406d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergedReason(SNES snes, SNESConvergedReason reason) 4407d71ae5a4SJacob Faibussowitsch { 440833866048SMatthew G. Knepley PetscFunctionBegin; 440933866048SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 44105f3c5e7aSBarry Smith PetscCheck(!snes->errorifnotconverged || reason > 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "SNES code should have previously errored due to negative reason"); 441133866048SMatthew G. Knepley snes->reason = reason; 44123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 441333866048SMatthew G. Knepley } 441433866048SMatthew G. Knepley 4415c9005455SLois Curfman McInnes /*@ 4416420bcc1bSBarry Smith SNESSetConvergenceHistory - Sets the arrays used to hold the convergence history. 4417c9005455SLois Curfman McInnes 4418c3339decSBarry Smith Logically Collective 4419fee21e36SBarry Smith 4420c7afd0dbSLois Curfman McInnes Input Parameters: 4421f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 44228c7482ecSBarry Smith . a - array to hold history, this array will contain the function norms computed at each step 4423cd5578b5SBarry Smith . its - integer array holds the number of linear iterations for each solve. 4424420bcc1bSBarry Smith . na - size of `a` and `its` 4425f6dfbefdSBarry Smith - reset - `PETSC_TRUE` indicates each new nonlinear solve resets the history counter to zero, 4426758f92a0SBarry Smith else it continues storing new values for new nonlinear solves after the old ones 4427c7afd0dbSLois Curfman McInnes 4428dc4c0fb0SBarry Smith Level: intermediate 4429dc4c0fb0SBarry Smith 4430308dcc3eSBarry Smith Notes: 4431ce78bad3SBarry 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 443277e5a1f9SBarry Smith default array of length 1,000 is allocated. 4433308dcc3eSBarry Smith 4434c9005455SLois Curfman McInnes This routine is useful, e.g., when running a code for purposes 4435c9005455SLois Curfman McInnes of accurate performance monitoring, when no I/O should be done 4436c9005455SLois Curfman McInnes during the section of code that is being timed. 4437c9005455SLois Curfman McInnes 4438420bcc1bSBarry Smith If the arrays run out of space after a number of iterations then the later values are not saved in the history 4439420bcc1bSBarry Smith 44401cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetConvergenceHistory()` 4441c9005455SLois Curfman McInnes @*/ 4442d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceHistory(SNES snes, PetscReal a[], PetscInt its[], PetscInt na, PetscBool reset) 4443d71ae5a4SJacob Faibussowitsch { 44443a40ed3dSBarry Smith PetscFunctionBegin; 44450700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 44464f572ea9SToby Isaac if (a) PetscAssertPointer(a, 2); 44474f572ea9SToby Isaac if (its) PetscAssertPointer(its, 3); 44487a1ec6d4SBarry Smith if (!a) { 444977e5a1f9SBarry Smith if (na == PETSC_DECIDE) na = 1000; 44509566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(na, &a, na, &its)); 4451071fcb05SBarry Smith snes->conv_hist_alloc = PETSC_TRUE; 4452308dcc3eSBarry Smith } 4453c9005455SLois Curfman McInnes snes->conv_hist = a; 4454758f92a0SBarry Smith snes->conv_hist_its = its; 4455115dd874SBarry Smith snes->conv_hist_max = (size_t)na; 4456a12bc48fSLisandro Dalcin snes->conv_hist_len = 0; 4457758f92a0SBarry Smith snes->conv_hist_reset = reset; 44583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4459758f92a0SBarry Smith } 4460758f92a0SBarry Smith 4461d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB) 4462c6db04a5SJed Brown #include <engine.h> /* MATLAB include file */ 4463c6db04a5SJed Brown #include <mex.h> /* MATLAB include file */ 446499e0435eSBarry Smith 4465d71ae5a4SJacob Faibussowitsch PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes) 4466d71ae5a4SJacob Faibussowitsch { 4467308dcc3eSBarry Smith mxArray *mat; 4468308dcc3eSBarry Smith PetscInt i; 4469308dcc3eSBarry Smith PetscReal *ar; 4470308dcc3eSBarry Smith 4471308dcc3eSBarry Smith mat = mxCreateDoubleMatrix(snes->conv_hist_len, 1, mxREAL); 4472308dcc3eSBarry Smith ar = (PetscReal *)mxGetData(mat); 4473f5af7f23SKarl Rupp for (i = 0; i < snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i]; 447411cc89d2SBarry Smith return mat; 4475308dcc3eSBarry Smith } 4476308dcc3eSBarry Smith #endif 4477308dcc3eSBarry Smith 44780c4c9dddSBarry Smith /*@C 4479420bcc1bSBarry Smith SNESGetConvergenceHistory - Gets the arrays used to hold the convergence history. 4480758f92a0SBarry Smith 44813f9fe445SBarry Smith Not Collective 4482758f92a0SBarry Smith 4483758f92a0SBarry Smith Input Parameter: 4484f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 4485758f92a0SBarry Smith 4486758f92a0SBarry Smith Output Parameters: 4487f6dfbefdSBarry Smith + a - array to hold history, usually was set with `SNESSetConvergenceHistory()` 4488758f92a0SBarry Smith . its - integer array holds the number of linear iterations (or 4489758f92a0SBarry Smith negative if not converged) for each solve. 449020f4b53cSBarry Smith - na - size of `a` and `its` 4491758f92a0SBarry Smith 4492dc4c0fb0SBarry Smith Level: intermediate 4493dc4c0fb0SBarry Smith 449420f4b53cSBarry Smith Note: 449520f4b53cSBarry Smith This routine is useful, e.g., when running a code for purposes 449620f4b53cSBarry Smith of accurate performance monitoring, when no I/O should be done 449720f4b53cSBarry Smith during the section of code that is being timed. 449820f4b53cSBarry Smith 4499ce78bad3SBarry Smith Fortran Notes: 4500ce78bad3SBarry Smith Return the arrays with ``SNESRestoreConvergenceHistory()` 4501ce78bad3SBarry Smith 4502ce78bad3SBarry Smith Use the arguments 4503dc4c0fb0SBarry Smith .vb 4504ce78bad3SBarry Smith PetscReal, pointer :: a(:) 4505ce78bad3SBarry Smith PetscInt, pointer :: its(:) 4506dc4c0fb0SBarry Smith .ve 4507758f92a0SBarry Smith 45081cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceHistory()` 4509758f92a0SBarry Smith @*/ 4510d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergenceHistory(SNES snes, PetscReal *a[], PetscInt *its[], PetscInt *na) 4511d71ae5a4SJacob Faibussowitsch { 4512758f92a0SBarry Smith PetscFunctionBegin; 45130700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4514758f92a0SBarry Smith if (a) *a = snes->conv_hist; 4515758f92a0SBarry Smith if (its) *its = snes->conv_hist_its; 4516115dd874SBarry Smith if (na) *na = (PetscInt)snes->conv_hist_len; 45173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4518c9005455SLois Curfman McInnes } 4519c9005455SLois Curfman McInnes 4520ac226902SBarry Smith /*@C 452176b2cf59SMatthew Knepley SNESSetUpdate - Sets the general-purpose update function called 4522eec8f646SJed Brown at the beginning of every iteration of the nonlinear solve. Specifically 452353e5d35bSStefano Zampini it is called just before the Jacobian is "evaluated" and after the function 452453e5d35bSStefano Zampini evaluation. 452576b2cf59SMatthew Knepley 4526c3339decSBarry Smith Logically Collective 452776b2cf59SMatthew Knepley 452876b2cf59SMatthew Knepley Input Parameters: 4529a2b725a8SWilliam Gropp + snes - The nonlinear solver context 453053e5d35bSStefano Zampini - func - The update function; for calling sequence see `SNESUpdateFn` 453176b2cf59SMatthew Knepley 4532fe97e370SBarry Smith Level: advanced 4533fe97e370SBarry Smith 4534420bcc1bSBarry Smith Notes: 4535f6dfbefdSBarry 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 4536f6dfbefdSBarry Smith to `SNESSetFunction()`, or `SNESSetPicard()` 453753e5d35bSStefano Zampini This is not used by most users, and it is intended to provide a general hook that is run 453853e5d35bSStefano Zampini right before the direction step is computed. 4539ce78bad3SBarry Smith 454053e5d35bSStefano Zampini Users are free to modify the current residual vector, 454153e5d35bSStefano Zampini the current linearization point, or any other vector associated to the specific solver used. 454253e5d35bSStefano Zampini If such modifications take place, it is the user responsibility to update all the relevant 4543ce78bad3SBarry Smith vectors. For example, if one is adjusting the model parameters at each Newton step their code may look like 4544ce78bad3SBarry Smith .vb 4545ce78bad3SBarry Smith PetscErrorCode update(SNES snes, PetscInt iteration) 4546ce78bad3SBarry Smith { 4547ce78bad3SBarry Smith PetscFunctionBeginUser; 4548ce78bad3SBarry Smith if (iteration > 0) { 4549ce78bad3SBarry Smith // update the model parameters here 4550ce78bad3SBarry Smith Vec x,f; 4551ce78bad3SBarry Smith PetscCall(SNESGetSolution(snes,&x)); 4552ce78bad3SBarry Smith PetcCall(SNESGetFunction(snes,&f,NULL,NULL)); 4553ce78bad3SBarry Smith PetscCall(SNESComputeFunction(snes,x,f)); 4554ce78bad3SBarry Smith } 4555ce78bad3SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 4556ce78bad3SBarry Smith } 4557ce78bad3SBarry Smith .ve 455876b2cf59SMatthew Knepley 4559aaa8cc7dSPierre 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. 45606b7fb656SBarry Smith 4561e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetJacobian()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRSetPostCheck()`, 456253e5d35bSStefano Zampini `SNESMonitorSet()` 456376b2cf59SMatthew Knepley @*/ 456453e5d35bSStefano Zampini PetscErrorCode SNESSetUpdate(SNES snes, SNESUpdateFn *func) 4565d71ae5a4SJacob Faibussowitsch { 456676b2cf59SMatthew Knepley PetscFunctionBegin; 45670700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4568e7788613SBarry Smith snes->ops->update = func; 45693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 457076b2cf59SMatthew Knepley } 457176b2cf59SMatthew Knepley 4572ffeef943SBarry Smith /*@ 4573f6dfbefdSBarry Smith SNESConvergedReasonView - Displays the reason a `SNES` solve converged or diverged to a viewer 45742a359c20SBarry Smith 4575c3339decSBarry Smith Collective 45762a359c20SBarry Smith 4577e4094ef1SJacob Faibussowitsch Input Parameters: 4578f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 45792a359c20SBarry Smith - viewer - the viewer to display the reason 45802a359c20SBarry Smith 45812a359c20SBarry Smith Options Database Keys: 4582ee300463SSatish Balay + -snes_converged_reason - print reason for converged or diverged, also prints number of iterations 4583ee300463SSatish Balay - -snes_converged_reason ::failed - only print reason and number of iterations when diverged 4584eafd5ff0SAlex Lindsay 4585420bcc1bSBarry Smith Level: beginner 4586420bcc1bSBarry Smith 4587f6dfbefdSBarry Smith Note: 4588f6dfbefdSBarry Smith To change the format of the output call `PetscViewerPushFormat`(viewer,format) before this call. Use `PETSC_VIEWER_DEFAULT` for the default, 4589f6dfbefdSBarry Smith use `PETSC_VIEWER_FAILED` to only display a reason if it fails. 45902a359c20SBarry Smith 45911cc06b55SBarry Smith .seealso: [](ch_snes), `SNESConvergedReason`, `PetscViewer`, `SNES`, 4592f6dfbefdSBarry Smith `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, 4593f6dfbefdSBarry Smith `SNESConvergedReasonViewFromOptions()`, 4594db781477SPatrick Sanan `PetscViewerPushFormat()`, `PetscViewerPopFormat()` 45952a359c20SBarry Smith @*/ 4596d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonView(SNES snes, PetscViewer viewer) 4597d71ae5a4SJacob Faibussowitsch { 459875cca76cSMatthew G. Knepley PetscViewerFormat format; 45992a359c20SBarry Smith PetscBool isAscii; 46002a359c20SBarry Smith 46012a359c20SBarry Smith PetscFunctionBegin; 460219a666eeSBarry Smith if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)); 46039566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii)); 46042a359c20SBarry Smith if (isAscii) { 46059566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 460665bf60d2SBarry Smith PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel + 1)); 460775cca76cSMatthew G. Knepley if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 460875cca76cSMatthew G. Knepley DM dm; 460975cca76cSMatthew G. Knepley Vec u; 461075cca76cSMatthew G. Knepley PetscDS prob; 461175cca76cSMatthew G. Knepley PetscInt Nf, f; 461295cbbfd3SMatthew G. Knepley PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *); 461395cbbfd3SMatthew G. Knepley void **exactCtx; 461475cca76cSMatthew G. Knepley PetscReal error; 461575cca76cSMatthew G. Knepley 46169566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 46179566063dSJacob Faibussowitsch PetscCall(SNESGetSolution(snes, &u)); 46189566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob)); 46199566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(prob, &Nf)); 46209566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(Nf, &exactSol, Nf, &exactCtx)); 46219566063dSJacob Faibussowitsch for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f])); 46229566063dSJacob Faibussowitsch PetscCall(DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error)); 46239566063dSJacob Faibussowitsch PetscCall(PetscFree2(exactSol, exactCtx)); 46249566063dSJacob Faibussowitsch if (error < 1.0e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n")); 462563a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", (double)error)); 462675cca76cSMatthew G. Knepley } 4627eafd5ff0SAlex Lindsay if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) { 46282a359c20SBarry Smith if (((PetscObject)snes)->prefix) { 462963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter)); 46302a359c20SBarry Smith } else { 463163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve converged due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter)); 46322a359c20SBarry Smith } 4633eafd5ff0SAlex Lindsay } else if (snes->reason <= 0) { 46342a359c20SBarry Smith if (((PetscObject)snes)->prefix) { 463563a3b9bcSJacob 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)); 46362a359c20SBarry Smith } else { 463763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve did not converge due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter)); 46382a359c20SBarry Smith } 46392a359c20SBarry Smith } 464065bf60d2SBarry Smith PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel + 1)); 46412a359c20SBarry Smith } 46423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 46432a359c20SBarry Smith } 46442a359c20SBarry Smith 4645c4421ceaSFande Kong /*@C 4646c4421ceaSFande Kong SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the 4647aaa8cc7dSPierre Jolivet end of the nonlinear solver to display the convergence reason of the nonlinear solver. 4648c4421ceaSFande Kong 4649c3339decSBarry Smith Logically Collective 4650c4421ceaSFande Kong 4651c4421ceaSFande Kong Input Parameters: 4652f6dfbefdSBarry Smith + snes - the `SNES` context 4653420bcc1bSBarry Smith . f - the `SNESConvergedReason` view function 4654420bcc1bSBarry Smith . vctx - [optional] user-defined context for private data for the `SNESConvergedReason` view function (use `NULL` if no context is desired) 465549abdd8aSBarry Smith - reasonviewdestroy - [optional] routine that frees the context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence 4656420bcc1bSBarry Smith 4657420bcc1bSBarry Smith Calling sequence of `f`: 4658420bcc1bSBarry Smith + snes - the `SNES` context 465949abdd8aSBarry Smith - vctx - [optional] context for private data for the function 4660c4421ceaSFande Kong 4661c4421ceaSFande Kong Options Database Keys: 4662f6dfbefdSBarry Smith + -snes_converged_reason - sets a default `SNESConvergedReasonView()` 4663420bcc1bSBarry Smith - -snes_converged_reason_view_cancel - cancels all converged reason viewers that have been hardwired into a code by 4664420bcc1bSBarry Smith calls to `SNESConvergedReasonViewSet()`, but does not cancel those set via the options database. 4665c4421ceaSFande Kong 4666dc4c0fb0SBarry Smith Level: intermediate 4667dc4c0fb0SBarry Smith 4668f6dfbefdSBarry Smith Note: 4669c4421ceaSFande Kong Several different converged reason view routines may be set by calling 4670f6dfbefdSBarry Smith `SNESConvergedReasonViewSet()` multiple times; all will be called in the 4671c4421ceaSFande Kong order in which they were set. 4672c4421ceaSFande Kong 467349abdd8aSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`, `SNESConvergedReasonViewCancel()`, 467449abdd8aSBarry Smith `PetscCtxDestroyFn` 4675c4421ceaSFande Kong @*/ 467649abdd8aSBarry Smith PetscErrorCode SNESConvergedReasonViewSet(SNES snes, PetscErrorCode (*f)(SNES snes, void *vctx), void *vctx, PetscCtxDestroyFn *reasonviewdestroy) 4677d71ae5a4SJacob Faibussowitsch { 4678c4421ceaSFande Kong PetscInt i; 4679c4421ceaSFande Kong PetscBool identical; 4680c4421ceaSFande Kong 4681c4421ceaSFande Kong PetscFunctionBegin; 4682c4421ceaSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4683c4421ceaSFande Kong for (i = 0; i < snes->numberreasonviews; i++) { 46849566063dSJacob Faibussowitsch PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))f, vctx, reasonviewdestroy, (PetscErrorCode (*)(void))snes->reasonview[i], snes->reasonviewcontext[i], snes->reasonviewdestroy[i], &identical)); 46853ba16761SJacob Faibussowitsch if (identical) PetscFunctionReturn(PETSC_SUCCESS); 4686c4421ceaSFande Kong } 46875f80ce2aSJacob Faibussowitsch PetscCheck(snes->numberreasonviews < MAXSNESREASONVIEWS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many SNES reasonview set"); 4688c4421ceaSFande Kong snes->reasonview[snes->numberreasonviews] = f; 4689c4421ceaSFande Kong snes->reasonviewdestroy[snes->numberreasonviews] = reasonviewdestroy; 4690835f2295SStefano Zampini snes->reasonviewcontext[snes->numberreasonviews++] = vctx; 46913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4692c4421ceaSFande Kong } 4693c4421ceaSFande Kong 469491f3e32bSBarry Smith /*@ 4695420bcc1bSBarry Smith SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a `SNESConvergedReason` is to be viewed at the end of `SNESSolve()` 46960b4b7b1cSBarry Smith All the user-provided viewer routines set with `SNESConvergedReasonViewSet()` will be called, if they exist. 46972a359c20SBarry Smith 4698c3339decSBarry Smith Collective 46992a359c20SBarry Smith 47002fe279fdSBarry Smith Input Parameter: 4701f6dfbefdSBarry Smith . snes - the `SNES` object 47022a359c20SBarry Smith 4703f6dfbefdSBarry Smith Level: advanced 47042a359c20SBarry Smith 47051cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESConvergedReasonViewSet()`, `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, 4706f6dfbefdSBarry Smith `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()` 47072a359c20SBarry Smith @*/ 4708d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes) 4709d71ae5a4SJacob Faibussowitsch { 47102a359c20SBarry Smith static PetscBool incall = PETSC_FALSE; 47112a359c20SBarry Smith 47122a359c20SBarry Smith PetscFunctionBegin; 47133ba16761SJacob Faibussowitsch if (incall) PetscFunctionReturn(PETSC_SUCCESS); 47142a359c20SBarry Smith incall = PETSC_TRUE; 4715c4421ceaSFande Kong 4716c4421ceaSFande Kong /* All user-provided viewers are called first, if they exist. */ 471736d43d94SBarry Smith for (PetscInt i = 0; i < snes->numberreasonviews; i++) PetscCall((*snes->reasonview[i])(snes, snes->reasonviewcontext[i])); 4718c4421ceaSFande Kong 4719c4421ceaSFande Kong /* Call PETSc default routine if users ask for it */ 472036d43d94SBarry Smith if (snes->convergedreasonviewer) { 472136d43d94SBarry Smith PetscCall(PetscViewerPushFormat(snes->convergedreasonviewer, snes->convergedreasonformat)); 472236d43d94SBarry Smith PetscCall(SNESConvergedReasonView(snes, snes->convergedreasonviewer)); 472336d43d94SBarry Smith PetscCall(PetscViewerPopFormat(snes->convergedreasonviewer)); 47242a359c20SBarry Smith } 47252a359c20SBarry Smith incall = PETSC_FALSE; 47263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 47272a359c20SBarry Smith } 47282a359c20SBarry Smith 4729487a658cSBarry Smith /*@ 47300b4b7b1cSBarry Smith SNESSolve - Solves a nonlinear system $F(x) = b $ associated with a `SNES` object 47319b94acceSBarry Smith 4732c3339decSBarry Smith Collective 4733c7afd0dbSLois Curfman McInnes 4734b2002411SLois Curfman McInnes Input Parameters: 4735f6dfbefdSBarry Smith + snes - the `SNES` context 47360b4b7b1cSBarry Smith . b - the constant part of the equation $F(x) = b$, or `NULL` to use zero. 473785385478SLisandro Dalcin - x - the solution vector. 47389b94acceSBarry Smith 4739dc4c0fb0SBarry Smith Level: beginner 4740dc4c0fb0SBarry Smith 4741f6dfbefdSBarry Smith Note: 4742420bcc1bSBarry Smith The user should initialize the vector, `x`, with the initial guess 4743a9b45538SStefano Zampini for the nonlinear solve prior to calling `SNESSolve()` . 47448ddd3da0SLois Curfman McInnes 47451cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESSetFunction()`, `SNESSetJacobian()`, `SNESSetGridSequence()`, `SNESGetSolution()`, 4746db781477SPatrick Sanan `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRGetPreCheck()`, `SNESNewtonTRSetPostCheck()`, `SNESNewtonTRGetPostCheck()`, 4747a9b45538SStefano Zampini `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()` 47489b94acceSBarry Smith @*/ 4749d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSolve(SNES snes, Vec b, Vec x) 4750d71ae5a4SJacob Faibussowitsch { 4751ace3abfcSBarry Smith PetscBool flg; 4752efd51863SBarry Smith PetscInt grid; 47530298fd71SBarry Smith Vec xcreated = NULL; 4754caa4e7f2SJed Brown DM dm; 4755052efed2SBarry Smith 47563a40ed3dSBarry Smith PetscFunctionBegin; 47570700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4758a69afd8bSBarry Smith if (x) PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4759a69afd8bSBarry Smith if (x) PetscCheckSameComm(snes, 1, x, 3); 47600700a824SBarry Smith if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 476185385478SLisandro Dalcin if (b) PetscCheckSameComm(snes, 1, b, 2); 476285385478SLisandro Dalcin 476334b4d3a8SMatthew G. Knepley /* High level operations using the nonlinear solver */ 476406fc46c8SMatthew G. Knepley { 476506fc46c8SMatthew G. Knepley PetscViewer viewer; 476606fc46c8SMatthew G. Knepley PetscViewerFormat format; 47677c88af5aSMatthew G. Knepley PetscInt num; 476806fc46c8SMatthew G. Knepley PetscBool flg; 476906fc46c8SMatthew G. Knepley static PetscBool incall = PETSC_FALSE; 477006fc46c8SMatthew G. Knepley 477106fc46c8SMatthew G. Knepley if (!incall) { 477234b4d3a8SMatthew G. Knepley /* Estimate the convergence rate of the discretization */ 4773648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg)); 477406fc46c8SMatthew G. Knepley if (flg) { 477506fc46c8SMatthew G. Knepley PetscConvEst conv; 477646079b62SMatthew G. Knepley DM dm; 477746079b62SMatthew G. Knepley PetscReal *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */ 477846079b62SMatthew G. Knepley PetscInt Nf; 477906fc46c8SMatthew G. Knepley 478006fc46c8SMatthew G. Knepley incall = PETSC_TRUE; 47819566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 47829566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 47839566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(Nf, &alpha)); 47849566063dSJacob Faibussowitsch PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)snes), &conv)); 47859566063dSJacob Faibussowitsch PetscCall(PetscConvEstSetSolver(conv, (PetscObject)snes)); 47869566063dSJacob Faibussowitsch PetscCall(PetscConvEstSetFromOptions(conv)); 47879566063dSJacob Faibussowitsch PetscCall(PetscConvEstSetUp(conv)); 47889566063dSJacob Faibussowitsch PetscCall(PetscConvEstGetConvRate(conv, alpha)); 47899566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(viewer, format)); 47909566063dSJacob Faibussowitsch PetscCall(PetscConvEstRateView(conv, alpha, viewer)); 47919566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer)); 4792648c30bcSBarry Smith PetscCall(PetscViewerDestroy(&viewer)); 47939566063dSJacob Faibussowitsch PetscCall(PetscConvEstDestroy(&conv)); 47949566063dSJacob Faibussowitsch PetscCall(PetscFree(alpha)); 479506fc46c8SMatthew G. Knepley incall = PETSC_FALSE; 479606fc46c8SMatthew G. Knepley } 479734b4d3a8SMatthew G. Knepley /* Adaptively refine the initial grid */ 4798b2588ea6SMatthew G. Knepley num = 1; 47999566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_initial", &num, &flg)); 480034b4d3a8SMatthew G. Knepley if (flg) { 480134b4d3a8SMatthew G. Knepley DMAdaptor adaptor; 480234b4d3a8SMatthew G. Knepley 480334b4d3a8SMatthew G. Knepley incall = PETSC_TRUE; 48049566063dSJacob Faibussowitsch PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor)); 48059566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSolver(adaptor, snes)); 48069566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSequenceLength(adaptor, num)); 48079566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetFromOptions(adaptor)); 48089566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetUp(adaptor)); 48099566063dSJacob Faibussowitsch PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x)); 48109566063dSJacob Faibussowitsch PetscCall(DMAdaptorDestroy(&adaptor)); 481134b4d3a8SMatthew G. Knepley incall = PETSC_FALSE; 481234b4d3a8SMatthew G. Knepley } 48137c88af5aSMatthew G. Knepley /* Use grid sequencing to adapt */ 48147c88af5aSMatthew G. Knepley num = 0; 48159566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_sequence", &num, NULL)); 48167c88af5aSMatthew G. Knepley if (num) { 48177c88af5aSMatthew G. Knepley DMAdaptor adaptor; 4818e03fd340SMatthew G. Knepley const char *prefix; 48197c88af5aSMatthew G. Knepley 48207c88af5aSMatthew G. Knepley incall = PETSC_TRUE; 48219566063dSJacob Faibussowitsch PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor)); 4822e03fd340SMatthew G. Knepley PetscCall(SNESGetOptionsPrefix(snes, &prefix)); 4823e03fd340SMatthew G. Knepley PetscCall(DMAdaptorSetOptionsPrefix(adaptor, prefix)); 48249566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSolver(adaptor, snes)); 48259566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSequenceLength(adaptor, num)); 48269566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetFromOptions(adaptor)); 48279566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetUp(adaptor)); 4828e5148a0bSMatthew G. Knepley PetscCall(PetscObjectViewFromOptions((PetscObject)adaptor, NULL, "-snes_adapt_view")); 48299566063dSJacob Faibussowitsch PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x)); 48309566063dSJacob Faibussowitsch PetscCall(DMAdaptorDestroy(&adaptor)); 48317c88af5aSMatthew G. Knepley incall = PETSC_FALSE; 48327c88af5aSMatthew G. Knepley } 483306fc46c8SMatthew G. Knepley } 483406fc46c8SMatthew G. Knepley } 4835ad540459SPierre Jolivet if (!x) x = snes->vec_sol; 4836caa4e7f2SJed Brown if (!x) { 48379566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 48389566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dm, &xcreated)); 4839a69afd8bSBarry Smith x = xcreated; 4840a69afd8bSBarry Smith } 48419566063dSJacob Faibussowitsch PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view_pre")); 4842f05ece33SBarry Smith 48439566063dSJacob Faibussowitsch for (grid = 0; grid < snes->gridsequence; grid++) PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)))); 4844efd51863SBarry Smith for (grid = 0; grid < snes->gridsequence + 1; grid++) { 484585385478SLisandro Dalcin /* set solution vector */ 48469566063dSJacob Faibussowitsch if (!grid) PetscCall(PetscObjectReference((PetscObject)x)); 48479566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol)); 484885385478SLisandro Dalcin snes->vec_sol = x; 48499566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 4850caa4e7f2SJed Brown 4851caa4e7f2SJed Brown /* set affine vector if provided */ 48529566063dSJacob Faibussowitsch if (b) PetscCall(PetscObjectReference((PetscObject)b)); 48539566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_rhs)); 485485385478SLisandro Dalcin snes->vec_rhs = b; 485585385478SLisandro Dalcin 48565f80ce2aSJacob 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"); 48575f80ce2aSJacob Faibussowitsch PetscCheck(snes->vec_func != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be function vector"); 4858dd8e379bSPierre Jolivet PetscCheck(snes->vec_rhs != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be right-hand side vector"); 4859aa624791SPierre Jolivet if (!snes->vec_sol_update /* && snes->vec_sol */) PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_sol_update)); 48609566063dSJacob Faibussowitsch PetscCall(DMShellSetGlobalVector(dm, snes->vec_sol)); 48619566063dSJacob Faibussowitsch PetscCall(SNESSetUp(snes)); 48623f149594SLisandro Dalcin 48637eee914bSBarry Smith if (!grid) { 48649927e4dfSBarry Smith if (snes->ops->computeinitialguess) PetscCallBack("SNES callback compute initial guess", (*snes->ops->computeinitialguess)(snes, snes->vec_sol, snes->initialguessP)); 4865dd568438SSatish Balay } 4866d25893d9SBarry Smith 4867abc0a331SBarry Smith if (snes->conv_hist_reset) snes->conv_hist_len = 0; 486812b1dd1aSStefano Zampini PetscCall(SNESResetCounters(snes)); 48692d157150SStefano Zampini snes->reason = SNES_CONVERGED_ITERATING; 48709566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_Solve, snes, 0, 0, 0)); 4871dbbe0bcdSBarry Smith PetscUseTypeMethod(snes, solve); 48729566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_Solve, snes, 0, 0, 0)); 48732d157150SStefano Zampini PetscCheck(snes->reason, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error, solver %s returned without setting converged reason", ((PetscObject)snes)->type_name); 4874422a814eSBarry Smith snes->domainerror = PETSC_FALSE; /* clear the flag if it has been set */ 48753f149594SLisandro Dalcin 487637ec4e1aSPeter Brune if (snes->lagjac_persist) snes->jac_iter += snes->iter; 487737ec4e1aSPeter Brune if (snes->lagpre_persist) snes->pre_iter += snes->iter; 487837ec4e1aSPeter Brune 4879648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_test_local_min", NULL, NULL, &flg)); 48809566063dSJacob Faibussowitsch if (flg && !PetscPreLoadingOn) PetscCall(SNESTestLocalMin(snes)); 4881c4421ceaSFande Kong /* Call converged reason views. This may involve user-provided viewers as well */ 48829566063dSJacob Faibussowitsch PetscCall(SNESConvergedReasonViewFromOptions(snes)); 48835968eb51SBarry Smith 48845f80ce2aSJacob Faibussowitsch if (snes->errorifnotconverged) PetscCheck(snes->reason >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_NOT_CONVERGED, "SNESSolve has not converged"); 48859c8e83a9SBarry Smith if (snes->reason < 0) break; 4886efd51863SBarry Smith if (grid < snes->gridsequence) { 4887efd51863SBarry Smith DM fine; 4888efd51863SBarry Smith Vec xnew; 4889efd51863SBarry Smith Mat interp; 4890efd51863SBarry Smith 48919566063dSJacob Faibussowitsch PetscCall(DMRefine(snes->dm, PetscObjectComm((PetscObject)snes), &fine)); 48925f80ce2aSJacob Faibussowitsch PetscCheck(fine, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_INCOMP, "DMRefine() did not perform any refinement, cannot continue grid sequencing"); 48932eace19aSMatthew G. Knepley PetscCall(DMGetCoordinatesLocalSetUp(fine)); 48949566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(snes->dm, fine, &interp, NULL)); 48959566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(fine, &xnew)); 48969566063dSJacob Faibussowitsch PetscCall(MatInterpolate(interp, x, xnew)); 48979566063dSJacob Faibussowitsch PetscCall(DMInterpolate(snes->dm, interp, fine)); 48989566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interp)); 4899efd51863SBarry Smith x = xnew; 4900efd51863SBarry Smith 49019566063dSJacob Faibussowitsch PetscCall(SNESReset(snes)); 49029566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes, fine)); 49039566063dSJacob Faibussowitsch PetscCall(SNESResetFromOptions(snes)); 49049566063dSJacob Faibussowitsch PetscCall(DMDestroy(&fine)); 49059566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)))); 4906efd51863SBarry Smith } 4907efd51863SBarry Smith } 49089566063dSJacob Faibussowitsch PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view")); 49099566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(snes->vec_sol, (PetscObject)snes, "-snes_view_solution")); 49109566063dSJacob Faibussowitsch PetscCall(DMMonitor(snes->dm)); 49119566063dSJacob Faibussowitsch PetscCall(SNESMonitorPauseFinal_Internal(snes)); 49123f7e2da0SPeter Brune 49139566063dSJacob Faibussowitsch PetscCall(VecDestroy(&xcreated)); 49149566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsBlock((PetscObject)snes)); 49153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49169b94acceSBarry Smith } 49179b94acceSBarry Smith 49189b94acceSBarry Smith /* --------- Internal routines for SNES Package --------- */ 49199b94acceSBarry Smith 4920cc4c1da9SBarry Smith /*@ 49210b4b7b1cSBarry Smith SNESSetType - Sets the algorithm/method to be used to solve the nonlinear system with the given `SNES` 49229b94acceSBarry Smith 4923c3339decSBarry Smith Collective 4924fee21e36SBarry Smith 4925c7afd0dbSLois Curfman McInnes Input Parameters: 4926f6dfbefdSBarry Smith + snes - the `SNES` context 4927454a90a3SBarry Smith - type - a known method 4928c7afd0dbSLois Curfman McInnes 4929c7afd0dbSLois Curfman McInnes Options Database Key: 4930454a90a3SBarry Smith . -snes_type <type> - Sets the method; use -help for a list 493104d7464bSBarry Smith of available methods (for instance, newtonls or newtontr) 4932ae12b187SLois Curfman McInnes 4933dc4c0fb0SBarry Smith Level: intermediate 4934dc4c0fb0SBarry Smith 49359b94acceSBarry Smith Notes: 49360b4b7b1cSBarry Smith See `SNESType` for available methods (for instance) 4937f6dfbefdSBarry Smith + `SNESNEWTONLS` - Newton's method with line search 4938c7afd0dbSLois Curfman McInnes (systems of nonlinear equations) 49394a221d59SStefano Zampini - `SNESNEWTONTR` - Newton's method with trust region 4940c7afd0dbSLois Curfman McInnes (systems of nonlinear equations) 49419b94acceSBarry Smith 4942f6dfbefdSBarry Smith Normally, it is best to use the `SNESSetFromOptions()` command and then 4943f6dfbefdSBarry Smith set the `SNES` solver type from the options database rather than by using 4944ae12b187SLois Curfman McInnes this routine. Using the options database provides the user with 4945ae12b187SLois Curfman McInnes maximum flexibility in evaluating the many nonlinear solvers. 4946f6dfbefdSBarry Smith The `SNESSetType()` routine is provided for those situations where it 4947ae12b187SLois Curfman McInnes is necessary to set the nonlinear solver independently of the command 4948ae12b187SLois Curfman McInnes line or options database. This might be the case, for example, when 4949ae12b187SLois Curfman McInnes the choice of solver changes during the execution of the program, 4950ae12b187SLois Curfman McInnes and the user's application is taking responsibility for choosing the 4951b0a32e0cSBarry Smith appropriate method. 495236851e7fSLois Curfman McInnes 4953420bcc1bSBarry Smith Developer Note: 4954f6dfbefdSBarry Smith `SNESRegister()` adds a constructor for a new `SNESType` to `SNESList`, `SNESSetType()` locates 4955f6dfbefdSBarry Smith the constructor in that list and calls it to create the specific object. 49568f6c3df8SBarry Smith 49571cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESType`, `SNESCreate()`, `SNESDestroy()`, `SNESGetType()`, `SNESSetFromOptions()` 49589b94acceSBarry Smith @*/ 4959d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetType(SNES snes, SNESType type) 4960d71ae5a4SJacob Faibussowitsch { 4961ace3abfcSBarry Smith PetscBool match; 49625f80ce2aSJacob Faibussowitsch PetscErrorCode (*r)(SNES); 49633a40ed3dSBarry Smith 49643a40ed3dSBarry Smith PetscFunctionBegin; 49650700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 49664f572ea9SToby Isaac PetscAssertPointer(type, 2); 496782bf6240SBarry Smith 49689566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes, type, &match)); 49693ba16761SJacob Faibussowitsch if (match) PetscFunctionReturn(PETSC_SUCCESS); 497092ff6ae8SBarry Smith 49719566063dSJacob Faibussowitsch PetscCall(PetscFunctionListFind(SNESList, type, &r)); 49726adde796SStefano Zampini PetscCheck(r, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested SNES type %s", type); 497375396ef9SLisandro Dalcin /* Destroy the previous private SNES context */ 4974dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, destroy); 497543547594SStefano Zampini /* Reinitialize type-specific function pointers in SNESOps structure */ 497643547594SStefano Zampini snes->ops->reset = NULL; 49779e5d0892SLisandro Dalcin snes->ops->setup = NULL; 49789e5d0892SLisandro Dalcin snes->ops->solve = NULL; 49799e5d0892SLisandro Dalcin snes->ops->view = NULL; 49809e5d0892SLisandro Dalcin snes->ops->setfromoptions = NULL; 49819e5d0892SLisandro Dalcin snes->ops->destroy = NULL; 49827fe760d5SStefano Zampini 49837fe760d5SStefano Zampini /* It may happen the user has customized the line search before calling SNESSetType */ 49849566063dSJacob Faibussowitsch if (((PetscObject)snes)->type_name) PetscCall(SNESLineSearchDestroy(&snes->linesearch)); 49857fe760d5SStefano Zampini 498675396ef9SLisandro Dalcin /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */ 498775396ef9SLisandro Dalcin snes->setupcalled = PETSC_FALSE; 4988f5af7f23SKarl Rupp 49899566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)snes, type)); 49909566063dSJacob Faibussowitsch PetscCall((*r)(snes)); 49913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49929b94acceSBarry Smith } 49939b94acceSBarry Smith 4994cc4c1da9SBarry Smith /*@ 4995f6dfbefdSBarry Smith SNESGetType - Gets the `SNES` method type and name (as a string). 49969b94acceSBarry Smith 4997c7afd0dbSLois Curfman McInnes Not Collective 4998c7afd0dbSLois Curfman McInnes 49999b94acceSBarry Smith Input Parameter: 50004b0e389bSBarry Smith . snes - nonlinear solver context 50019b94acceSBarry Smith 50029b94acceSBarry Smith Output Parameter: 5003f6dfbefdSBarry Smith . type - `SNES` method (a character string) 50049b94acceSBarry Smith 500536851e7fSLois Curfman McInnes Level: intermediate 500636851e7fSLois Curfman McInnes 50071cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetType()`, `SNESType`, `SNESSetFromOptions()`, `SNES` 50089b94acceSBarry Smith @*/ 5009d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetType(SNES snes, SNESType *type) 5010d71ae5a4SJacob Faibussowitsch { 50113a40ed3dSBarry Smith PetscFunctionBegin; 50120700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 50134f572ea9SToby Isaac PetscAssertPointer(type, 2); 50147adad957SLisandro Dalcin *type = ((PetscObject)snes)->type_name; 50153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50169b94acceSBarry Smith } 50179b94acceSBarry Smith 50183cd8a7caSMatthew G. Knepley /*@ 5019f6dfbefdSBarry Smith SNESSetSolution - Sets the solution vector for use by the `SNES` routines. 50203cd8a7caSMatthew G. Knepley 5021c3339decSBarry Smith Logically Collective 50223cd8a7caSMatthew G. Knepley 50233cd8a7caSMatthew G. Knepley Input Parameters: 5024f6dfbefdSBarry Smith + snes - the `SNES` context obtained from `SNESCreate()` 50253cd8a7caSMatthew G. Knepley - u - the solution vector 50263cd8a7caSMatthew G. Knepley 50273cd8a7caSMatthew G. Knepley Level: beginner 50283cd8a7caSMatthew G. Knepley 50291cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetSolution()`, `Vec` 50303cd8a7caSMatthew G. Knepley @*/ 5031d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetSolution(SNES snes, Vec u) 5032d71ae5a4SJacob Faibussowitsch { 50333cd8a7caSMatthew G. Knepley DM dm; 50343cd8a7caSMatthew G. Knepley 50353cd8a7caSMatthew G. Knepley PetscFunctionBegin; 50363cd8a7caSMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 50373cd8a7caSMatthew G. Knepley PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 50389566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)u)); 50399566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol)); 50403cd8a7caSMatthew G. Knepley 50413cd8a7caSMatthew G. Knepley snes->vec_sol = u; 50423cd8a7caSMatthew G. Knepley 50439566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 50449566063dSJacob Faibussowitsch PetscCall(DMShellSetGlobalVector(dm, u)); 50453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50463cd8a7caSMatthew G. Knepley } 50473cd8a7caSMatthew G. Knepley 504852baeb72SSatish Balay /*@ 50499b94acceSBarry Smith SNESGetSolution - Returns the vector where the approximate solution is 5050f6dfbefdSBarry Smith stored. This is the fine grid solution when using `SNESSetGridSequence()`. 50519b94acceSBarry Smith 5052420bcc1bSBarry Smith Not Collective, but `x` is parallel if `snes` is parallel 5053c7afd0dbSLois Curfman McInnes 50549b94acceSBarry Smith Input Parameter: 5055f6dfbefdSBarry Smith . snes - the `SNES` context 50569b94acceSBarry Smith 50579b94acceSBarry Smith Output Parameter: 50589b94acceSBarry Smith . x - the solution 50599b94acceSBarry Smith 506070e92668SMatthew Knepley Level: intermediate 506136851e7fSLois Curfman McInnes 50621cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetSolution()`, `SNESSolve()`, `SNES`, `SNESGetSolutionUpdate()`, `SNESGetFunction()` 50639b94acceSBarry Smith @*/ 5064d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolution(SNES snes, Vec *x) 5065d71ae5a4SJacob Faibussowitsch { 50663a40ed3dSBarry Smith PetscFunctionBegin; 50670700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 50684f572ea9SToby Isaac PetscAssertPointer(x, 2); 506985385478SLisandro Dalcin *x = snes->vec_sol; 50703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 507170e92668SMatthew Knepley } 507270e92668SMatthew Knepley 507352baeb72SSatish Balay /*@ 50749b94acceSBarry Smith SNESGetSolutionUpdate - Returns the vector where the solution update is 50759b94acceSBarry Smith stored. 50769b94acceSBarry Smith 5077420bcc1bSBarry Smith Not Collective, but `x` is parallel if `snes` is parallel 5078c7afd0dbSLois Curfman McInnes 50799b94acceSBarry Smith Input Parameter: 5080f6dfbefdSBarry Smith . snes - the `SNES` context 50819b94acceSBarry Smith 50829b94acceSBarry Smith Output Parameter: 50839b94acceSBarry Smith . x - the solution update 50849b94acceSBarry Smith 508536851e7fSLois Curfman McInnes Level: advanced 508636851e7fSLois Curfman McInnes 50871cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()` 50889b94acceSBarry Smith @*/ 5089d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionUpdate(SNES snes, Vec *x) 5090d71ae5a4SJacob Faibussowitsch { 50913a40ed3dSBarry Smith PetscFunctionBegin; 50920700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 50934f572ea9SToby Isaac PetscAssertPointer(x, 2); 509485385478SLisandro Dalcin *x = snes->vec_sol_update; 50953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50969b94acceSBarry Smith } 50979b94acceSBarry Smith 50989b94acceSBarry Smith /*@C 5099f6dfbefdSBarry Smith SNESGetFunction - Returns the function that defines the nonlinear system set with `SNESSetFunction()` 51009b94acceSBarry Smith 5101420bcc1bSBarry Smith Not Collective, but `r` is parallel if `snes` is parallel. Collective if `r` is requested, but has not been created yet. 5102c7afd0dbSLois Curfman McInnes 51039b94acceSBarry Smith Input Parameter: 5104f6dfbefdSBarry Smith . snes - the `SNES` context 51059b94acceSBarry Smith 5106d8d19677SJose E. Roman Output Parameters: 5107dc4c0fb0SBarry Smith + r - the vector that is used to store residuals (or `NULL` if you don't want it) 51088434afd1SBarry Smith . f - the function (or `NULL` if you don't want it); for calling sequence see `SNESFunctionFn` 5109dc4c0fb0SBarry Smith - ctx - the function context (or `NULL` if you don't want it) 51109b94acceSBarry Smith 511136851e7fSLois Curfman McInnes Level: advanced 511236851e7fSLois Curfman McInnes 5113f6dfbefdSBarry Smith Note: 5114dc4c0fb0SBarry Smith The vector `r` DOES NOT, in general, contain the current value of the `SNES` nonlinear function 511504edfde5SBarry Smith 51168434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetSolution()`, `SNESFunctionFn` 51179b94acceSBarry Smith @*/ 51188434afd1SBarry Smith PetscErrorCode SNESGetFunction(SNES snes, Vec *r, SNESFunctionFn **f, void **ctx) 5119d71ae5a4SJacob Faibussowitsch { 51206cab3a1bSJed Brown DM dm; 5121a63bb30eSJed Brown 51223a40ed3dSBarry Smith PetscFunctionBegin; 51230700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5124a63bb30eSJed Brown if (r) { 5125a63bb30eSJed Brown if (!snes->vec_func) { 5126a63bb30eSJed Brown if (snes->vec_rhs) { 51279566063dSJacob Faibussowitsch PetscCall(VecDuplicate(snes->vec_rhs, &snes->vec_func)); 5128a63bb30eSJed Brown } else if (snes->vec_sol) { 51299566063dSJacob Faibussowitsch PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_func)); 5130a63bb30eSJed Brown } else if (snes->dm) { 51319566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(snes->dm, &snes->vec_func)); 5132a63bb30eSJed Brown } 5133a63bb30eSJed Brown } 5134a63bb30eSJed Brown *r = snes->vec_func; 5135a63bb30eSJed Brown } 51369566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 51379566063dSJacob Faibussowitsch PetscCall(DMSNESGetFunction(dm, f, ctx)); 51383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 51399b94acceSBarry Smith } 51409b94acceSBarry Smith 5141c79ef259SPeter Brune /*@C 514237fdd005SBarry Smith SNESGetNGS - Returns the function and context set with `SNESSetNGS()` 5143c79ef259SPeter Brune 5144c79ef259SPeter Brune Input Parameter: 5145f6dfbefdSBarry Smith . snes - the `SNES` context 5146c79ef259SPeter Brune 5147d8d19677SJose E. Roman Output Parameters: 51488434afd1SBarry Smith + f - the function (or `NULL`) see `SNESNGSFn` for calling sequence 5149dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`) 5150c79ef259SPeter Brune 5151c79ef259SPeter Brune Level: advanced 5152c79ef259SPeter Brune 51538434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetNGS()`, `SNESGetFunction()`, `SNESNGSFn` 5154c79ef259SPeter Brune @*/ 51558434afd1SBarry Smith PetscErrorCode SNESGetNGS(SNES snes, SNESNGSFn **f, void **ctx) 5156d71ae5a4SJacob Faibussowitsch { 51576cab3a1bSJed Brown DM dm; 51586cab3a1bSJed Brown 5159646217ecSPeter Brune PetscFunctionBegin; 5160646217ecSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 51619566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 51629566063dSJacob Faibussowitsch PetscCall(DMSNESGetNGS(dm, f, ctx)); 51633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5164646217ecSPeter Brune } 5165646217ecSPeter Brune 5166cc4c1da9SBarry Smith /*@ 51673c7409f5SSatish Balay SNESSetOptionsPrefix - Sets the prefix used for searching for all 5168f6dfbefdSBarry Smith `SNES` options in the database. 51693c7409f5SSatish Balay 5170c3339decSBarry Smith Logically Collective 5171fee21e36SBarry Smith 5172d8d19677SJose E. Roman Input Parameters: 5173f6dfbefdSBarry Smith + snes - the `SNES` context 5174c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names 5175c7afd0dbSLois Curfman McInnes 5176dc4c0fb0SBarry Smith Level: advanced 5177dc4c0fb0SBarry Smith 5178f6dfbefdSBarry Smith Note: 5179a83b1b31SSatish Balay A hyphen (-) must NOT be given at the beginning of the prefix name. 5180c7afd0dbSLois Curfman McInnes The first character of all runtime options is AUTOMATICALLY the hyphen. 5181d850072dSLois Curfman McInnes 51821cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESAppendOptionsPrefix()` 51833c7409f5SSatish Balay @*/ 5184d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetOptionsPrefix(SNES snes, const char prefix[]) 5185d71ae5a4SJacob Faibussowitsch { 51863a40ed3dSBarry Smith PetscFunctionBegin; 51870700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 51889566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes, prefix)); 51899566063dSJacob Faibussowitsch if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 519035f5d045SPeter Brune if (snes->linesearch) { 51919566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 51929566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch, prefix)); 519335f5d045SPeter Brune } 51949566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(snes->ksp, prefix)); 51953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 51963c7409f5SSatish Balay } 51973c7409f5SSatish Balay 5198cc4c1da9SBarry Smith /*@ 5199f525115eSLois Curfman McInnes SNESAppendOptionsPrefix - Appends to the prefix used for searching for all 5200f6dfbefdSBarry Smith `SNES` options in the database. 52013c7409f5SSatish Balay 5202c3339decSBarry Smith Logically Collective 5203fee21e36SBarry Smith 5204c7afd0dbSLois Curfman McInnes Input Parameters: 5205f6dfbefdSBarry Smith + snes - the `SNES` context 5206c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names 5207c7afd0dbSLois Curfman McInnes 5208dc4c0fb0SBarry Smith Level: advanced 5209dc4c0fb0SBarry Smith 5210f6dfbefdSBarry Smith Note: 5211a83b1b31SSatish Balay A hyphen (-) must NOT be given at the beginning of the prefix name. 5212c7afd0dbSLois Curfman McInnes The first character of all runtime options is AUTOMATICALLY the hyphen. 5213d850072dSLois Curfman McInnes 52141cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetOptionsPrefix()`, `SNESSetOptionsPrefix()` 52153c7409f5SSatish Balay @*/ 5216d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESAppendOptionsPrefix(SNES snes, const char prefix[]) 5217d71ae5a4SJacob Faibussowitsch { 52183a40ed3dSBarry Smith PetscFunctionBegin; 52190700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 52209566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes, prefix)); 52219566063dSJacob Faibussowitsch if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 522235f5d045SPeter Brune if (snes->linesearch) { 52239566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 52249566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch, prefix)); 522535f5d045SPeter Brune } 52269566063dSJacob Faibussowitsch PetscCall(KSPAppendOptionsPrefix(snes->ksp, prefix)); 52273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 52283c7409f5SSatish Balay } 52293c7409f5SSatish Balay 5230cc4c1da9SBarry Smith /*@ 5231f6dfbefdSBarry Smith SNESGetOptionsPrefix - Gets the prefix used for searching for all 5232f6dfbefdSBarry Smith `SNES` options in the database. 52333c7409f5SSatish Balay 5234c7afd0dbSLois Curfman McInnes Not Collective 5235c7afd0dbSLois Curfman McInnes 52363c7409f5SSatish Balay Input Parameter: 5237f6dfbefdSBarry Smith . snes - the `SNES` context 52383c7409f5SSatish Balay 52393c7409f5SSatish Balay Output Parameter: 52403c7409f5SSatish Balay . prefix - pointer to the prefix string used 52413c7409f5SSatish Balay 524236851e7fSLois Curfman McInnes Level: advanced 524336851e7fSLois Curfman McInnes 52441cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetOptionsPrefix()`, `SNESAppendOptionsPrefix()` 52453c7409f5SSatish Balay @*/ 5246d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetOptionsPrefix(SNES snes, const char *prefix[]) 5247d71ae5a4SJacob Faibussowitsch { 52483a40ed3dSBarry Smith PetscFunctionBegin; 52490700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 52509566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)snes, prefix)); 52513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 52523c7409f5SSatish Balay } 52533c7409f5SSatish Balay 52543cea93caSBarry Smith /*@C 52551c84c290SBarry Smith SNESRegister - Adds a method to the nonlinear solver package. 52561c84c290SBarry Smith 525720f4b53cSBarry Smith Not Collective 52581c84c290SBarry Smith 52591c84c290SBarry Smith Input Parameters: 526020f4b53cSBarry Smith + sname - name of a new user-defined solver 526120f4b53cSBarry Smith - function - routine to create method context 52621c84c290SBarry Smith 5263dc4c0fb0SBarry Smith Level: advanced 5264dc4c0fb0SBarry Smith 5265f6dfbefdSBarry Smith Note: 5266f6dfbefdSBarry Smith `SNESRegister()` may be called multiple times to add several user-defined solvers. 52671c84c290SBarry Smith 5268e4094ef1SJacob Faibussowitsch Example Usage: 52691c84c290SBarry Smith .vb 5270bdf89e91SBarry Smith SNESRegister("my_solver", MySolverCreate); 52711c84c290SBarry Smith .ve 52721c84c290SBarry Smith 52731c84c290SBarry Smith Then, your solver can be chosen with the procedural interface via 5274b44f4de4SBarry Smith .vb 5275b44f4de4SBarry Smith SNESSetType(snes, "my_solver") 5276b44f4de4SBarry Smith .ve 52771c84c290SBarry Smith or at runtime via the option 5278b44f4de4SBarry Smith .vb 5279b44f4de4SBarry Smith -snes_type my_solver 5280b44f4de4SBarry Smith .ve 52811c84c290SBarry Smith 52821cc06b55SBarry Smith .seealso: [](ch_snes), `SNESRegisterAll()`, `SNESRegisterDestroy()` 52833cea93caSBarry Smith @*/ 5284d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESRegister(const char sname[], PetscErrorCode (*function)(SNES)) 5285d71ae5a4SJacob Faibussowitsch { 5286b2002411SLois Curfman McInnes PetscFunctionBegin; 52879566063dSJacob Faibussowitsch PetscCall(SNESInitializePackage()); 52889566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&SNESList, sname, function)); 52893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5290b2002411SLois Curfman McInnes } 5291da9b6338SBarry Smith 5292d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestLocalMin(SNES snes) 5293d71ae5a4SJacob Faibussowitsch { 529477431f27SBarry Smith PetscInt N, i, j; 5295da9b6338SBarry Smith Vec u, uh, fh; 5296da9b6338SBarry Smith PetscScalar value; 5297da9b6338SBarry Smith PetscReal norm; 5298da9b6338SBarry Smith 5299da9b6338SBarry Smith PetscFunctionBegin; 53009566063dSJacob Faibussowitsch PetscCall(SNESGetSolution(snes, &u)); 53019566063dSJacob Faibussowitsch PetscCall(VecDuplicate(u, &uh)); 53029566063dSJacob Faibussowitsch PetscCall(VecDuplicate(u, &fh)); 5303da9b6338SBarry Smith 5304da9b6338SBarry Smith /* currently only works for sequential */ 53059566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Testing FormFunction() for local min\n")); 53069566063dSJacob Faibussowitsch PetscCall(VecGetSize(u, &N)); 5307da9b6338SBarry Smith for (i = 0; i < N; i++) { 53089566063dSJacob Faibussowitsch PetscCall(VecCopy(u, uh)); 530963a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "i = %" PetscInt_FMT "\n", i)); 5310da9b6338SBarry Smith for (j = -10; j < 11; j++) { 53118b49ba18SBarry Smith value = PetscSign(j) * PetscExpReal(PetscAbs(j) - 10.0); 53129566063dSJacob Faibussowitsch PetscCall(VecSetValue(uh, i, value, ADD_VALUES)); 53139566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, uh, fh)); 53149566063dSJacob Faibussowitsch PetscCall(VecNorm(fh, NORM_2, &norm)); 531563a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), " j norm %" PetscInt_FMT " %18.16e\n", j, (double)norm)); 5316da9b6338SBarry Smith value = -value; 53179566063dSJacob Faibussowitsch PetscCall(VecSetValue(uh, i, value, ADD_VALUES)); 5318da9b6338SBarry Smith } 5319da9b6338SBarry Smith } 53209566063dSJacob Faibussowitsch PetscCall(VecDestroy(&uh)); 53219566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fh)); 53223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5323da9b6338SBarry Smith } 532471f87433Sdalcinl 532571f87433Sdalcinl /*@ 5326f6dfbefdSBarry Smith SNESKSPSetUseEW - Sets `SNES` to the use Eisenstat-Walker method for 532771f87433Sdalcinl computing relative tolerance for linear solvers within an inexact 532871f87433Sdalcinl Newton method. 532971f87433Sdalcinl 5330c3339decSBarry Smith Logically Collective 533171f87433Sdalcinl 533271f87433Sdalcinl Input Parameters: 5333f6dfbefdSBarry Smith + snes - `SNES` context 5334f6dfbefdSBarry Smith - flag - `PETSC_TRUE` or `PETSC_FALSE` 533571f87433Sdalcinl 5336f6dfbefdSBarry Smith Options Database Keys: 533764ba62caSBarry Smith + -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence 533864ba62caSBarry Smith . -snes_ksp_ew_version ver - version of Eisenstat-Walker method 533964ba62caSBarry Smith . -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0 534064ba62caSBarry Smith . -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax 534164ba62caSBarry Smith . -snes_ksp_ew_gamma <gamma> - Sets gamma 534264ba62caSBarry Smith . -snes_ksp_ew_alpha <alpha> - Sets alpha 534364ba62caSBarry Smith . -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2 534464ba62caSBarry Smith - -snes_ksp_ew_threshold <threshold> - Sets threshold 534564ba62caSBarry Smith 5346dc4c0fb0SBarry Smith Level: advanced 5347dc4c0fb0SBarry Smith 5348f6dfbefdSBarry Smith Note: 5349f6dfbefdSBarry Smith The default is to use a constant relative tolerance for 535071f87433Sdalcinl the inner linear solvers. Alternatively, one can use the 53511d27aa22SBarry Smith Eisenstat-Walker method {cite}`ew96`, where the relative convergence tolerance 535271f87433Sdalcinl is reset at each Newton iteration according progress of the nonlinear 535371f87433Sdalcinl solver. 535471f87433Sdalcinl 53551cc06b55SBarry Smith .seealso: [](ch_snes), `KSP`, `SNES`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()` 535671f87433Sdalcinl @*/ 5357d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetUseEW(SNES snes, PetscBool flag) 5358d71ae5a4SJacob Faibussowitsch { 535971f87433Sdalcinl PetscFunctionBegin; 53600700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5361acfcf0e5SJed Brown PetscValidLogicalCollectiveBool(snes, flag, 2); 536271f87433Sdalcinl snes->ksp_ewconv = flag; 53633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 536471f87433Sdalcinl } 536571f87433Sdalcinl 536671f87433Sdalcinl /*@ 5367f6dfbefdSBarry Smith SNESKSPGetUseEW - Gets if `SNES` is using Eisenstat-Walker method 536871f87433Sdalcinl for computing relative tolerance for linear solvers within an 536971f87433Sdalcinl inexact Newton method. 537071f87433Sdalcinl 537171f87433Sdalcinl Not Collective 537271f87433Sdalcinl 537371f87433Sdalcinl Input Parameter: 5374f6dfbefdSBarry Smith . snes - `SNES` context 537571f87433Sdalcinl 537671f87433Sdalcinl Output Parameter: 5377f6dfbefdSBarry Smith . flag - `PETSC_TRUE` or `PETSC_FALSE` 537871f87433Sdalcinl 537971f87433Sdalcinl Level: advanced 538071f87433Sdalcinl 53811cc06b55SBarry Smith .seealso: [](ch_snes), `SNESKSPSetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()` 538271f87433Sdalcinl @*/ 5383d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag) 5384d71ae5a4SJacob Faibussowitsch { 538571f87433Sdalcinl PetscFunctionBegin; 53860700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 53874f572ea9SToby Isaac PetscAssertPointer(flag, 2); 538871f87433Sdalcinl *flag = snes->ksp_ewconv; 53893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 539071f87433Sdalcinl } 539171f87433Sdalcinl 539271f87433Sdalcinl /*@ 5393fa9f3622SBarry Smith SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker 539471f87433Sdalcinl convergence criteria for the linear solvers within an inexact 539571f87433Sdalcinl Newton method. 539671f87433Sdalcinl 5397c3339decSBarry Smith Logically Collective 539871f87433Sdalcinl 539971f87433Sdalcinl Input Parameters: 5400f6dfbefdSBarry Smith + snes - `SNES` context 54010f0abf79SStefano Zampini . version - version 1, 2 (default is 2), 3 or 4 540271f87433Sdalcinl . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 540371f87433Sdalcinl . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 540471f87433Sdalcinl . gamma - multiplicative factor for version 2 rtol computation 540571f87433Sdalcinl (0 <= gamma2 <= 1) 540671f87433Sdalcinl . alpha - power for version 2 rtol computation (1 < alpha <= 2) 540771f87433Sdalcinl . alpha2 - power for safeguard 540871f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1) 540971f87433Sdalcinl 5410dc4c0fb0SBarry Smith Level: advanced 5411dc4c0fb0SBarry Smith 5412f6dfbefdSBarry Smith Notes: 541371f87433Sdalcinl Version 3 was contributed by Luis Chacon, June 2006. 541471f87433Sdalcinl 541577e5a1f9SBarry Smith Use `PETSC_CURRENT` to retain the default for any of the parameters. 541671f87433Sdalcinl 54171cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()` 541871f87433Sdalcinl @*/ 5419d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetParametersEW(SNES snes, PetscInt version, PetscReal rtol_0, PetscReal rtol_max, PetscReal gamma, PetscReal alpha, PetscReal alpha2, PetscReal threshold) 5420d71ae5a4SJacob Faibussowitsch { 5421fa9f3622SBarry Smith SNESKSPEW *kctx; 54225fd66863SKarl Rupp 542371f87433Sdalcinl PetscFunctionBegin; 54240700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5425fa9f3622SBarry Smith kctx = (SNESKSPEW *)snes->kspconvctx; 54265f80ce2aSJacob Faibussowitsch PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing"); 5427c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, version, 2); 5428c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, rtol_0, 3); 5429c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, rtol_max, 4); 5430c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, gamma, 5); 5431c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, alpha, 6); 5432c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, alpha2, 7); 5433c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, threshold, 8); 543471f87433Sdalcinl 543577e5a1f9SBarry Smith if (version != PETSC_CURRENT) kctx->version = version; 543677e5a1f9SBarry Smith if (rtol_0 != (PetscReal)PETSC_CURRENT) kctx->rtol_0 = rtol_0; 543777e5a1f9SBarry Smith if (rtol_max != (PetscReal)PETSC_CURRENT) kctx->rtol_max = rtol_max; 543877e5a1f9SBarry Smith if (gamma != (PetscReal)PETSC_CURRENT) kctx->gamma = gamma; 543977e5a1f9SBarry Smith if (alpha != (PetscReal)PETSC_CURRENT) kctx->alpha = alpha; 544077e5a1f9SBarry Smith if (alpha2 != (PetscReal)PETSC_CURRENT) kctx->alpha2 = alpha2; 544177e5a1f9SBarry Smith if (threshold != (PetscReal)PETSC_CURRENT) kctx->threshold = threshold; 544271f87433Sdalcinl 54430f0abf79SStefano 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); 54440b121fc5SBarry 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); 54450b121fc5SBarry 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); 54460b121fc5SBarry 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); 54470b121fc5SBarry 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); 54480b121fc5SBarry 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); 54493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 545071f87433Sdalcinl } 545171f87433Sdalcinl 545271f87433Sdalcinl /*@ 5453fa9f3622SBarry Smith SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker 545471f87433Sdalcinl convergence criteria for the linear solvers within an inexact 545571f87433Sdalcinl Newton method. 545671f87433Sdalcinl 545771f87433Sdalcinl Not Collective 545871f87433Sdalcinl 545997bb3fdcSJose E. Roman Input Parameter: 5460f6dfbefdSBarry Smith . snes - `SNES` context 546171f87433Sdalcinl 546271f87433Sdalcinl Output Parameters: 54630f0abf79SStefano Zampini + version - version 1, 2 (default is 2), 3 or 4 546471f87433Sdalcinl . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 546571f87433Sdalcinl . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 5466bf388a1fSBarry Smith . gamma - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1) 546771f87433Sdalcinl . alpha - power for version 2 rtol computation (1 < alpha <= 2) 546871f87433Sdalcinl . alpha2 - power for safeguard 546971f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1) 547071f87433Sdalcinl 547171f87433Sdalcinl Level: advanced 547271f87433Sdalcinl 54731cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPSetParametersEW()` 547471f87433Sdalcinl @*/ 5475d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetParametersEW(SNES snes, PetscInt *version, PetscReal *rtol_0, PetscReal *rtol_max, PetscReal *gamma, PetscReal *alpha, PetscReal *alpha2, PetscReal *threshold) 5476d71ae5a4SJacob Faibussowitsch { 5477fa9f3622SBarry Smith SNESKSPEW *kctx; 54785fd66863SKarl Rupp 547971f87433Sdalcinl PetscFunctionBegin; 54800700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5481fa9f3622SBarry Smith kctx = (SNESKSPEW *)snes->kspconvctx; 54825f80ce2aSJacob Faibussowitsch PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing"); 548371f87433Sdalcinl if (version) *version = kctx->version; 548471f87433Sdalcinl if (rtol_0) *rtol_0 = kctx->rtol_0; 548571f87433Sdalcinl if (rtol_max) *rtol_max = kctx->rtol_max; 548671f87433Sdalcinl if (gamma) *gamma = kctx->gamma; 548771f87433Sdalcinl if (alpha) *alpha = kctx->alpha; 548871f87433Sdalcinl if (alpha2) *alpha2 = kctx->alpha2; 548971f87433Sdalcinl if (threshold) *threshold = kctx->threshold; 54903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 549171f87433Sdalcinl } 549271f87433Sdalcinl 54935c0db29aSPierre Jolivet PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx) 5494d71ae5a4SJacob Faibussowitsch { 54955c0db29aSPierre Jolivet SNES snes = (SNES)ctx; 5496fa9f3622SBarry Smith SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx; 549777e5a1f9SBarry Smith PetscReal rtol = PETSC_CURRENT, stol; 549871f87433Sdalcinl 549971f87433Sdalcinl PetscFunctionBegin; 55003ba16761SJacob Faibussowitsch if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS); 550130058271SDmitry Karpeev if (!snes->iter) { 550230058271SDmitry Karpeev rtol = kctx->rtol_0; /* first time in, so use the original user rtol */ 55039566063dSJacob Faibussowitsch PetscCall(VecNorm(snes->vec_func, NORM_2, &kctx->norm_first)); 55040f0abf79SStefano Zampini } else { 55050fdf79fbSJacob 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); 550671f87433Sdalcinl if (kctx->version == 1) { 55070f0abf79SStefano Zampini rtol = PetscAbsReal(snes->norm - kctx->lresid_last) / kctx->norm_last; 550885ec1a3cSBarry Smith stol = PetscPowReal(kctx->rtol_last, kctx->alpha2); 550971f87433Sdalcinl if (stol > kctx->threshold) rtol = PetscMax(rtol, stol); 551071f87433Sdalcinl } else if (kctx->version == 2) { 551185ec1a3cSBarry Smith rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha); 551285ec1a3cSBarry Smith stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha); 551371f87433Sdalcinl if (stol > kctx->threshold) rtol = PetscMax(rtol, stol); 551471f87433Sdalcinl } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */ 551585ec1a3cSBarry Smith rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha); 551671f87433Sdalcinl /* safeguard: avoid sharp decrease of rtol */ 551785ec1a3cSBarry Smith stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha); 551871f87433Sdalcinl stol = PetscMax(rtol, stol); 551971f87433Sdalcinl rtol = PetscMin(kctx->rtol_0, stol); 552071f87433Sdalcinl /* safeguard: avoid oversolving */ 552130058271SDmitry Karpeev stol = kctx->gamma * (kctx->norm_first * snes->rtol) / snes->norm; 552271f87433Sdalcinl stol = PetscMax(rtol, stol); 552371f87433Sdalcinl rtol = PetscMin(kctx->rtol_0, stol); 55240fdf79fbSJacob Faibussowitsch } else /* if (kctx->version == 4) */ { 55250fdf79fbSJacob Faibussowitsch /* H.-B. An et al. Journal of Computational and Applied Mathematics 200 (2007) 47-60 */ 55260f0abf79SStefano Zampini PetscReal ared = PetscAbsReal(kctx->norm_last - snes->norm); 55270f0abf79SStefano Zampini PetscReal pred = PetscAbsReal(kctx->norm_last - kctx->lresid_last); 55280f0abf79SStefano Zampini PetscReal rk = ared / pred; 55290f0abf79SStefano Zampini if (rk < kctx->v4_p1) rtol = 1. - 2. * kctx->v4_p1; 55300f0abf79SStefano Zampini else if (rk < kctx->v4_p2) rtol = kctx->rtol_last; 55310f0abf79SStefano Zampini else if (rk < kctx->v4_p3) rtol = kctx->v4_m1 * kctx->rtol_last; 55320f0abf79SStefano Zampini else rtol = kctx->v4_m2 * kctx->rtol_last; 55330f0abf79SStefano Zampini 5534a4598233SStefano 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; 55350f0abf79SStefano Zampini kctx->rtol_last_2 = kctx->rtol_last; 55360f0abf79SStefano Zampini kctx->rk_last_2 = kctx->rk_last; 55370f0abf79SStefano Zampini kctx->rk_last = rk; 55380fdf79fbSJacob Faibussowitsch } 55390f0abf79SStefano Zampini } 55400f0abf79SStefano Zampini /* safeguard: avoid rtol greater than rtol_max */ 554171f87433Sdalcinl rtol = PetscMin(rtol, kctx->rtol_max); 554277e5a1f9SBarry Smith PetscCall(KSPSetTolerances(ksp, rtol, PETSC_CURRENT, PETSC_CURRENT, PETSC_CURRENT)); 554363a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "iter %" PetscInt_FMT ", Eisenstat-Walker (version %" PetscInt_FMT ") KSP rtol=%g\n", snes->iter, kctx->version, (double)rtol)); 55443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 554571f87433Sdalcinl } 554671f87433Sdalcinl 55475c0db29aSPierre Jolivet PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx) 5548d71ae5a4SJacob Faibussowitsch { 55495c0db29aSPierre Jolivet SNES snes = (SNES)ctx; 5550fa9f3622SBarry Smith SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx; 555171f87433Sdalcinl PCSide pcside; 555271f87433Sdalcinl Vec lres; 555371f87433Sdalcinl 555471f87433Sdalcinl PetscFunctionBegin; 55553ba16761SJacob Faibussowitsch if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS); 55569566063dSJacob Faibussowitsch PetscCall(KSPGetTolerances(ksp, &kctx->rtol_last, NULL, NULL, NULL)); 555771dbe336SPeter Brune kctx->norm_last = snes->norm; 55580f0abf79SStefano Zampini if (kctx->version == 1 || kctx->version == 4) { 55594f00ce20SMatthew G. Knepley PC pc; 55600f0abf79SStefano Zampini PetscBool getRes; 55614f00ce20SMatthew G. Knepley 55629566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksp, &pc)); 55630f0abf79SStefano Zampini PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &getRes)); 55640f0abf79SStefano Zampini if (!getRes) { 55650f0abf79SStefano Zampini KSPNormType normtype; 55660f0abf79SStefano Zampini 55670f0abf79SStefano Zampini PetscCall(KSPGetNormType(ksp, &normtype)); 55680f0abf79SStefano Zampini getRes = (PetscBool)(normtype == KSP_NORM_UNPRECONDITIONED); 55690f0abf79SStefano Zampini } 55709566063dSJacob Faibussowitsch PetscCall(KSPGetPCSide(ksp, &pcside)); 55710f0abf79SStefano Zampini if (pcside == PC_RIGHT || getRes) { /* KSP residual is true linear residual */ 55729566063dSJacob Faibussowitsch PetscCall(KSPGetResidualNorm(ksp, &kctx->lresid_last)); 557371f87433Sdalcinl } else { 557471f87433Sdalcinl /* KSP residual is preconditioned residual */ 557571f87433Sdalcinl /* compute true linear residual norm */ 55760f0abf79SStefano Zampini Mat J; 55770f0abf79SStefano Zampini PetscCall(KSPGetOperators(ksp, &J, NULL)); 55789566063dSJacob Faibussowitsch PetscCall(VecDuplicate(b, &lres)); 55790f0abf79SStefano Zampini PetscCall(MatMult(J, x, lres)); 55809566063dSJacob Faibussowitsch PetscCall(VecAYPX(lres, -1.0, b)); 55819566063dSJacob Faibussowitsch PetscCall(VecNorm(lres, NORM_2, &kctx->lresid_last)); 55829566063dSJacob Faibussowitsch PetscCall(VecDestroy(&lres)); 558371f87433Sdalcinl } 558471f87433Sdalcinl } 55853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 558671f87433Sdalcinl } 558771f87433Sdalcinl 5588d4211eb9SBarry Smith /*@ 5589f6dfbefdSBarry Smith SNESGetKSP - Returns the `KSP` context for a `SNES` solver. 5590d4211eb9SBarry Smith 5591420bcc1bSBarry Smith Not Collective, but if `snes` is parallel, then `ksp` is parallel 5592d4211eb9SBarry Smith 5593d4211eb9SBarry Smith Input Parameter: 5594f6dfbefdSBarry Smith . snes - the `SNES` context 5595d4211eb9SBarry Smith 5596d4211eb9SBarry Smith Output Parameter: 5597f6dfbefdSBarry Smith . ksp - the `KSP` context 5598d4211eb9SBarry Smith 5599dc4c0fb0SBarry Smith Level: beginner 5600dc4c0fb0SBarry Smith 5601d4211eb9SBarry Smith Notes: 5602f6dfbefdSBarry Smith The user can then directly manipulate the `KSP` context to set various 5603d4211eb9SBarry Smith options, etc. Likewise, the user can then extract and manipulate the 5604f6dfbefdSBarry Smith `PC` contexts as well. 5605f6dfbefdSBarry Smith 56060b4b7b1cSBarry 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. 5607d4211eb9SBarry Smith 56081cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSP`, `PC`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()` 5609d4211eb9SBarry Smith @*/ 5610d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetKSP(SNES snes, KSP *ksp) 5611d71ae5a4SJacob Faibussowitsch { 561271f87433Sdalcinl PetscFunctionBegin; 5613d4211eb9SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 56144f572ea9SToby Isaac PetscAssertPointer(ksp, 2); 5615d4211eb9SBarry Smith 5616d4211eb9SBarry Smith if (!snes->ksp) { 56179566063dSJacob Faibussowitsch PetscCall(KSPCreate(PetscObjectComm((PetscObject)snes), &snes->ksp)); 56189566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->ksp, (PetscObject)snes, 1)); 5619d4211eb9SBarry Smith 56205c0db29aSPierre Jolivet PetscCall(KSPSetPreSolve(snes->ksp, KSPPreSolve_SNESEW, snes)); 56215c0db29aSPierre Jolivet PetscCall(KSPSetPostSolve(snes->ksp, KSPPostSolve_SNESEW, snes)); 5622a5c2985bSBarry Smith 56239566063dSJacob Faibussowitsch PetscCall(KSPMonitorSetFromOptions(snes->ksp, "-snes_monitor_ksp", "snes_preconditioned_residual", snes)); 56249566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptions((PetscObject)snes->ksp, ((PetscObject)snes)->options)); 5625d4211eb9SBarry Smith } 5626d4211eb9SBarry Smith *ksp = snes->ksp; 56273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 562871f87433Sdalcinl } 56296c699258SBarry Smith 5630af0996ceSBarry Smith #include <petsc/private/dmimpl.h> 56316c699258SBarry Smith /*@ 56320b4b7b1cSBarry Smith SNESSetDM - Sets the `DM` that may be used by some `SNES` nonlinear solvers or their underlying preconditioners 56336c699258SBarry Smith 5634c3339decSBarry Smith Logically Collective 56356c699258SBarry Smith 56366c699258SBarry Smith Input Parameters: 56372a808120SBarry Smith + snes - the nonlinear solver context 5638420bcc1bSBarry Smith - dm - the `DM`, cannot be `NULL` 5639dc4c0fb0SBarry Smith 5640dc4c0fb0SBarry Smith Level: intermediate 56416c699258SBarry Smith 5642f6dfbefdSBarry Smith Note: 5643f6dfbefdSBarry Smith A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`, 5644f6dfbefdSBarry Smith even when not using interfaces like `DMSNESSetFunction()`. Use `DMClone()` to get a distinct `DM` when solving different 5645e03a659cSJed Brown problems using the same function space. 5646e03a659cSJed Brown 5647420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()` 56486c699258SBarry Smith @*/ 5649d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDM(SNES snes, DM dm) 5650d71ae5a4SJacob Faibussowitsch { 5651345fed2cSBarry Smith KSP ksp; 5652942e3340SBarry Smith DMSNES sdm; 56536c699258SBarry Smith 56546c699258SBarry Smith PetscFunctionBegin; 56550700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 56562a808120SBarry Smith PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 56579566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 5658942e3340SBarry Smith if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */ 565951f4b3c7SToby Isaac if (snes->dm->dmsnes && !dm->dmsnes) { 56609566063dSJacob Faibussowitsch PetscCall(DMCopyDMSNES(snes->dm, dm)); 56619566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(snes->dm, &sdm)); 5662f5af7f23SKarl Rupp if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */ 56636cab3a1bSJed Brown } 56649566063dSJacob Faibussowitsch PetscCall(DMCoarsenHookRemove(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes)); 56659566063dSJacob Faibussowitsch PetscCall(DMDestroy(&snes->dm)); 56666cab3a1bSJed Brown } 56676c699258SBarry Smith snes->dm = dm; 5668116d1032SJed Brown snes->dmAuto = PETSC_FALSE; 5669f5af7f23SKarl Rupp 56709566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 56719566063dSJacob Faibussowitsch PetscCall(KSPSetDM(ksp, dm)); 56729566063dSJacob Faibussowitsch PetscCall(KSPSetDMActive(ksp, PETSC_FALSE)); 5673efd4aadfSBarry Smith if (snes->npc) { 56749566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes->npc, snes->dm)); 56759566063dSJacob Faibussowitsch PetscCall(SNESSetNPCSide(snes, snes->npcside)); 56762c155ee1SBarry Smith } 56773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 56786c699258SBarry Smith } 56796c699258SBarry Smith 56806c699258SBarry Smith /*@ 56810b4b7b1cSBarry Smith SNESGetDM - Gets the `DM` that may be used by some `SNES` nonlinear solvers/preconditioners 56826c699258SBarry Smith 56830b4b7b1cSBarry Smith Not Collective but `dm` obtained is parallel on `snes` 56846c699258SBarry Smith 56856c699258SBarry Smith Input Parameter: 5686420bcc1bSBarry Smith . snes - the `SNES` context 56876c699258SBarry Smith 56886c699258SBarry Smith Output Parameter: 5689420bcc1bSBarry Smith . dm - the `DM` 56906c699258SBarry Smith 56916c699258SBarry Smith Level: intermediate 56926c699258SBarry Smith 5693420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESSetDM()`, `KSPSetDM()`, `KSPGetDM()` 56946c699258SBarry Smith @*/ 5695d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDM(SNES snes, DM *dm) 5696d71ae5a4SJacob Faibussowitsch { 56976c699258SBarry Smith PetscFunctionBegin; 56980700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 56996cab3a1bSJed Brown if (!snes->dm) { 57009566063dSJacob Faibussowitsch PetscCall(DMShellCreate(PetscObjectComm((PetscObject)snes), &snes->dm)); 5701116d1032SJed Brown snes->dmAuto = PETSC_TRUE; 57026cab3a1bSJed Brown } 57036c699258SBarry Smith *dm = snes->dm; 57043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 57056c699258SBarry Smith } 57060807856dSBarry Smith 570731823bd8SMatthew G Knepley /*@ 5708be95d8f1SBarry Smith SNESSetNPC - Sets the nonlinear preconditioner to be used. 570931823bd8SMatthew G Knepley 5710c3339decSBarry Smith Collective 571131823bd8SMatthew G Knepley 571231823bd8SMatthew G Knepley Input Parameters: 5713f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 571462842358SBarry Smith - npc - the `SNES` nonlinear preconditioner object 571562842358SBarry Smith 571662842358SBarry Smith Options Database Key: 571762842358SBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner 571831823bd8SMatthew G Knepley 5719dc4c0fb0SBarry Smith Level: developer 5720dc4c0fb0SBarry Smith 572131823bd8SMatthew G Knepley Notes: 572262842358SBarry Smith This is rarely used, rather use `SNESGetNPC()` to retrieve the preconditioner and configure it using the API. 572331823bd8SMatthew G Knepley 5724f6dfbefdSBarry Smith Only some `SNESType` can use a nonlinear preconditioner 5725f6dfbefdSBarry Smith 5726420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNGS`, `SNESFAS`, `SNESGetNPC()`, `SNESHasNPC()` 572731823bd8SMatthew G Knepley @*/ 5728d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPC(SNES snes, SNES npc) 5729d71ae5a4SJacob Faibussowitsch { 573031823bd8SMatthew G Knepley PetscFunctionBegin; 573131823bd8SMatthew G Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5732f6dfbefdSBarry Smith PetscValidHeaderSpecific(npc, SNES_CLASSID, 2); 5733f6dfbefdSBarry Smith PetscCheckSameComm(snes, 1, npc, 2); 5734f6dfbefdSBarry Smith PetscCall(PetscObjectReference((PetscObject)npc)); 57359566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&snes->npc)); 5736f6dfbefdSBarry Smith snes->npc = npc; 57373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 573831823bd8SMatthew G Knepley } 573931823bd8SMatthew G Knepley 574031823bd8SMatthew G Knepley /*@ 5741f6dfbefdSBarry Smith SNESGetNPC - Gets a nonlinear preconditioning solver SNES` to be used to precondition the original nonlinear solver. 574231823bd8SMatthew G Knepley 57430b4b7b1cSBarry Smith Not Collective; but any changes to the obtained the `pc` object must be applied collectively 574431823bd8SMatthew G Knepley 574531823bd8SMatthew G Knepley Input Parameter: 5746f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 574731823bd8SMatthew G Knepley 574831823bd8SMatthew G Knepley Output Parameter: 574962842358SBarry Smith . pc - the `SNES` preconditioner context 575031823bd8SMatthew G Knepley 5751f6dfbefdSBarry Smith Options Database Key: 5752f6dfbefdSBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner 5753b5badacbSBarry Smith 57540b4b7b1cSBarry Smith Level: advanced 5755dc4c0fb0SBarry Smith 575695452b02SPatrick Sanan Notes: 57570b4b7b1cSBarry Smith If a `SNES` was previously set with `SNESSetNPC()` then that value is returned, otherwise a new `SNES` object is created that will 57580b4b7b1cSBarry Smith be used as the nonlinear preconditioner for the current `SNES`. 5759be95d8f1SBarry Smith 5760f6dfbefdSBarry Smith The (preconditioner) `SNES` returned automatically inherits the same nonlinear function and Jacobian supplied to the original 576162842358SBarry Smith `SNES`. These may be overwritten if needed. 576262842358SBarry Smith 576362842358SBarry Smith Use the options database prefixes `-npc_snes`, `-npc_ksp`, etc., to control the configuration of the nonlinear preconditioner 5764951fe5abSBarry Smith 57651cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESHasNPC()`, `SNES`, `SNESCreate()` 576631823bd8SMatthew G Knepley @*/ 5767d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPC(SNES snes, SNES *pc) 5768d71ae5a4SJacob Faibussowitsch { 5769a64e098fSPeter Brune const char *optionsprefix; 577031823bd8SMatthew G Knepley 577131823bd8SMatthew G Knepley PetscFunctionBegin; 577231823bd8SMatthew G Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 57734f572ea9SToby Isaac PetscAssertPointer(pc, 2); 5774efd4aadfSBarry Smith if (!snes->npc) { 5775ec785e5bSStefano Zampini void *ctx; 5776ec785e5bSStefano Zampini 57779566063dSJacob Faibussowitsch PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &snes->npc)); 57789566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->npc, (PetscObject)snes, 1)); 57799566063dSJacob Faibussowitsch PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 57809566063dSJacob Faibussowitsch PetscCall(SNESSetOptionsPrefix(snes->npc, optionsprefix)); 57819566063dSJacob Faibussowitsch PetscCall(SNESAppendOptionsPrefix(snes->npc, "npc_")); 5782fb87a551SStefano Zampini if (snes->ops->usercompute) { 578349abdd8aSBarry Smith PetscCall(SNESSetComputeApplicationContext(snes, snes->ops->usercompute, snes->ops->ctxdestroy)); 5784fb87a551SStefano Zampini } else { 5785ec785e5bSStefano Zampini PetscCall(SNESGetApplicationContext(snes, &ctx)); 5786ec785e5bSStefano Zampini PetscCall(SNESSetApplicationContext(snes->npc, ctx)); 5787fb87a551SStefano Zampini } 57889566063dSJacob Faibussowitsch PetscCall(SNESSetCountersReset(snes->npc, PETSC_FALSE)); 578931823bd8SMatthew G Knepley } 5790efd4aadfSBarry Smith *pc = snes->npc; 57913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 579231823bd8SMatthew G Knepley } 579331823bd8SMatthew G Knepley 57943ad1a0b9SPatrick Farrell /*@ 57950b4b7b1cSBarry Smith SNESHasNPC - Returns whether a nonlinear preconditioner is associated with the given `SNES` 57963ad1a0b9SPatrick Farrell 57973ad1a0b9SPatrick Farrell Not Collective 57983ad1a0b9SPatrick Farrell 57993ad1a0b9SPatrick Farrell Input Parameter: 5800f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 58013ad1a0b9SPatrick Farrell 58023ad1a0b9SPatrick Farrell Output Parameter: 5803420bcc1bSBarry Smith . has_npc - whether the `SNES` has a nonlinear preconditioner or not 58043ad1a0b9SPatrick Farrell 58053ad1a0b9SPatrick Farrell Level: developer 58063ad1a0b9SPatrick Farrell 58071cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESGetNPC()` 58083ad1a0b9SPatrick Farrell @*/ 5809d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc) 5810d71ae5a4SJacob Faibussowitsch { 58113ad1a0b9SPatrick Farrell PetscFunctionBegin; 58123ad1a0b9SPatrick Farrell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5813835f2295SStefano Zampini PetscAssertPointer(has_npc, 2); 5814835f2295SStefano Zampini *has_npc = snes->npc ? PETSC_TRUE : PETSC_FALSE; 58153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 58163ad1a0b9SPatrick Farrell } 58173ad1a0b9SPatrick Farrell 5818c40d0f55SPeter Brune /*@ 581962842358SBarry Smith SNESSetNPCSide - Sets the nonlinear preconditioning side used by the nonlinear preconditioner inside `SNES`. 5820c40d0f55SPeter Brune 5821c3339decSBarry Smith Logically Collective 5822c40d0f55SPeter Brune 5823c40d0f55SPeter Brune Input Parameter: 5824f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 5825c40d0f55SPeter Brune 5826c40d0f55SPeter Brune Output Parameter: 5827c40d0f55SPeter Brune . side - the preconditioning side, where side is one of 5828c40d0f55SPeter Brune .vb 58292d547940SBarry Smith PC_LEFT - left preconditioning 58302d547940SBarry Smith PC_RIGHT - right preconditioning (default for most nonlinear solvers) 5831c40d0f55SPeter Brune .ve 5832c40d0f55SPeter Brune 5833f6dfbefdSBarry Smith Options Database Key: 583467b8a455SSatish Balay . -snes_npc_side <right,left> - nonlinear preconditioner side 5835c40d0f55SPeter Brune 5836dc4c0fb0SBarry Smith Level: intermediate 5837dc4c0fb0SBarry Smith 5838f6dfbefdSBarry Smith Note: 5839f6dfbefdSBarry Smith `SNESNRICHARDSON` and `SNESNCG` only support left preconditioning. 58402d547940SBarry Smith 584162842358SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNPC()`, `SNESNRICHARDSON`, `SNESNCG`, `SNESType`, `SNESGetNPCSide()`, `KSPSetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide` 5842c40d0f55SPeter Brune @*/ 5843d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPCSide(SNES snes, PCSide side) 5844d71ae5a4SJacob Faibussowitsch { 5845c40d0f55SPeter Brune PetscFunctionBegin; 5846c40d0f55SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5847c40d0f55SPeter Brune PetscValidLogicalCollectiveEnum(snes, side, 2); 5848b552625fSStefano Zampini if (side == PC_SIDE_DEFAULT) side = PC_RIGHT; 584954c59aa7SJacob Faibussowitsch PetscCheck((side == PC_LEFT) || (side == PC_RIGHT), PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Only PC_LEFT and PC_RIGHT are supported"); 5850efd4aadfSBarry Smith snes->npcside = side; 58513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5852c40d0f55SPeter Brune } 5853c40d0f55SPeter Brune 5854c40d0f55SPeter Brune /*@ 585562842358SBarry Smith SNESGetNPCSide - Gets the preconditioning side used by the nonlinear preconditioner inside `SNES`. 5856c40d0f55SPeter Brune 5857c40d0f55SPeter Brune Not Collective 5858c40d0f55SPeter Brune 5859c40d0f55SPeter Brune Input Parameter: 5860f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 5861c40d0f55SPeter Brune 5862c40d0f55SPeter Brune Output Parameter: 5863c40d0f55SPeter Brune . side - the preconditioning side, where side is one of 5864c40d0f55SPeter Brune .vb 5865f6dfbefdSBarry Smith `PC_LEFT` - left preconditioning 5866f6dfbefdSBarry Smith `PC_RIGHT` - right preconditioning (default for most nonlinear solvers) 5867c40d0f55SPeter Brune .ve 5868c40d0f55SPeter Brune 5869c40d0f55SPeter Brune Level: intermediate 5870c40d0f55SPeter Brune 587162842358SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNPC()`, `SNESSetNPCSide()`, `KSPGetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide` 5872c40d0f55SPeter Brune @*/ 5873d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPCSide(SNES snes, PCSide *side) 5874d71ae5a4SJacob Faibussowitsch { 5875c40d0f55SPeter Brune PetscFunctionBegin; 5876c40d0f55SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 58774f572ea9SToby Isaac PetscAssertPointer(side, 2); 5878efd4aadfSBarry Smith *side = snes->npcside; 58793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5880c40d0f55SPeter Brune } 5881c40d0f55SPeter Brune 58829e764e56SPeter Brune /*@ 58830b4b7b1cSBarry Smith SNESSetLineSearch - Sets the `SNESLineSearch` to be used for a given `SNES` 58849e764e56SPeter Brune 5885c3339decSBarry Smith Collective 58869e764e56SPeter Brune 58879e764e56SPeter Brune Input Parameters: 5888f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 58899e764e56SPeter Brune - linesearch - the linesearch object 58909e764e56SPeter Brune 5891dc4c0fb0SBarry Smith Level: developer 5892dc4c0fb0SBarry Smith 5893f6dfbefdSBarry Smith Note: 5894420bcc1bSBarry Smith This is almost never used, rather one uses `SNESGetLineSearch()` to retrieve the line search and set options on it 58959e764e56SPeter Brune to configure it using the API). 58969e764e56SPeter Brune 5897420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()` 58989e764e56SPeter Brune @*/ 5899d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch) 5900d71ae5a4SJacob Faibussowitsch { 59019e764e56SPeter Brune PetscFunctionBegin; 59029e764e56SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5903f1c6b773SPeter Brune PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 2); 59049e764e56SPeter Brune PetscCheckSameComm(snes, 1, linesearch, 2); 59059566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)linesearch)); 59069566063dSJacob Faibussowitsch PetscCall(SNESLineSearchDestroy(&snes->linesearch)); 5907f5af7f23SKarl Rupp 59089e764e56SPeter Brune snes->linesearch = linesearch; 59093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 59109e764e56SPeter Brune } 59119e764e56SPeter Brune 5912a34ceb2aSJed Brown /*@ 591362842358SBarry Smith SNESGetLineSearch - Returns the line search associated with the `SNES`. 59149e764e56SPeter Brune 59159e764e56SPeter Brune Not Collective 59169e764e56SPeter Brune 59179e764e56SPeter Brune Input Parameter: 5918f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 59199e764e56SPeter Brune 59209e764e56SPeter Brune Output Parameter: 59219e764e56SPeter Brune . linesearch - linesearch context 59229e764e56SPeter Brune 5923162e0bf5SPeter Brune Level: beginner 59249e764e56SPeter Brune 592562842358SBarry Smith Notes: 592662842358SBarry Smith It creates a default line search instance which can be configured as needed in case it has not been already set with `SNESSetLineSearch()`. 592762842358SBarry Smith 592862842358SBarry Smith You can also use the options database keys `-snes_linesearch_*` to configure the line search. See `SNESLineSearchSetFromOptions()` for the possible options. 592962842358SBarry Smith 593062842358SBarry Smith .seealso: [](ch_snes), `SNESLineSearch`, `SNESSetLineSearch()`, `SNESLineSearchCreate()`, `SNESLineSearchSetFromOptions()` 59319e764e56SPeter Brune @*/ 5932d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch) 5933d71ae5a4SJacob Faibussowitsch { 59349e764e56SPeter Brune const char *optionsprefix; 59359e764e56SPeter Brune 59369e764e56SPeter Brune PetscFunctionBegin; 59379e764e56SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 59384f572ea9SToby Isaac PetscAssertPointer(linesearch, 2); 59399e764e56SPeter Brune if (!snes->linesearch) { 59409566063dSJacob Faibussowitsch PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 59419566063dSJacob Faibussowitsch PetscCall(SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch)); 59429566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetSNES(snes->linesearch, snes)); 59439566063dSJacob Faibussowitsch PetscCall(SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix)); 59449566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->linesearch, (PetscObject)snes, 1)); 59459e764e56SPeter Brune } 59469e764e56SPeter Brune *linesearch = snes->linesearch; 59473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 59489e764e56SPeter Brune } 5949