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; 13fc8bc0e3SRichard Tran Mills PetscLogEvent SNES_Solve, SNES_SetUp, SNES_FunctionEval, SNES_JacobianEval, SNES_NGSEval, SNES_NGSFuncEval, 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 120c3339decSBarry Smith Logically Collective 1214936397dSBarry Smith 1222fe279fdSBarry Smith Input Parameter: 123f6dfbefdSBarry Smith . snes - the `SNES` context 1244936397dSBarry Smith 12528529972SSatish Balay Level: advanced 1264936397dSBarry Smith 127ced0f3aeSBarry Smith Notes: 128ced0f3aeSBarry Smith If this is called the `SNESSolve()` stops iterating and returns with a `SNESConvergedReason` of `SNES_DIVERGED_FUNCTION_DOMAIN` 129ced0f3aeSBarry Smith 130ced0f3aeSBarry Smith You should always call `SNESGetConvergedReason()` after each `SNESSolve()` and verify if the iteration converged (positive result) or diverged (negative result). 131ced0f3aeSBarry Smith 132f0b84518SBarry Smith You can direct `SNES` to avoid certain steps by using `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()` or 133f0b84518SBarry Smith `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()` 134f0b84518SBarry Smith 1358434afd1SBarry Smith .seealso: [](ch_snes), `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetJacobianDomainError()`, `SNESVISetVariableBounds()`, 136ced0f3aeSBarry Smith `SNESVISetComputeVariableBounds()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESConvergedReason`, `SNESGetConvergedReason()` 1374936397dSBarry Smith @*/ 138d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionDomainError(SNES snes) 139d71ae5a4SJacob Faibussowitsch { 1404936397dSBarry Smith PetscFunctionBegin; 1410700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1425f80ce2aSJacob Faibussowitsch PetscCheck(!snes->errorifnotconverged, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "User code indicates input vector is not in the function domain"); 1434936397dSBarry Smith snes->domainerror = PETSC_TRUE; 1443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1454936397dSBarry Smith } 1464936397dSBarry Smith 1476a388c36SPeter Brune /*@ 148f6dfbefdSBarry Smith SNESSetJacobianDomainError - tells `SNES` that the function you provided to `SNESSetJacobian()` at the proposed step. For example there is a negative element transformation. 14907b62357SFande Kong 150c3339decSBarry Smith Logically Collective 15107b62357SFande Kong 1522fe279fdSBarry Smith Input Parameter: 153f6dfbefdSBarry Smith . snes - the `SNES` context 15407b62357SFande Kong 15507b62357SFande Kong Level: advanced 15607b62357SFande Kong 157ced0f3aeSBarry Smith Notes: 158ced0f3aeSBarry Smith If this is called the `SNESSolve()` stops iterating and returns with a `SNESConvergedReason` of `SNES_DIVERGED_FUNCTION_DOMAIN` 159ced0f3aeSBarry Smith 160ced0f3aeSBarry Smith You should always call `SNESGetConvergedReason()` after each `SNESSolve()` and verify if the iteration converged (positive result) or diverged (negative result). 161ced0f3aeSBarry Smith 162f0b84518SBarry Smith You can direct `SNES` to avoid certain steps by using `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()` or 163f0b84518SBarry Smith `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()` 164f0b84518SBarry Smith 1658434afd1SBarry Smith .seealso: [](ch_snes), `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetFunctionDomainError()`, `SNESVISetVariableBounds()`, 166ced0f3aeSBarry Smith `SNESVISetComputeVariableBounds()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESConvergedReason`, `SNESGetConvergedReason()` 16707b62357SFande Kong @*/ 168d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetJacobianDomainError(SNES snes) 169d71ae5a4SJacob Faibussowitsch { 17007b62357SFande Kong PetscFunctionBegin; 17107b62357SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1725f80ce2aSJacob Faibussowitsch PetscCheck(!snes->errorifnotconverged, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "User code indicates computeJacobian does not make sense"); 17307b62357SFande Kong snes->jacobiandomainerror = PETSC_TRUE; 1743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17507b62357SFande Kong } 17607b62357SFande Kong 17707b62357SFande Kong /*@ 178f6dfbefdSBarry Smith SNESSetCheckJacobianDomainError - tells `SNESSolve()` whether to check if the user called `SNESSetJacobianDomainError()` Jacobian domain error after 179420bcc1bSBarry 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. 180b351a90bSFande Kong 181c3339decSBarry Smith Logically Collective 182b351a90bSFande Kong 183b351a90bSFande Kong Input Parameters: 18420f4b53cSBarry Smith + snes - the `SNES` context 185f6dfbefdSBarry Smith - flg - indicates if or not to check Jacobian domain error after each Jacobian evaluation 186b351a90bSFande Kong 187b351a90bSFande Kong Level: advanced 188b351a90bSFande Kong 189f6dfbefdSBarry Smith Note: 190f6dfbefdSBarry Smith Checks require one extra parallel synchronization for each Jacobian evaluation 191f6dfbefdSBarry Smith 1928434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetFunctionDomainError()`, `SNESGetCheckJacobianDomainError()` 193b351a90bSFande Kong @*/ 194d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCheckJacobianDomainError(SNES snes, PetscBool flg) 195d71ae5a4SJacob Faibussowitsch { 196b351a90bSFande Kong PetscFunctionBegin; 197b351a90bSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 198b351a90bSFande Kong snes->checkjacdomainerror = flg; 1993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 200b351a90bSFande Kong } 201b351a90bSFande Kong 202b351a90bSFande Kong /*@ 203420bcc1bSBarry Smith SNESGetCheckJacobianDomainError - Get an indicator whether or not `SNES` is checking Jacobian domain errors after each Jacobian evaluation. 2048383d7d7SFande Kong 205c3339decSBarry Smith Logically Collective 2068383d7d7SFande Kong 2072fe279fdSBarry Smith Input Parameter: 208f6dfbefdSBarry Smith . snes - the `SNES` context 2098383d7d7SFande Kong 2102fe279fdSBarry Smith Output Parameter: 211420bcc1bSBarry Smith . flg - `PETSC_FALSE` indicates that it is not checking Jacobian domain errors after each Jacobian evaluation 2128383d7d7SFande Kong 2138383d7d7SFande Kong Level: advanced 2148383d7d7SFande Kong 2158434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetFunctionDomainError()`, `SNESSetCheckJacobianDomainError()` 2168383d7d7SFande Kong @*/ 217d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetCheckJacobianDomainError(SNES snes, PetscBool *flg) 218d71ae5a4SJacob Faibussowitsch { 2198383d7d7SFande Kong PetscFunctionBegin; 2208383d7d7SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2214f572ea9SToby Isaac PetscAssertPointer(flg, 2); 2228383d7d7SFande Kong *flg = snes->checkjacdomainerror; 2233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2248383d7d7SFande Kong } 2258383d7d7SFande Kong 2268383d7d7SFande Kong /*@ 227420bcc1bSBarry Smith SNESGetFunctionDomainError - Gets the status of the domain error after a call to `SNESComputeFunction()` 2286a388c36SPeter Brune 229f6dfbefdSBarry Smith Logically Collective 2306a388c36SPeter Brune 2312fe279fdSBarry Smith Input Parameter: 232f6dfbefdSBarry Smith . snes - the `SNES` context 2336a388c36SPeter Brune 2342fe279fdSBarry Smith Output Parameter: 235f6dfbefdSBarry Smith . domainerror - Set to `PETSC_TRUE` if there's a domain error; `PETSC_FALSE` otherwise. 2366a388c36SPeter Brune 237f6dfbefdSBarry Smith Level: developer 2386a388c36SPeter Brune 2391cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunctionDomainError()`, `SNESComputeFunction()` 2406a388c36SPeter Brune @*/ 241d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionDomainError(SNES snes, PetscBool *domainerror) 242d71ae5a4SJacob Faibussowitsch { 2436a388c36SPeter Brune PetscFunctionBegin; 2446a388c36SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2454f572ea9SToby Isaac PetscAssertPointer(domainerror, 2); 2466a388c36SPeter Brune *domainerror = snes->domainerror; 2473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2486a388c36SPeter Brune } 2496a388c36SPeter Brune 25007b62357SFande Kong /*@ 251420bcc1bSBarry Smith SNESGetJacobianDomainError - Gets the status of the Jacobian domain error after a call to `SNESComputeJacobian()` 25207b62357SFande Kong 253c3339decSBarry Smith Logically Collective 25407b62357SFande Kong 2552fe279fdSBarry Smith Input Parameter: 256f6dfbefdSBarry Smith . snes - the `SNES` context 25707b62357SFande Kong 2582fe279fdSBarry Smith Output Parameter: 259f6dfbefdSBarry Smith . domainerror - Set to `PETSC_TRUE` if there's a Jacobian domain error; `PETSC_FALSE` otherwise. 26007b62357SFande Kong 26107b62357SFande Kong Level: advanced 26207b62357SFande Kong 2631cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunctionDomainError()`, `SNESComputeFunction()`, `SNESGetFunctionDomainError()` 26407b62357SFande Kong @*/ 265d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetJacobianDomainError(SNES snes, PetscBool *domainerror) 266d71ae5a4SJacob Faibussowitsch { 26707b62357SFande Kong PetscFunctionBegin; 26807b62357SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2694f572ea9SToby Isaac PetscAssertPointer(domainerror, 2); 27007b62357SFande Kong *domainerror = snes->jacobiandomainerror; 2713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 27207b62357SFande Kong } 27307b62357SFande Kong 27455849f57SBarry Smith /*@C 275f6dfbefdSBarry Smith SNESLoad - Loads a `SNES` that has been stored in `PETSCVIEWERBINARY` with `SNESView()`. 27655849f57SBarry Smith 277c3339decSBarry Smith Collective 27855849f57SBarry Smith 27955849f57SBarry Smith Input Parameters: 280e4094ef1SJacob Faibussowitsch + snes - the newly loaded `SNES`, this needs to have been created with `SNESCreate()` or 281f6dfbefdSBarry Smith some related function before a call to `SNESLoad()`. 282f6dfbefdSBarry Smith - viewer - binary file viewer, obtained from `PetscViewerBinaryOpen()` 28355849f57SBarry Smith 28455849f57SBarry Smith Level: intermediate 28555849f57SBarry Smith 286f6dfbefdSBarry Smith Note: 287420bcc1bSBarry Smith The `SNESType` is determined by the data in the file, any type set into the `SNES` before this call is ignored. 28855849f57SBarry Smith 2891cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `PetscViewer`, `SNESCreate()`, `SNESType`, `PetscViewerBinaryOpen()`, `SNESView()`, `MatLoad()`, `VecLoad()` 29055849f57SBarry Smith @*/ 291d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESLoad(SNES snes, PetscViewer viewer) 292d71ae5a4SJacob Faibussowitsch { 29355849f57SBarry Smith PetscBool isbinary; 294060da220SMatthew G. Knepley PetscInt classid; 29555849f57SBarry Smith char type[256]; 29655849f57SBarry Smith KSP ksp; 2972d53ad75SBarry Smith DM dm; 2982d53ad75SBarry Smith DMSNES dmsnes; 29955849f57SBarry Smith 30055849f57SBarry Smith PetscFunctionBegin; 3012d53ad75SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 30255849f57SBarry Smith PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 3039566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 3045f80ce2aSJacob Faibussowitsch PetscCheck(isbinary, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerBinaryOpen()"); 30555849f57SBarry Smith 3069566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer, &classid, 1, NULL, PETSC_INT)); 3075f80ce2aSJacob Faibussowitsch PetscCheck(classid == SNES_FILE_CLASSID, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Not SNES next in file"); 3089566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer, type, 256, NULL, PETSC_CHAR)); 3099566063dSJacob Faibussowitsch PetscCall(SNESSetType(snes, type)); 310dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, load, viewer); 3119566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 3129566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &dmsnes)); 3139566063dSJacob Faibussowitsch PetscCall(DMSNESLoad(dmsnes, viewer)); 3149566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 3159566063dSJacob Faibussowitsch PetscCall(KSPLoad(ksp, viewer)); 3163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 31755849f57SBarry Smith } 3186a388c36SPeter Brune 3199804daf3SBarry Smith #include <petscdraw.h> 320e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS) 321e04113cfSBarry Smith #include <petscviewersaws.h> 322bfb97211SBarry Smith #endif 3238404b7f3SBarry Smith 324fe2efc57SMark /*@C 325dc4c0fb0SBarry Smith SNESViewFromOptions - View a `SNES` based on values in the options database 326fe2efc57SMark 327c3339decSBarry Smith Collective 328fe2efc57SMark 329fe2efc57SMark Input Parameters: 330f6dfbefdSBarry Smith + A - the `SNES` context 331dc4c0fb0SBarry Smith . obj - Optional object that provides the options prefix for the checks 332736c3998SJose E. Roman - name - command line option 333fe2efc57SMark 334fe2efc57SMark Level: intermediate 335f6dfbefdSBarry Smith 3361cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESView`, `PetscObjectViewFromOptions()`, `SNESCreate()` 337fe2efc57SMark @*/ 338d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESViewFromOptions(SNES A, PetscObject obj, const char name[]) 339d71ae5a4SJacob Faibussowitsch { 340fe2efc57SMark PetscFunctionBegin; 341fe2efc57SMark PetscValidHeaderSpecific(A, SNES_CLASSID, 1); 3429566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 3433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 344fe2efc57SMark } 345fe2efc57SMark 346789d8953SBarry Smith PETSC_EXTERN PetscErrorCode SNESComputeJacobian_DMDA(SNES, Vec, Mat, Mat, void *); 347789d8953SBarry Smith 3487e2c5f70SBarry Smith /*@C 349dc4c0fb0SBarry Smith SNESView - Prints or visualizes the `SNES` data structure. 3509b94acceSBarry Smith 351c3339decSBarry Smith Collective 352fee21e36SBarry Smith 353c7afd0dbSLois Curfman McInnes Input Parameters: 354f6dfbefdSBarry Smith + snes - the `SNES` context 355f6dfbefdSBarry Smith - viewer - the `PetscViewer` 356c7afd0dbSLois Curfman McInnes 3579b94acceSBarry Smith Options Database Key: 358f6dfbefdSBarry Smith . -snes_view - Calls `SNESView()` at end of `SNESSolve()` 3599b94acceSBarry Smith 360dc4c0fb0SBarry Smith Level: beginner 361dc4c0fb0SBarry Smith 3629b94acceSBarry Smith Notes: 3639b94acceSBarry Smith The available visualization contexts include 364f6dfbefdSBarry Smith + `PETSC_VIEWER_STDOUT_SELF` - standard output (default) 365f6dfbefdSBarry Smith - `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard 366c8a8ba5cSLois Curfman McInnes output where only the first processor opens 367c8a8ba5cSLois Curfman McInnes the file. All other processors send their 368c8a8ba5cSLois Curfman McInnes data to the first processor to print. 3699b94acceSBarry Smith 370052bf0daSPierre Jolivet The available formats include 371f6dfbefdSBarry Smith + `PETSC_VIEWER_DEFAULT` - standard output (default) 372f6dfbefdSBarry Smith - `PETSC_VIEWER_ASCII_INFO_DETAIL` - more verbose output for `SNESNASM` 373052bf0daSPierre Jolivet 3743e081fefSLois Curfman McInnes The user can open an alternative visualization context with 375f6dfbefdSBarry Smith `PetscViewerASCIIOpen()` - output to a specified file. 3769b94acceSBarry Smith 377f6dfbefdSBarry Smith In the debugger you can do "call `SNESView`(snes,0)" to display the `SNES` solver. (The same holds for any PETSc object viewer). 378595c91d4SBarry Smith 3791cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESLoad()`, `SNESCreate()`, `PetscViewerASCIIOpen()` 3809b94acceSBarry Smith @*/ 381d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESView(SNES snes, PetscViewer viewer) 382d71ae5a4SJacob Faibussowitsch { 383fa9f3622SBarry Smith SNESKSPEW *kctx; 38494b7f48cSBarry Smith KSP ksp; 3857f1410a3SPeter Brune SNESLineSearch linesearch; 38672a02f06SBarry Smith PetscBool iascii, isstring, isbinary, isdraw; 3872d53ad75SBarry Smith DMSNES dmsnes; 388e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS) 389536b137fSBarry Smith PetscBool issaws; 390bfb97211SBarry Smith #endif 3919b94acceSBarry Smith 3923a40ed3dSBarry Smith PetscFunctionBegin; 3930700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 39448a46eb9SPierre Jolivet if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &viewer)); 3950700a824SBarry Smith PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 396c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, viewer, 2); 39774679c65SBarry Smith 3989566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 3999566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 4009566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 4019566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 402e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS) 4039566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 404bfb97211SBarry Smith #endif 40532077d6dSBarry Smith if (iascii) { 406dc0571f2SMatthew G. Knepley SNESNormSchedule normschedule; 4078404b7f3SBarry Smith DM dm; 4088434afd1SBarry Smith SNESJacobianFn *cJ; 4098404b7f3SBarry Smith void *ctx; 410789d8953SBarry Smith const char *pre = ""; 411dc0571f2SMatthew G. Knepley 4129566063dSJacob Faibussowitsch PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)snes, viewer)); 41348a46eb9SPierre Jolivet if (!snes->setupcalled) PetscCall(PetscViewerASCIIPrintf(viewer, " SNES has not been set up so information may be incomplete\n")); 414e7788613SBarry Smith if (snes->ops->view) { 4159566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 416dbbe0bcdSBarry Smith PetscUseTypeMethod(snes, view, viewer); 4179566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 4180ef38995SBarry Smith } 41963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " maximum iterations=%" PetscInt_FMT ", maximum function evaluations=%" PetscInt_FMT "\n", snes->max_its, snes->max_funcs)); 4209566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " tolerances: relative=%g, absolute=%g, solution=%g\n", (double)snes->rtol, (double)snes->abstol, (double)snes->stol)); 42148a46eb9SPierre Jolivet if (snes->usesksp) PetscCall(PetscViewerASCIIPrintf(viewer, " total number of linear solver iterations=%" PetscInt_FMT "\n", snes->linear_its)); 42263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " total number of function evaluations=%" PetscInt_FMT "\n", snes->nfuncs)); 4239566063dSJacob Faibussowitsch PetscCall(SNESGetNormSchedule(snes, &normschedule)); 4249566063dSJacob Faibussowitsch if (normschedule > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " norm schedule %s\n", SNESNormSchedules[normschedule])); 42548a46eb9SPierre Jolivet if (snes->gridsequence) PetscCall(PetscViewerASCIIPrintf(viewer, " total number of grid sequence refinements=%" PetscInt_FMT "\n", snes->gridsequence)); 4269b94acceSBarry Smith if (snes->ksp_ewconv) { 427fa9f3622SBarry Smith kctx = (SNESKSPEW *)snes->kspconvctx; 4289b94acceSBarry Smith if (kctx) { 42963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Eisenstat-Walker computation of KSP relative tolerance (version %" PetscInt_FMT ")\n", kctx->version)); 4309566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " rtol_0=%g, rtol_max=%g, threshold=%g\n", (double)kctx->rtol_0, (double)kctx->rtol_max, (double)kctx->threshold)); 4319566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " gamma=%g, alpha=%g, alpha2=%g\n", (double)kctx->gamma, (double)kctx->alpha, (double)kctx->alpha2)); 4329b94acceSBarry Smith } 4339b94acceSBarry Smith } 434eb1f6c34SBarry Smith if (snes->lagpreconditioner == -1) { 4359566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Preconditioned is never rebuilt\n")); 436eb1f6c34SBarry Smith } else if (snes->lagpreconditioner > 1) { 43763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Preconditioned is rebuilt every %" PetscInt_FMT " new Jacobians\n", snes->lagpreconditioner)); 438eb1f6c34SBarry Smith } 439eb1f6c34SBarry Smith if (snes->lagjacobian == -1) { 4409566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Jacobian is never rebuilt\n")); 441eb1f6c34SBarry Smith } else if (snes->lagjacobian > 1) { 44263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Jacobian is rebuilt every %" PetscInt_FMT " SNES iterations\n", snes->lagjacobian)); 443eb1f6c34SBarry Smith } 4449566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 4459566063dSJacob Faibussowitsch PetscCall(DMSNESGetJacobian(dm, &cJ, &ctx)); 446789d8953SBarry Smith if (snes->mf_operator) { 4479566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Jacobian is applied matrix-free with differencing\n")); 448789d8953SBarry Smith pre = "Preconditioning "; 449789d8953SBarry Smith } 4508404b7f3SBarry Smith if (cJ == SNESComputeJacobianDefault) { 4519566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %sJacobian is built using finite differences one column at a time\n", pre)); 4528404b7f3SBarry Smith } else if (cJ == SNESComputeJacobianDefaultColor) { 4539566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %sJacobian is built using finite differences with coloring\n", pre)); 454789d8953SBarry Smith /* it slightly breaks data encapsulation for access the DMDA information directly */ 455789d8953SBarry Smith } else if (cJ == SNESComputeJacobian_DMDA) { 456789d8953SBarry Smith MatFDColoring fdcoloring; 4579566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)dm, "DMDASNES_FDCOLORING", (PetscObject *)&fdcoloring)); 458789d8953SBarry Smith if (fdcoloring) { 4599566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %sJacobian is built using colored finite differences on a DMDA\n", pre)); 460789d8953SBarry Smith } else { 4619566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %sJacobian is built using a DMDA local Jacobian\n", pre)); 462789d8953SBarry Smith } 463996e1cbcSBarry Smith } else if (snes->mf && !snes->mf_operator) { 4649566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Jacobian is applied matrix-free with differencing, no explicit Jacobian\n")); 4658404b7f3SBarry Smith } 4660f5bd95cSBarry Smith } else if (isstring) { 467317d6ea6SBarry Smith const char *type; 4689566063dSJacob Faibussowitsch PetscCall(SNESGetType(snes, &type)); 4699566063dSJacob Faibussowitsch PetscCall(PetscViewerStringSPrintf(viewer, " SNESType: %-7.7s", type)); 470dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, view, viewer); 47155849f57SBarry Smith } else if (isbinary) { 47255849f57SBarry Smith PetscInt classid = SNES_FILE_CLASSID; 47355849f57SBarry Smith MPI_Comm comm; 47455849f57SBarry Smith PetscMPIInt rank; 47555849f57SBarry Smith char type[256]; 47655849f57SBarry Smith 4779566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 4789566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 479dd400576SPatrick Sanan if (rank == 0) { 4809566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryWrite(viewer, &classid, 1, PETSC_INT)); 4819566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(type, ((PetscObject)snes)->type_name, sizeof(type))); 4829566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryWrite(viewer, type, sizeof(type), PETSC_CHAR)); 48355849f57SBarry Smith } 484dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, view, viewer); 48572a02f06SBarry Smith } else if (isdraw) { 48672a02f06SBarry Smith PetscDraw draw; 48772a02f06SBarry Smith char str[36]; 48889fd9fafSBarry Smith PetscReal x, y, bottom, h; 48972a02f06SBarry Smith 4909566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 4919566063dSJacob Faibussowitsch PetscCall(PetscDrawGetCurrentPoint(draw, &x, &y)); 4929566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(str, "SNES: ", sizeof(str))); 4939566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(str, ((PetscObject)snes)->type_name, sizeof(str))); 4949566063dSJacob Faibussowitsch PetscCall(PetscDrawStringBoxed(draw, x, y, PETSC_DRAW_BLUE, PETSC_DRAW_BLACK, str, NULL, &h)); 49589fd9fafSBarry Smith bottom = y - h; 4969566063dSJacob Faibussowitsch PetscCall(PetscDrawPushCurrentPoint(draw, x, bottom)); 497dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, view, viewer); 498e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS) 499536b137fSBarry Smith } else if (issaws) { 500d45a07a7SBarry Smith PetscMPIInt rank; 5012657e9d9SBarry Smith const char *name; 502d45a07a7SBarry Smith 5039566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)snes, &name)); 5049566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 505dd400576SPatrick Sanan if (!((PetscObject)snes)->amsmem && rank == 0) { 506d45a07a7SBarry Smith char dir[1024]; 507d45a07a7SBarry Smith 5089566063dSJacob Faibussowitsch PetscCall(PetscObjectViewSAWs((PetscObject)snes, viewer)); 5099566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/its", name)); 510792fecdfSBarry Smith PetscCallSAWs(SAWs_Register, (dir, &snes->iter, 1, SAWs_READ, SAWs_INT)); 51148a46eb9SPierre Jolivet if (!snes->conv_hist) PetscCall(SNESSetConvergenceHistory(snes, NULL, NULL, PETSC_DECIDE, PETSC_TRUE)); 5129566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/conv_hist", name)); 513792fecdfSBarry Smith PetscCallSAWs(SAWs_Register, (dir, snes->conv_hist, 10, SAWs_READ, SAWs_DOUBLE)); 514f05ece33SBarry Smith } 515bfb97211SBarry Smith #endif 51672a02f06SBarry Smith } 51772a02f06SBarry Smith if (snes->linesearch) { 5189566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &linesearch)); 5199566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 5209566063dSJacob Faibussowitsch PetscCall(SNESLineSearchView(linesearch, viewer)); 5219566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 52219bcc07fSBarry Smith } 523efd4aadfSBarry Smith if (snes->npc && snes->usesnpc) { 5249566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 5259566063dSJacob Faibussowitsch PetscCall(SNESView(snes->npc, viewer)); 5269566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 5274a0c5b0cSMatthew G Knepley } 5289566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 5299566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(snes->dm, &dmsnes)); 5309566063dSJacob Faibussowitsch PetscCall(DMSNESView(dmsnes, viewer)); 5319566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 5322c155ee1SBarry Smith if (snes->usesksp) { 5339566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 5349566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 5359566063dSJacob Faibussowitsch PetscCall(KSPView(ksp, viewer)); 5369566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 5372c155ee1SBarry Smith } 53872a02f06SBarry Smith if (isdraw) { 53972a02f06SBarry Smith PetscDraw draw; 5409566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 5419566063dSJacob Faibussowitsch PetscCall(PetscDrawPopCurrentPoint(draw)); 5427f1410a3SPeter Brune } 5433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5449b94acceSBarry Smith } 5459b94acceSBarry Smith 54676b2cf59SMatthew Knepley /* 54776b2cf59SMatthew Knepley We retain a list of functions that also take SNES command 54876b2cf59SMatthew Knepley line options. These are called at the end SNESSetFromOptions() 54976b2cf59SMatthew Knepley */ 55076b2cf59SMatthew Knepley #define MAXSETFROMOPTIONS 5 551a7cc72afSBarry Smith static PetscInt numberofsetfromoptions; 5526849ba73SBarry Smith static PetscErrorCode (*othersetfromoptions[MAXSETFROMOPTIONS])(SNES); 55376b2cf59SMatthew Knepley 554ac226902SBarry Smith /*@C 555f6dfbefdSBarry Smith SNESAddOptionsChecker - Adds an additional function to check for `SNES` options. 55676b2cf59SMatthew Knepley 55776b2cf59SMatthew Knepley Not Collective 55876b2cf59SMatthew Knepley 55976b2cf59SMatthew Knepley Input Parameter: 56076b2cf59SMatthew Knepley . snescheck - function that checks for options 56176b2cf59SMatthew Knepley 562420bcc1bSBarry Smith Calling sequence of `snescheck`: 563420bcc1bSBarry Smith . snes - the `SNES` object for which it is checking options 564420bcc1bSBarry Smith 56576b2cf59SMatthew Knepley Level: developer 56676b2cf59SMatthew Knepley 5671cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()` 56876b2cf59SMatthew Knepley @*/ 569420bcc1bSBarry Smith PetscErrorCode SNESAddOptionsChecker(PetscErrorCode (*snescheck)(SNES snes)) 570d71ae5a4SJacob Faibussowitsch { 57176b2cf59SMatthew Knepley PetscFunctionBegin; 57263a3b9bcSJacob Faibussowitsch PetscCheck(numberofsetfromoptions < MAXSETFROMOPTIONS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many options checkers, only %d allowed", MAXSETFROMOPTIONS); 57376b2cf59SMatthew Knepley othersetfromoptions[numberofsetfromoptions++] = snescheck; 5743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 57576b2cf59SMatthew Knepley } 57676b2cf59SMatthew Knepley 577d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetUpMatrixFree_Private(SNES snes, PetscBool hasOperator, PetscInt version) 578d71ae5a4SJacob Faibussowitsch { 579aa3661deSLisandro Dalcin Mat J; 580895c21f2SBarry Smith MatNullSpace nullsp; 581aa3661deSLisandro Dalcin 582aa3661deSLisandro Dalcin PetscFunctionBegin; 5830700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 584aa3661deSLisandro Dalcin 58598613b67SLisandro Dalcin if (!snes->vec_func && (snes->jacobian || snes->jacobian_pre)) { 58698613b67SLisandro Dalcin Mat A = snes->jacobian, B = snes->jacobian_pre; 5879566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A ? A : B, NULL, &snes->vec_func)); 58898613b67SLisandro Dalcin } 58998613b67SLisandro Dalcin 5900fdf79fbSJacob Faibussowitsch PetscCheck(version == 1 || version == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "matrix-free operator routines, only version 1 and 2"); 591aa3661deSLisandro Dalcin if (version == 1) { 5929566063dSJacob Faibussowitsch PetscCall(MatCreateSNESMF(snes, &J)); 5939566063dSJacob Faibussowitsch PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix)); 5949566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(J)); 5951e2ae407SBarry Smith /* TODO: the version 2 code should be merged into the MatCreateSNESMF() and MatCreateMFFD() infrastructure and then removed */ 5960fdf79fbSJacob Faibussowitsch } else /* if (version == 2) */ { 5975f80ce2aSJacob Faibussowitsch PetscCheck(snes->vec_func, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "SNESSetFunction() must be called first"); 598570b7f6dSBarry Smith #if !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_REAL_SINGLE) && !defined(PETSC_USE_REAL___FLOAT128) && !defined(PETSC_USE_REAL___FP16) 599f6dfbefdSBarry Smith PetscCall(MatCreateSNESMFMore(snes, snes->vec_func, &J)); 600aa3661deSLisandro Dalcin #else 6012479783cSJose E. Roman SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "matrix-free operator routines (version 2)"); 602aa3661deSLisandro Dalcin #endif 6030fdf79fbSJacob Faibussowitsch } 604aa3661deSLisandro Dalcin 60501c1178eSBarry Smith /* attach any user provided null space that was on Amat to the newly created matrix-free matrix */ 606895c21f2SBarry Smith if (snes->jacobian) { 6079566063dSJacob Faibussowitsch PetscCall(MatGetNullSpace(snes->jacobian, &nullsp)); 6081baa6e33SBarry Smith if (nullsp) PetscCall(MatSetNullSpace(J, nullsp)); 609895c21f2SBarry Smith } 610895c21f2SBarry Smith 61163a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Setting default matrix-free operator routines (version %" PetscInt_FMT ")\n", version)); 612d3462f78SMatthew Knepley if (hasOperator) { 613aa3661deSLisandro Dalcin /* This version replaces the user provided Jacobian matrix with a 614aa3661deSLisandro Dalcin matrix-free version but still employs the user-provided preconditioner matrix. */ 6159566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL)); 616aa3661deSLisandro Dalcin } else { 617aa3661deSLisandro Dalcin /* This version replaces both the user-provided Jacobian and the user- 61801c1178eSBarry Smith provided preconditioner Jacobian with the default matrix-free version. */ 619b552625fSStefano Zampini if (snes->npcside == PC_LEFT && snes->npc) { 6209566063dSJacob Faibussowitsch if (!snes->jacobian) PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL)); 621172a4300SPeter Brune } else { 622789d8953SBarry Smith KSP ksp; 623789d8953SBarry Smith PC pc; 624789d8953SBarry Smith PetscBool match; 625789d8953SBarry Smith 6269566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J, J, MatMFFDComputeJacobian, NULL)); 627aa3661deSLisandro Dalcin /* Force no preconditioner */ 6289566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 6299566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksp, &pc)); 6302698c518SLisandro Dalcin PetscCall(PetscObjectTypeCompareAny((PetscObject)pc, &match, PCSHELL, PCH2OPUS, "")); 631aa3661deSLisandro Dalcin if (!match) { 6329566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Setting default matrix-free preconditioner routines\nThat is no preconditioner is being used\n")); 6339566063dSJacob Faibussowitsch PetscCall(PCSetType(pc, PCNONE)); 634aa3661deSLisandro Dalcin } 635aa3661deSLisandro Dalcin } 636789d8953SBarry Smith } 6379566063dSJacob Faibussowitsch PetscCall(MatDestroy(&J)); 6383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 639aa3661deSLisandro Dalcin } 640aa3661deSLisandro Dalcin 641d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMRestrictHook_SNESVecSol(DM dmfine, Mat Restrict, Vec Rscale, Mat Inject, DM dmcoarse, void *ctx) 642d71ae5a4SJacob Faibussowitsch { 643dfe15315SJed Brown SNES snes = (SNES)ctx; 6440298fd71SBarry Smith Vec Xfine, Xfine_named = NULL, Xcoarse; 645dfe15315SJed Brown 646dfe15315SJed Brown PetscFunctionBegin; 64716ebb321SJed Brown if (PetscLogPrintInfo) { 64816ebb321SJed Brown PetscInt finelevel, coarselevel, fineclevel, coarseclevel; 6499566063dSJacob Faibussowitsch PetscCall(DMGetRefineLevel(dmfine, &finelevel)); 6509566063dSJacob Faibussowitsch PetscCall(DMGetCoarsenLevel(dmfine, &fineclevel)); 6519566063dSJacob Faibussowitsch PetscCall(DMGetRefineLevel(dmcoarse, &coarselevel)); 6529566063dSJacob Faibussowitsch PetscCall(DMGetCoarsenLevel(dmcoarse, &coarseclevel)); 65363a3b9bcSJacob 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)); 65416ebb321SJed Brown } 655dfe15315SJed Brown if (dmfine == snes->dm) Xfine = snes->vec_sol; 656dfe15315SJed Brown else { 6579566063dSJacob Faibussowitsch PetscCall(DMGetNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named)); 658dfe15315SJed Brown Xfine = Xfine_named; 659dfe15315SJed Brown } 6609566063dSJacob Faibussowitsch PetscCall(DMGetNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse)); 661907f5c5aSLawrence Mitchell if (Inject) { 6629566063dSJacob Faibussowitsch PetscCall(MatRestrict(Inject, Xfine, Xcoarse)); 663907f5c5aSLawrence Mitchell } else { 6649566063dSJacob Faibussowitsch PetscCall(MatRestrict(Restrict, Xfine, Xcoarse)); 6659566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(Xcoarse, Xcoarse, Rscale)); 666907f5c5aSLawrence Mitchell } 6679566063dSJacob Faibussowitsch PetscCall(DMRestoreNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse)); 6689566063dSJacob Faibussowitsch if (Xfine_named) PetscCall(DMRestoreNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named)); 6693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 670dfe15315SJed Brown } 671dfe15315SJed Brown 672d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCoarsenHook_SNESVecSol(DM dm, DM dmc, void *ctx) 673d71ae5a4SJacob Faibussowitsch { 67416ebb321SJed Brown PetscFunctionBegin; 6759566063dSJacob Faibussowitsch PetscCall(DMCoarsenHookAdd(dmc, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, ctx)); 6763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 67716ebb321SJed Brown } 67816ebb321SJed Brown 679a6950cb2SJed Brown /* This may be called to rediscretize the operator on levels of linear multigrid. The DM shuffle is so the user can 680a6950cb2SJed Brown * safely call SNESGetDM() in their residual evaluation routine. */ 681d71ae5a4SJacob Faibussowitsch static PetscErrorCode KSPComputeOperators_SNES(KSP ksp, Mat A, Mat B, void *ctx) 682d71ae5a4SJacob Faibussowitsch { 683caa4e7f2SJed Brown SNES snes = (SNES)ctx; 6840298fd71SBarry Smith Vec X, Xnamed = NULL; 685dfe15315SJed Brown DM dmsave; 6864e269d77SPeter Brune void *ctxsave; 6878434afd1SBarry Smith SNESJacobianFn *jac = NULL; 688caa4e7f2SJed Brown 689caa4e7f2SJed Brown PetscFunctionBegin; 690dfe15315SJed Brown dmsave = snes->dm; 6919566063dSJacob Faibussowitsch PetscCall(KSPGetDM(ksp, &snes->dm)); 692dfe15315SJed Brown if (dmsave == snes->dm) X = snes->vec_sol; /* We are on the finest level */ 6939371c9d4SSatish Balay else { /* We are on a coarser level, this vec was initialized using a DM restrict hook */ PetscCall(DMGetNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed)); 694dfe15315SJed Brown X = Xnamed; 6959566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, NULL, NULL, &jac, &ctxsave)); 6964e269d77SPeter Brune /* If the DM's don't match up, the MatFDColoring context needed for the jacobian won't match up either -- fixit. */ 69748a46eb9SPierre Jolivet if (jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, SNESComputeJacobianDefaultColor, NULL)); 6984e269d77SPeter Brune } 6994dde8bb0SMatthew G. Knepley /* Make sure KSP DM has the Jacobian computation routine */ 7004dde8bb0SMatthew G. Knepley { 7014dde8bb0SMatthew G. Knepley DMSNES sdm; 7024e269d77SPeter Brune 7039566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(snes->dm, &sdm)); 70448a46eb9SPierre Jolivet if (!sdm->ops->computejacobian) PetscCall(DMCopyDMSNES(dmsave, snes->dm)); 7054dde8bb0SMatthew G. Knepley } 7062b93b426SMatthew G. Knepley /* Compute the operators */ 7079566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobian(snes, X, A, B)); 7082b93b426SMatthew G. Knepley /* Put the previous context back */ 70948a46eb9SPierre Jolivet if (snes->dm != dmsave && jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, jac, ctxsave)); 7104e269d77SPeter Brune 7119566063dSJacob Faibussowitsch if (Xnamed) PetscCall(DMRestoreNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed)); 712dfe15315SJed Brown snes->dm = dmsave; 7133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 714caa4e7f2SJed Brown } 715caa4e7f2SJed Brown 7166cab3a1bSJed Brown /*@ 717dc4c0fb0SBarry Smith SNESSetUpMatrices - ensures that matrices are available for `SNES` Newton-like methods, this is called by `SNESSetUp_XXX()` 7186cab3a1bSJed Brown 7196cab3a1bSJed Brown Collective 7206cab3a1bSJed Brown 7214165533cSJose E. Roman Input Parameter: 72220f4b53cSBarry Smith . snes - `SNES` object to configure 7236cab3a1bSJed Brown 7246cab3a1bSJed Brown Level: developer 7256cab3a1bSJed Brown 726dc4c0fb0SBarry Smith Note: 727dc4c0fb0SBarry 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` 728dc4c0fb0SBarry Smith 7291cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUp()` 7306cab3a1bSJed Brown @*/ 731d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUpMatrices(SNES snes) 732d71ae5a4SJacob Faibussowitsch { 7336cab3a1bSJed Brown DM dm; 734942e3340SBarry Smith DMSNES sdm; 7356cab3a1bSJed Brown 7366cab3a1bSJed Brown PetscFunctionBegin; 7379566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 7389566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 73958b371f3SBarry Smith if (!snes->jacobian && snes->mf) { 7406cab3a1bSJed Brown Mat J; 7416cab3a1bSJed Brown void *functx; 7429566063dSJacob Faibussowitsch PetscCall(MatCreateSNESMF(snes, &J)); 7439566063dSJacob Faibussowitsch PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix)); 7449566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(J)); 7459566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, NULL, &functx)); 7469566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J, J, NULL, NULL)); 7479566063dSJacob Faibussowitsch PetscCall(MatDestroy(&J)); 748caa4e7f2SJed Brown } else if (snes->mf_operator && !snes->jacobian_pre && !snes->jacobian) { 7496cab3a1bSJed Brown Mat J, B; 7509566063dSJacob Faibussowitsch PetscCall(MatCreateSNESMF(snes, &J)); 7519566063dSJacob Faibussowitsch PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix)); 7529566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(J)); 7539566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(snes->dm, &B)); 75406f20277SJed Brown /* sdm->computejacobian was already set to reach here */ 7559566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J, B, NULL, NULL)); 7569566063dSJacob Faibussowitsch PetscCall(MatDestroy(&J)); 7579566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 758caa4e7f2SJed Brown } else if (!snes->jacobian_pre) { 7591ba9b98eSMatthew G. Knepley PetscDS prob; 7606cab3a1bSJed Brown Mat J, B; 7611ba9b98eSMatthew G. Knepley PetscBool hasPrec = PETSC_FALSE; 7621ba9b98eSMatthew G. Knepley 7636cab3a1bSJed Brown J = snes->jacobian; 7649566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob)); 7659566063dSJacob Faibussowitsch if (prob) PetscCall(PetscDSHasJacobianPreconditioner(prob, &hasPrec)); 7669566063dSJacob Faibussowitsch if (J) PetscCall(PetscObjectReference((PetscObject)J)); 7679566063dSJacob Faibussowitsch else if (hasPrec) PetscCall(DMCreateMatrix(snes->dm, &J)); 7689566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(snes->dm, &B)); 7699566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J ? J : B, B, NULL, NULL)); 7709566063dSJacob Faibussowitsch PetscCall(MatDestroy(&J)); 7719566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 7726cab3a1bSJed Brown } 773caa4e7f2SJed Brown { 774caa4e7f2SJed Brown KSP ksp; 7759566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 7769566063dSJacob Faibussowitsch PetscCall(KSPSetComputeOperators(ksp, KSPComputeOperators_SNES, snes)); 7779566063dSJacob Faibussowitsch PetscCall(DMCoarsenHookAdd(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes)); 778caa4e7f2SJed Brown } 7793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7806cab3a1bSJed Brown } 7816cab3a1bSJed Brown 782d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESMonitorPauseFinal_Internal(SNES snes) 783d71ae5a4SJacob Faibussowitsch { 7845e7c47f3SMatthew G. Knepley PetscInt i; 7855e7c47f3SMatthew G. Knepley 7865e7c47f3SMatthew G. Knepley PetscFunctionBegin; 7873ba16761SJacob Faibussowitsch if (!snes->pauseFinal) PetscFunctionReturn(PETSC_SUCCESS); 7885e7c47f3SMatthew G. Knepley for (i = 0; i < snes->numbermonitors; ++i) { 7895e7c47f3SMatthew G. Knepley PetscViewerAndFormat *vf = (PetscViewerAndFormat *)snes->monitorcontext[i]; 7905e7c47f3SMatthew G. Knepley PetscDraw draw; 7915e7c47f3SMatthew G. Knepley PetscReal lpause; 7925e7c47f3SMatthew G. Knepley 7935e7c47f3SMatthew G. Knepley if (!vf) continue; 7945e7c47f3SMatthew G. Knepley if (vf->lg) { 7955e7c47f3SMatthew G. Knepley if (!PetscCheckPointer(vf->lg, PETSC_OBJECT)) continue; 7965e7c47f3SMatthew G. Knepley if (((PetscObject)vf->lg)->classid != PETSC_DRAWLG_CLASSID) continue; 7979566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(vf->lg, &draw)); 7989566063dSJacob Faibussowitsch PetscCall(PetscDrawGetPause(draw, &lpause)); 7999566063dSJacob Faibussowitsch PetscCall(PetscDrawSetPause(draw, -1.0)); 8009566063dSJacob Faibussowitsch PetscCall(PetscDrawPause(draw)); 8019566063dSJacob Faibussowitsch PetscCall(PetscDrawSetPause(draw, lpause)); 8025e7c47f3SMatthew G. Knepley } else { 8035e7c47f3SMatthew G. Knepley PetscBool isdraw; 8045e7c47f3SMatthew G. Knepley 8055e7c47f3SMatthew G. Knepley if (!PetscCheckPointer(vf->viewer, PETSC_OBJECT)) continue; 8065e7c47f3SMatthew G. Knepley if (((PetscObject)vf->viewer)->classid != PETSC_VIEWER_CLASSID) continue; 8079566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)vf->viewer, PETSCVIEWERDRAW, &isdraw)); 8085e7c47f3SMatthew G. Knepley if (!isdraw) continue; 8099566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(vf->viewer, 0, &draw)); 8109566063dSJacob Faibussowitsch PetscCall(PetscDrawGetPause(draw, &lpause)); 8119566063dSJacob Faibussowitsch PetscCall(PetscDrawSetPause(draw, -1.0)); 8129566063dSJacob Faibussowitsch PetscCall(PetscDrawPause(draw)); 8139566063dSJacob Faibussowitsch PetscCall(PetscDrawSetPause(draw, lpause)); 8145e7c47f3SMatthew G. Knepley } 8155e7c47f3SMatthew G. Knepley } 8163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8175e7c47f3SMatthew G. Knepley } 8185e7c47f3SMatthew G. Knepley 819fde5950dSBarry Smith /*@C 820fde5950dSBarry Smith SNESMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user 821fde5950dSBarry Smith 822c3339decSBarry Smith Collective 823fde5950dSBarry Smith 824fde5950dSBarry Smith Input Parameters: 825dc4c0fb0SBarry Smith + snes - `SNES` object you wish to monitor 826fde5950dSBarry Smith . name - the monitor type one is seeking 827fde5950dSBarry Smith . help - message indicating what monitoring is done 828fde5950dSBarry Smith . manual - manual page for the monitor 829fde5950dSBarry Smith . monitor - the monitor function 830f6dfbefdSBarry 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 831fde5950dSBarry Smith 832420bcc1bSBarry Smith Calling sequence of `monitor`: 833420bcc1bSBarry Smith + snes - the nonlinear solver context 834420bcc1bSBarry Smith . it - the current iteration 835420bcc1bSBarry Smith . r - the current function norm 836420bcc1bSBarry Smith - vf - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use 837420bcc1bSBarry Smith 838420bcc1bSBarry Smith Calling sequence of `monitorsetup`: 839420bcc1bSBarry Smith + snes - the nonlinear solver context 840420bcc1bSBarry Smith - vf - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use 841420bcc1bSBarry Smith 842f6dfbefdSBarry Smith Options Database Key: 843f6dfbefdSBarry Smith . -name - trigger the use of this monitor in `SNESSetFromOptions()` 844f6dfbefdSBarry Smith 845f6dfbefdSBarry Smith Level: advanced 846fde5950dSBarry Smith 8471cc06b55SBarry Smith .seealso: [](ch_snes), `PetscOptionsGetViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, 848db781477SPatrick Sanan `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()` 849e4094ef1SJacob Faibussowitsch `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, 850db781477SPatrick Sanan `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`, 851c2e3fba1SPatrick Sanan `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`, 852db781477SPatrick Sanan `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`, 853db781477SPatrick Sanan `PetscOptionsFList()`, `PetscOptionsEList()` 854fde5950dSBarry Smith @*/ 855420bcc1bSBarry 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)) 856d71ae5a4SJacob Faibussowitsch { 857fde5950dSBarry Smith PetscViewer viewer; 858fde5950dSBarry Smith PetscViewerFormat format; 859fde5950dSBarry Smith PetscBool flg; 860fde5950dSBarry Smith 861fde5950dSBarry Smith PetscFunctionBegin; 8629566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, name, &viewer, &format, &flg)); 863fde5950dSBarry Smith if (flg) { 864d43b4f6eSBarry Smith PetscViewerAndFormat *vf; 8659566063dSJacob Faibussowitsch PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf)); 866cd791dc2SBarry Smith PetscCall(PetscOptionsRestoreViewer(&viewer)); 8671baa6e33SBarry Smith if (monitorsetup) PetscCall((*monitorsetup)(snes, vf)); 8689566063dSJacob Faibussowitsch PetscCall(SNESMonitorSet(snes, (PetscErrorCode(*)(SNES, PetscInt, PetscReal, void *))monitor, vf, (PetscErrorCode(*)(void **))PetscViewerAndFormatDestroy)); 869fde5950dSBarry Smith } 8703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 871fde5950dSBarry Smith } 872fde5950dSBarry Smith 873a4598233SStefano Zampini PetscErrorCode SNESEWSetFromOptions_Private(SNESKSPEW *kctx, PetscBool print_api, MPI_Comm comm, const char *prefix) 874d71ae5a4SJacob Faibussowitsch { 875a4598233SStefano Zampini const char *api = print_api ? "SNESKSPSetParametersEW" : NULL; 876a4598233SStefano Zampini 8770f0abf79SStefano Zampini PetscFunctionBegin; 8780f0abf79SStefano Zampini PetscOptionsBegin(comm, prefix, "Eisenstat and Walker type forcing options", "KSP"); 879a4598233SStefano Zampini PetscCall(PetscOptionsInt("-ksp_ew_version", "Version 1, 2 or 3", api, kctx->version, &kctx->version, NULL)); 880a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_rtol0", "0 <= rtol0 < 1", api, kctx->rtol_0, &kctx->rtol_0, NULL)); 881a4598233SStefano Zampini kctx->rtol_max = PetscMax(kctx->rtol_0, kctx->rtol_max); 882a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_rtolmax", "0 <= rtolmax < 1", api, kctx->rtol_max, &kctx->rtol_max, NULL)); 883a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_gamma", "0 <= gamma <= 1", api, kctx->gamma, &kctx->gamma, NULL)); 884a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_alpha", "1 < alpha <= 2", api, kctx->alpha, &kctx->alpha, NULL)); 8850f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_alpha2", "alpha2", NULL, kctx->alpha2, &kctx->alpha2, NULL)); 886a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_threshold", "0 < threshold < 1", api, kctx->threshold, &kctx->threshold, NULL)); 8870f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_p1", "p1", NULL, kctx->v4_p1, &kctx->v4_p1, NULL)); 8880f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_p2", "p2", NULL, kctx->v4_p2, &kctx->v4_p2, NULL)); 8890f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_p3", "p3", NULL, kctx->v4_p3, &kctx->v4_p3, NULL)); 8900f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_m1", "Scaling when rk-1 in [p2,p3)", NULL, kctx->v4_m1, &kctx->v4_m1, NULL)); 8910f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_m2", "Scaling when rk-1 in [p3,+infty)", NULL, kctx->v4_m2, &kctx->v4_m2, NULL)); 8920f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_m3", "Threshold for successive rtol (0.1 in Eq.7)", NULL, kctx->v4_m3, &kctx->v4_m3, NULL)); 8930f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_m4", "Adaptation scaling (0.5 in Eq.7)", NULL, kctx->v4_m4, &kctx->v4_m4, NULL)); 8940f0abf79SStefano Zampini PetscOptionsEnd(); 8953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8960f0abf79SStefano Zampini } 8970f0abf79SStefano Zampini 8989b94acceSBarry Smith /*@ 899f6dfbefdSBarry Smith SNESSetFromOptions - Sets various `SNES` and `KSP` parameters from user options. 9009b94acceSBarry Smith 901c3339decSBarry Smith Collective 902c7afd0dbSLois Curfman McInnes 9039b94acceSBarry Smith Input Parameter: 904f6dfbefdSBarry Smith . snes - the `SNES` context 9059b94acceSBarry Smith 90636851e7fSLois Curfman McInnes Options Database Keys: 907f6dfbefdSBarry Smith + -snes_type <type> - newtonls, newtontr, ngmres, ncg, nrichardson, qn, vi, fas, `SNESType` for complete list 908ceaaa498SBarry Smith . -snes_stol <stol> - convergence tolerance in terms of the norm of the change in the solution between steps 90970441072SBarry Smith . -snes_atol <abstol> - absolute tolerance of residual norm 910b39c3a46SLois Curfman McInnes . -snes_rtol <rtol> - relative decrease in tolerance norm from initial 911e4d06f11SPatrick Farrell . -snes_divergence_tolerance <divtol> - if the residual goes above divtol*rnorm0, exit with divergence 912ceaaa498SBarry Smith . -snes_force_iteration <force> - force `SNESSolve()` to take at least one iteration 913b39c3a46SLois Curfman McInnes . -snes_max_it <max_it> - maximum number of iterations 914b39c3a46SLois Curfman McInnes . -snes_max_funcs <max_funcs> - maximum number of function evaluations 9154839bfe8SBarry Smith . -snes_max_fail <max_fail> - maximum number of line search failures allowed before stopping, default is none 916ddf469c8SBarry Smith . -snes_max_linear_solve_fail - number of linear solver failures before SNESSolve() stops 917a8054027SBarry Smith . -snes_lag_preconditioner <lag> - how often preconditioner is rebuilt (use -1 to never rebuild) 9183d5a8a6aSBarry Smith . -snes_lag_preconditioner_persists <true,false> - retains the -snes_lag_preconditioner information across multiple SNESSolve() 919e35cf81dSBarry Smith . -snes_lag_jacobian <lag> - how often Jacobian is rebuilt (use -1 to never rebuild) 9203d5a8a6aSBarry Smith . -snes_lag_jacobian_persists <true,false> - retains the -snes_lag_jacobian information across multiple SNESSolve() 9214a221d59SStefano Zampini . -snes_tr_tol <trtol> - trust region tolerance 922ceaaa498SBarry Smith . -snes_convergence_test <default,skip,correct_pressure> - convergence test in nonlinear solver. default `SNESConvergedDefault()`. skip `SNESConvergedSkip()` means continue iterating until max_it or some other criterion is reached, saving expense of convergence test. correct_pressure `SNESConvergedCorrectPressure()` has special handling of a pressure null space. 923fde5950dSBarry Smith . -snes_monitor [ascii][:filename][:viewer format] - prints residual norm at each iteration. if no filename given prints to stdout 924fde5950dSBarry Smith . -snes_monitor_solution [ascii binary draw][:filename][:viewer format] - plots solution at each iteration 925fde5950dSBarry Smith . -snes_monitor_residual [ascii binary draw][:filename][:viewer format] - plots residual (not its norm) at each iteration 926fde5950dSBarry Smith . -snes_monitor_solution_update [ascii binary draw][:filename][:viewer format] - plots update to solution at each iteration 9274619e776SBarry Smith . -snes_monitor_lg_residualnorm - plots residual norm at each iteration 928459f5d12SBarry Smith . -snes_monitor_lg_range - plots residual norm at each iteration 9295e7c47f3SMatthew G. Knepley . -snes_monitor_pause_final - Pauses all monitor drawing after the solver ends 930e24b481bSBarry Smith . -snes_fd - use finite differences to compute Jacobian; very slow, only for testing 931e2e60de9SPeter Brune . -snes_fd_color - use finite differences with coloring to compute Jacobian 932ceaaa498SBarry Smith . -snes_mf_ksp_monitor - if using matrix-free multiply then print h at each `KSP` iteration 933b5badacbSBarry Smith . -snes_converged_reason - print the reason for convergence/divergence after each solve 934ceaaa498SBarry Smith . -npc_snes_type <type> - the `SNES` type to use as a nonlinear preconditioner 935e62ac41dSBarry Smith . -snes_test_jacobian <optional threshold> - compare the user provided Jacobian with one computed via finite differences to check for errors. If a threshold is given, display only those entries whose difference is greater than the threshold. 936e62ac41dSBarry Smith - -snes_test_jacobian_view - display the user provided Jacobian, the finite difference Jacobian and the difference between them to help users detect the location of errors in the user provided Jacobian. 93782738288SBarry Smith 938f6dfbefdSBarry Smith Options Database Keys for Eisenstat-Walker method: 939fa9f3622SBarry Smith + -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence 9404b27c08aSLois Curfman McInnes . -snes_ksp_ew_version ver - version of Eisenstat-Walker method 94136851e7fSLois Curfman McInnes . -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0 94236851e7fSLois Curfman McInnes . -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax 94336851e7fSLois Curfman McInnes . -snes_ksp_ew_gamma <gamma> - Sets gamma 94436851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha <alpha> - Sets alpha 94536851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2 94636851e7fSLois Curfman McInnes - -snes_ksp_ew_threshold <threshold> - Sets threshold 94782738288SBarry Smith 948dc4c0fb0SBarry Smith Level: beginner 949dc4c0fb0SBarry Smith 95011ca99fdSLois Curfman McInnes Notes: 951ec5066bdSBarry Smith To see all options, run your program with the -help option or consult the users manual 952ec5066bdSBarry Smith 953420bcc1bSBarry Smith `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`, 954420bcc1bSBarry Smith and computing explicitly with 955f6dfbefdSBarry Smith finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object. 95683e2fdc7SBarry Smith 957420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESType`, `SNESSetOptionsPrefix()`, `SNESResetFromOptions()`, `SNES`, `SNESCreate()`, `MatCreateSNESMF()`, `MatFDColoring` 9589b94acceSBarry Smith @*/ 959d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFromOptions(SNES snes) 960d71ae5a4SJacob Faibussowitsch { 9618afaa268SBarry Smith PetscBool flg, pcset, persist, set; 962d8f46077SPeter Brune PetscInt i, indx, lag, grids; 96304d7464bSBarry Smith const char *deft = SNESNEWTONLS; 964649ef022SMatthew Knepley const char *convtests[] = {"default", "skip", "correct_pressure"}; 96585385478SLisandro Dalcin SNESKSPEW *kctx = NULL; 9660f0abf79SStefano Zampini char type[256], monfilename[PETSC_MAX_PATH_LEN], ewprefix[256]; 967c40d0f55SPeter Brune PCSide pcside; 968a64e098fSPeter Brune const char *optionsprefix; 9699b94acceSBarry Smith 9703a40ed3dSBarry Smith PetscFunctionBegin; 9710700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 9729566063dSJacob Faibussowitsch PetscCall(SNESRegisterAll()); 973d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)snes); 974639ff905SBarry Smith if (((PetscObject)snes)->type_name) deft = ((PetscObject)snes)->type_name; 9759566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-snes_type", "Nonlinear solver method", "SNESSetType", SNESList, deft, type, 256, &flg)); 976d64ed03dSBarry Smith if (flg) { 9779566063dSJacob Faibussowitsch PetscCall(SNESSetType(snes, type)); 9787adad957SLisandro Dalcin } else if (!((PetscObject)snes)->type_name) { 9799566063dSJacob Faibussowitsch PetscCall(SNESSetType(snes, deft)); 980d64ed03dSBarry Smith } 9819566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-snes_stol", "Stop if step length less than", "SNESSetTolerances", snes->stol, &snes->stol, NULL)); 9829566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-snes_atol", "Stop if function norm less than", "SNESSetTolerances", snes->abstol, &snes->abstol, NULL)); 983186905e3SBarry Smith 9849566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-snes_rtol", "Stop if decrease in function norm less than", "SNESSetTolerances", snes->rtol, &snes->rtol, NULL)); 9859566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-snes_divergence_tolerance", "Stop if residual norm increases by this factor", "SNESSetDivergenceTolerance", snes->divtol, &snes->divtol, NULL)); 9869566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_max_it", "Maximum iterations", "SNESSetTolerances", snes->max_its, &snes->max_its, NULL)); 9879566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_max_funcs", "Maximum function evaluations", "SNESSetTolerances", snes->max_funcs, &snes->max_funcs, NULL)); 9889566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_max_fail", "Maximum nonlinear step failures", "SNESSetMaxNonlinearStepFailures", snes->maxFailures, &snes->maxFailures, NULL)); 9899566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_max_linear_solve_fail", "Maximum failures in linear solves allowed", "SNESSetMaxLinearSolveFailures", snes->maxLinearSolveFailures, &snes->maxLinearSolveFailures, NULL)); 9909566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_error_if_not_converged", "Generate error if solver does not converge", "SNESSetErrorIfNotConverged", snes->errorifnotconverged, &snes->errorifnotconverged, NULL)); 9919566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_force_iteration", "Force SNESSolve() to take at least one iteration", "SNESSetForceIteration", snes->forceiteration, &snes->forceiteration, NULL)); 9929566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_check_jacobian_domain_error", "Check Jacobian domain error after Jacobian evaluation", "SNESCheckJacobianDomainError", snes->checkjacdomainerror, &snes->checkjacdomainerror, NULL)); 99385385478SLisandro Dalcin 9949566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_lag_preconditioner", "How often to rebuild preconditioner", "SNESSetLagPreconditioner", snes->lagpreconditioner, &lag, &flg)); 995a8054027SBarry Smith if (flg) { 9965f80ce2aSJacob 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"); 9979566063dSJacob Faibussowitsch PetscCall(SNESSetLagPreconditioner(snes, lag)); 998a8054027SBarry Smith } 9999566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_lag_preconditioner_persists", "Preconditioner lagging through multiple SNES solves", "SNESSetLagPreconditionerPersists", snes->lagjac_persist, &persist, &flg)); 10001baa6e33SBarry Smith if (flg) PetscCall(SNESSetLagPreconditionerPersists(snes, persist)); 10019566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_lag_jacobian", "How often to rebuild Jacobian", "SNESSetLagJacobian", snes->lagjacobian, &lag, &flg)); 1002e35cf81dSBarry Smith if (flg) { 10035f80ce2aSJacob 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"); 10049566063dSJacob Faibussowitsch PetscCall(SNESSetLagJacobian(snes, lag)); 1005e35cf81dSBarry Smith } 10069566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_lag_jacobian_persists", "Jacobian lagging through multiple SNES solves", "SNESSetLagJacobianPersists", snes->lagjac_persist, &persist, &flg)); 10071baa6e33SBarry Smith if (flg) PetscCall(SNESSetLagJacobianPersists(snes, persist)); 100837ec4e1aSPeter Brune 10099566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_grid_sequence", "Use grid sequencing to generate initial guess", "SNESSetGridSequence", snes->gridsequence, &grids, &flg)); 10101baa6e33SBarry Smith if (flg) PetscCall(SNESSetGridSequence(snes, grids)); 1011a8054027SBarry Smith 1012400f6f02SBarry Smith PetscCall(PetscOptionsEList("-snes_convergence_test", "Convergence test", "SNESSetConvergenceTest", convtests, PETSC_STATIC_ARRAY_LENGTH(convtests), "default", &indx, &flg)); 101385385478SLisandro Dalcin if (flg) { 101485385478SLisandro Dalcin switch (indx) { 1015d71ae5a4SJacob Faibussowitsch case 0: 1016d71ae5a4SJacob Faibussowitsch PetscCall(SNESSetConvergenceTest(snes, SNESConvergedDefault, NULL, NULL)); 1017d71ae5a4SJacob Faibussowitsch break; 1018d71ae5a4SJacob Faibussowitsch case 1: 1019d71ae5a4SJacob Faibussowitsch PetscCall(SNESSetConvergenceTest(snes, SNESConvergedSkip, NULL, NULL)); 1020d71ae5a4SJacob Faibussowitsch break; 1021d71ae5a4SJacob Faibussowitsch case 2: 1022d71ae5a4SJacob Faibussowitsch PetscCall(SNESSetConvergenceTest(snes, SNESConvergedCorrectPressure, NULL, NULL)); 1023d71ae5a4SJacob Faibussowitsch break; 102485385478SLisandro Dalcin } 102585385478SLisandro Dalcin } 102685385478SLisandro Dalcin 10279566063dSJacob Faibussowitsch PetscCall(PetscOptionsEList("-snes_norm_schedule", "SNES Norm schedule", "SNESSetNormSchedule", SNESNormSchedules, 5, "function", &indx, &flg)); 10289566063dSJacob Faibussowitsch if (flg) PetscCall(SNESSetNormSchedule(snes, (SNESNormSchedule)indx)); 1029fdacfa88SPeter Brune 10309566063dSJacob Faibussowitsch PetscCall(PetscOptionsEList("-snes_function_type", "SNES Norm schedule", "SNESSetFunctionType", SNESFunctionTypes, 2, "unpreconditioned", &indx, &flg)); 10319566063dSJacob Faibussowitsch if (flg) PetscCall(SNESSetFunctionType(snes, (SNESFunctionType)indx)); 1032186905e3SBarry Smith 103385385478SLisandro Dalcin kctx = (SNESKSPEW *)snes->kspconvctx; 103485385478SLisandro Dalcin 10359566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_ksp_ew", "Use Eisentat-Walker linear system convergence test", "SNESKSPSetUseEW", snes->ksp_ewconv, &snes->ksp_ewconv, NULL)); 1036186905e3SBarry Smith 10370f0abf79SStefano Zampini PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 10380f0abf79SStefano Zampini PetscCall(PetscSNPrintf(ewprefix, sizeof(ewprefix), "%s%s", optionsprefix ? optionsprefix : "", "snes_")); 1039a4598233SStefano Zampini PetscCall(SNESEWSetFromOptions_Private(kctx, PETSC_TRUE, PetscObjectComm((PetscObject)snes), ewprefix)); 1040186905e3SBarry Smith 104190d69ab7SBarry Smith flg = PETSC_FALSE; 10429566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_monitor_cancel", "Remove all monitors", "SNESMonitorCancel", flg, &flg, &set)); 10439566063dSJacob Faibussowitsch if (set && flg) PetscCall(SNESMonitorCancel(snes)); 1044eabae89aSBarry Smith 10459566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor", "Monitor norm of function", "SNESMonitorDefault", SNESMonitorDefault, SNESMonitorDefaultSetUp)); 10469566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_short", "Monitor norm of function with fewer digits", "SNESMonitorDefaultShort", SNESMonitorDefaultShort, NULL)); 10479566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_range", "Monitor range of elements of function", "SNESMonitorRange", SNESMonitorRange, NULL)); 1048eabae89aSBarry Smith 10499566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_ratio", "Monitor ratios of the norm of function for consecutive steps", "SNESMonitorRatio", SNESMonitorRatio, SNESMonitorRatioSetUp)); 10509566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_field", "Monitor norm of function (split into fields)", "SNESMonitorDefaultField", SNESMonitorDefaultField, NULL)); 10519566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution", "View solution at each iteration", "SNESMonitorSolution", SNESMonitorSolution, NULL)); 10529566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution_update", "View correction at each iteration", "SNESMonitorSolutionUpdate", SNESMonitorSolutionUpdate, NULL)); 10539566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_residual", "View residual at each iteration", "SNESMonitorResidual", SNESMonitorResidual, NULL)); 10549566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_jacupdate_spectrum", "Print the change in the spectrum of the Jacobian", "SNESMonitorJacUpdateSpectrum", SNESMonitorJacUpdateSpectrum, NULL)); 10559566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_fields", "Monitor norm of function per field", "SNESMonitorSet", SNESMonitorFields, NULL)); 10569566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_monitor_pause_final", "Pauses all draw monitors at the final iterate", "SNESMonitorPauseFinal_Internal", PETSC_FALSE, &snes->pauseFinal, NULL)); 10572db13446SMatthew G. Knepley 10589566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-snes_monitor_python", "Use Python function", "SNESMonitorSet", NULL, monfilename, sizeof(monfilename), &flg)); 10599566063dSJacob Faibussowitsch if (flg) PetscCall(PetscPythonMonitorSet((PetscObject)snes, monfilename)); 10605180491cSLisandro Dalcin 106190d69ab7SBarry Smith flg = PETSC_FALSE; 10629566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_monitor_lg_range", "Plot function range at each iteration", "SNESMonitorLGRange", flg, &flg, NULL)); 1063459f5d12SBarry Smith if (flg) { 1064459f5d12SBarry Smith PetscViewer ctx; 1065e24b481bSBarry Smith 10669566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &ctx)); 10679566063dSJacob Faibussowitsch PetscCall(SNESMonitorSet(snes, SNESMonitorLGRange, ctx, (PetscErrorCode(*)(void **))PetscViewerDestroy)); 1068459f5d12SBarry Smith } 10692e7541e6SPeter Brune 107090d69ab7SBarry Smith flg = PETSC_FALSE; 10719566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_converged_reason_view_cancel", "Remove all converged reason viewers", "SNESConvergedReasonViewCancel", flg, &flg, &set)); 10729566063dSJacob Faibussowitsch if (set && flg) PetscCall(SNESConvergedReasonViewCancel(snes)); 1073c4421ceaSFande Kong 1074c4421ceaSFande Kong flg = PETSC_FALSE; 10759566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_fd", "Use finite differences (slow) to compute Jacobian", "SNESComputeJacobianDefault", flg, &flg, NULL)); 10764b27c08aSLois Curfman McInnes if (flg) { 10776cab3a1bSJed Brown void *functx; 1078b1f624c7SBarry Smith DM dm; 10799566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 1080800f99ffSJeremy L Thompson PetscCall(DMSNESUnsetJacobianContext_Internal(dm)); 10819566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, NULL, &functx)); 10829566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefault, functx)); 10839566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Setting default finite difference Jacobian matrix\n")); 10849b94acceSBarry Smith } 1085639f9d9dSBarry Smith 108644848bc4SPeter Brune flg = PETSC_FALSE; 10879566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_fd_function", "Use finite differences (slow) to compute function from user objective", "SNESObjectiveComputeFunctionDefaultFD", flg, &flg, NULL)); 10881baa6e33SBarry Smith if (flg) PetscCall(SNESSetFunction(snes, NULL, SNESObjectiveComputeFunctionDefaultFD, NULL)); 108997584545SPeter Brune 109097584545SPeter Brune flg = PETSC_FALSE; 10919566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_fd_color", "Use finite differences with coloring to compute Jacobian", "SNESComputeJacobianDefaultColor", flg, &flg, NULL)); 109244848bc4SPeter Brune if (flg) { 1093c52e227fSPeter Brune DM dm; 10949566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 1095800f99ffSJeremy L Thompson PetscCall(DMSNESUnsetJacobianContext_Internal(dm)); 10969566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefaultColor, NULL)); 10979566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Setting default finite difference coloring Jacobian matrix\n")); 109844848bc4SPeter Brune } 109944848bc4SPeter Brune 1100aa3661deSLisandro Dalcin flg = PETSC_FALSE; 11019566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_mf_operator", "Use a Matrix-Free Jacobian with user-provided preconditioner matrix", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf_operator, &flg)); 1102d8f46077SPeter Brune if (flg && snes->mf_operator) { 1103a8248277SBarry Smith snes->mf_operator = PETSC_TRUE; 1104d8f46077SPeter Brune snes->mf = PETSC_TRUE; 1105a8248277SBarry Smith } 1106aa3661deSLisandro Dalcin flg = PETSC_FALSE; 11079566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_mf", "Use a Matrix-Free Jacobian with no preconditioner matrix", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf, &flg)); 1108d8f46077SPeter Brune if (!flg && snes->mf_operator) snes->mf = PETSC_TRUE; 11099566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_mf_version", "Matrix-Free routines version 1 or 2", "None", snes->mf_version, &snes->mf_version, NULL)); 1110d28543b3SPeter Brune 1111c40d0f55SPeter Brune flg = PETSC_FALSE; 11129566063dSJacob Faibussowitsch PetscCall(SNESGetNPCSide(snes, &pcside)); 11139566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-snes_npc_side", "SNES nonlinear preconditioner side", "SNESSetNPCSide", PCSides, (PetscEnum)pcside, (PetscEnum *)&pcside, &flg)); 11149566063dSJacob Faibussowitsch if (flg) PetscCall(SNESSetNPCSide(snes, pcside)); 1115c40d0f55SPeter Brune 1116e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS) 11178a70d858SHong Zhang /* 11188a70d858SHong Zhang Publish convergence information using SAWs 11198a70d858SHong Zhang */ 11208a70d858SHong Zhang flg = PETSC_FALSE; 11219566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_monitor_saws", "Publish SNES progress using SAWs", "SNESMonitorSet", flg, &flg, NULL)); 11228a70d858SHong Zhang if (flg) { 11238a70d858SHong Zhang void *ctx; 11249566063dSJacob Faibussowitsch PetscCall(SNESMonitorSAWsCreate(snes, &ctx)); 11259566063dSJacob Faibussowitsch PetscCall(SNESMonitorSet(snes, SNESMonitorSAWs, ctx, SNESMonitorSAWsDestroy)); 11268a70d858SHong Zhang } 11278a70d858SHong Zhang #endif 11288a70d858SHong Zhang #if defined(PETSC_HAVE_SAWS) 1129b90c6cbeSBarry Smith { 1130b90c6cbeSBarry Smith PetscBool set; 1131b90c6cbeSBarry Smith flg = PETSC_FALSE; 11329566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_saws_block", "Block for SAWs at end of SNESSolve", "PetscObjectSAWsBlock", ((PetscObject)snes)->amspublishblock, &flg, &set)); 11331baa6e33SBarry Smith if (set) PetscCall(PetscObjectSAWsSetBlock((PetscObject)snes, flg)); 1134b90c6cbeSBarry Smith } 1135b90c6cbeSBarry Smith #endif 1136b90c6cbeSBarry Smith 113748a46eb9SPierre Jolivet for (i = 0; i < numberofsetfromoptions; i++) PetscCall((*othersetfromoptions[i])(snes)); 113876b2cf59SMatthew Knepley 1139dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, setfromoptions, PetscOptionsObject); 11405d973c19SBarry Smith 11415d973c19SBarry Smith /* process any options handlers added with PetscObjectAddOptionsHandler() */ 1142dbbe0bcdSBarry Smith PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)snes, PetscOptionsObject)); 1143d0609cedSBarry Smith PetscOptionsEnd(); 11444bbc92c1SBarry Smith 1145d8d34be6SBarry Smith if (snes->linesearch) { 11469566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 11479566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetFromOptions(snes->linesearch)); 1148d8d34be6SBarry Smith } 11499e764e56SPeter Brune 11506aa5e7e9SBarry Smith if (snes->usesksp) { 11519566063dSJacob Faibussowitsch if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 11529566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(snes->ksp, snes->jacobian, snes->jacobian_pre)); 11539566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(snes->ksp)); 11546aa5e7e9SBarry Smith } 11556991f827SBarry Smith 1156b5badacbSBarry Smith /* if user has set the SNES NPC type via options database, create it. */ 11579566063dSJacob Faibussowitsch PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 11589566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)snes)->options, optionsprefix, "-npc_snes_type", &pcset)); 115948a46eb9SPierre Jolivet if (pcset && (!snes->npc)) PetscCall(SNESGetNPC(snes, &snes->npc)); 11601baa6e33SBarry Smith if (snes->npc) PetscCall(SNESSetFromOptions(snes->npc)); 1161b3cd9a81SMatthew G. Knepley snes->setfromoptionscalled++; 11623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1163b3cd9a81SMatthew G. Knepley } 1164b3cd9a81SMatthew G. Knepley 1165b3cd9a81SMatthew G. Knepley /*@ 1166420bcc1bSBarry Smith SNESResetFromOptions - Sets various `SNES` and `KSP` parameters from user options ONLY if the `SNESSetFromOptions()` was previously called 1167b3cd9a81SMatthew G. Knepley 1168c3339decSBarry Smith Collective 1169b3cd9a81SMatthew G. Knepley 1170b3cd9a81SMatthew G. Knepley Input Parameter: 1171f6dfbefdSBarry Smith . snes - the `SNES` context 1172b3cd9a81SMatthew G. Knepley 1173420bcc1bSBarry Smith Level: advanced 1174b3cd9a81SMatthew G. Knepley 11751cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESSetOptionsPrefix()` 1176b3cd9a81SMatthew G. Knepley @*/ 1177d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESResetFromOptions(SNES snes) 1178d71ae5a4SJacob Faibussowitsch { 1179b3cd9a81SMatthew G. Knepley PetscFunctionBegin; 11809566063dSJacob Faibussowitsch if (snes->setfromoptionscalled) PetscCall(SNESSetFromOptions(snes)); 11813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11829b94acceSBarry Smith } 11839b94acceSBarry Smith 1184bb9467b5SJed Brown /*@C 1185d25893d9SBarry Smith SNESSetComputeApplicationContext - Sets an optional function to compute a user-defined context for 1186d25893d9SBarry Smith the nonlinear solvers. 1187d25893d9SBarry Smith 1188dc4c0fb0SBarry Smith Logically Collective; No Fortran Support 1189d25893d9SBarry Smith 1190d25893d9SBarry Smith Input Parameters: 1191f6dfbefdSBarry Smith + snes - the `SNES` context 1192d25893d9SBarry Smith . compute - function to compute the context 1193d25893d9SBarry Smith - destroy - function to destroy the context 1194d25893d9SBarry Smith 1195420bcc1bSBarry Smith Calling sequence of `compute`: 1196420bcc1bSBarry Smith + snes - the `SNES` context 1197420bcc1bSBarry Smith - ctx - context to be computed 1198420bcc1bSBarry Smith 1199420bcc1bSBarry Smith Calling sequence of `destroy`: 1200420bcc1bSBarry Smith . ctx - context to be computed by `compute()` 1201420bcc1bSBarry Smith 1202d25893d9SBarry Smith Level: intermediate 1203d25893d9SBarry Smith 1204f6dfbefdSBarry Smith Note: 1205f6dfbefdSBarry Smith This routine is useful if you are performing grid sequencing or using `SNESFAS` and need the appropriate context generated for each level. 1206f6dfbefdSBarry Smith 1207f6dfbefdSBarry Smith Use `SNESSetApplicationContext()` to see the context immediately 1208f6dfbefdSBarry Smith 120942747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNESGetApplicationContext()`, `SNESSetApplicationContext()` 1210d25893d9SBarry Smith @*/ 1211420bcc1bSBarry Smith PetscErrorCode SNESSetComputeApplicationContext(SNES snes, PetscErrorCode (*compute)(SNES snes, void **ctx), PetscErrorCode (*destroy)(void **ctx)) 1212d71ae5a4SJacob Faibussowitsch { 1213d25893d9SBarry Smith PetscFunctionBegin; 1214d25893d9SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1215d25893d9SBarry Smith snes->ops->usercompute = compute; 1216d25893d9SBarry Smith snes->ops->userdestroy = destroy; 12173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1218d25893d9SBarry Smith } 1219a847f771SSatish Balay 1220b07ff414SBarry Smith /*@ 1221f6dfbefdSBarry Smith SNESSetApplicationContext - Sets the optional user-defined context for the nonlinear solvers. 12229b94acceSBarry Smith 1223c3339decSBarry Smith Logically Collective 1224fee21e36SBarry Smith 1225c7afd0dbSLois Curfman McInnes Input Parameters: 1226f6dfbefdSBarry Smith + snes - the `SNES` context 1227c7afd0dbSLois Curfman McInnes - usrP - optional user context 1228c7afd0dbSLois Curfman McInnes 122936851e7fSLois Curfman McInnes Level: intermediate 123036851e7fSLois Curfman McInnes 1231f6dfbefdSBarry Smith Notes: 1232f6dfbefdSBarry Smith Users can provide a context when constructing the `SNES` options and then access it inside their function, Jacobian, or other evaluation function 1233f6dfbefdSBarry Smith with `SNESGetApplicationContext()` 1234f6dfbefdSBarry Smith 1235f6dfbefdSBarry Smith To provide a function that computes the context for you use `SNESSetComputeApplicationContext()` 1236f6dfbefdSBarry Smith 1237420bcc1bSBarry Smith Fortran Note: 1238dc4c0fb0SBarry Smith You must write a Fortran interface definition for this 1239420bcc1bSBarry Smith function that tells Fortran the Fortran derived data type that you are passing in as the `usrP` argument. 1240daf670e6SBarry Smith 12411cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetComputeApplicationContext()`, `SNESGetApplicationContext()` 12429b94acceSBarry Smith @*/ 1243d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetApplicationContext(SNES snes, void *usrP) 1244d71ae5a4SJacob Faibussowitsch { 1245b07ff414SBarry Smith KSP ksp; 12461b2093e4SBarry Smith 12473a40ed3dSBarry Smith PetscFunctionBegin; 12480700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 12499566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 12509566063dSJacob Faibussowitsch PetscCall(KSPSetApplicationContext(ksp, usrP)); 12519b94acceSBarry Smith snes->user = usrP; 12523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12539b94acceSBarry Smith } 125474679c65SBarry Smith 1255b07ff414SBarry Smith /*@ 12569b94acceSBarry Smith SNESGetApplicationContext - Gets the user-defined context for the 1257420bcc1bSBarry Smith nonlinear solvers set with `SNESGetApplicationContext()` or `SNESSetComputeApplicationContext()` 12589b94acceSBarry Smith 1259c7afd0dbSLois Curfman McInnes Not Collective 1260c7afd0dbSLois Curfman McInnes 12619b94acceSBarry Smith Input Parameter: 1262f6dfbefdSBarry Smith . snes - `SNES` context 12639b94acceSBarry Smith 12649b94acceSBarry Smith Output Parameter: 12659b94acceSBarry Smith . usrP - user context 12669b94acceSBarry Smith 126736851e7fSLois Curfman McInnes Level: intermediate 126836851e7fSLois Curfman McInnes 1269420bcc1bSBarry Smith Fortran Note: 1270dc4c0fb0SBarry Smith You must write a Fortran interface definition for this 1271420bcc1bSBarry Smith function that tells Fortran the Fortran derived data type that you are passing in as the `usrP` argument. 1272dc4c0fb0SBarry Smith 1273420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESSetApplicationContext()`, `SNESSetComputeApplicationContext()` 12749b94acceSBarry Smith @*/ 1275d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetApplicationContext(SNES snes, void *usrP) 1276d71ae5a4SJacob Faibussowitsch { 12773a40ed3dSBarry Smith PetscFunctionBegin; 12780700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1279e71120c6SJed Brown *(void **)usrP = snes->user; 12803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12819b94acceSBarry Smith } 128274679c65SBarry Smith 12839b94acceSBarry Smith /*@ 1284420bcc1bSBarry Smith SNESSetUseMatrixFree - indicates that `SNES` should use matrix-free finite difference matrix-vector products to apply the Jacobian. 12853565c898SBarry Smith 1286dc4c0fb0SBarry Smith Logically Collective 12873565c898SBarry Smith 12883565c898SBarry Smith Input Parameters: 1289f6dfbefdSBarry Smith + snes - `SNES` context 1290f6dfbefdSBarry Smith . mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used 1291f6dfbefdSBarry 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 1292420bcc1bSBarry Smith this option no matrix-element based preconditioners can be used in the linear solve since the matrix won't be explicitly available 12933565c898SBarry Smith 1294f6dfbefdSBarry Smith Options Database Keys: 129501c1178eSBarry Smith + -snes_mf_operator - use matrix-free only for the mat operator 1296f6dfbefdSBarry Smith . -snes_mf - use matrix-free for both the mat and pmat operator 1297ec5066bdSBarry Smith . -snes_fd_color - compute the Jacobian via coloring and finite differences. 1298ec5066bdSBarry Smith - -snes_fd - compute the Jacobian via finite differences (slow) 12993565c898SBarry Smith 13003565c898SBarry Smith Level: intermediate 13013565c898SBarry Smith 1302f6dfbefdSBarry Smith Note: 1303420bcc1bSBarry Smith `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`, 1304420bcc1bSBarry Smith and computing explicitly with 1305f6dfbefdSBarry Smith finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object. 1306ec5066bdSBarry Smith 1307420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetUseMatrixFree()`, `MatCreateSNESMF()`, `SNESComputeJacobianDefaultColor()`, `MatFDColoring` 13083565c898SBarry Smith @*/ 1309d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUseMatrixFree(SNES snes, PetscBool mf_operator, PetscBool mf) 1310d71ae5a4SJacob Faibussowitsch { 13113565c898SBarry Smith PetscFunctionBegin; 13123565c898SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 131388b4c220SStefano Zampini PetscValidLogicalCollectiveBool(snes, mf_operator, 2); 131488b4c220SStefano Zampini PetscValidLogicalCollectiveBool(snes, mf, 3); 13154ddffce6SLisandro Dalcin snes->mf = mf_operator ? PETSC_TRUE : mf; 13163565c898SBarry Smith snes->mf_operator = mf_operator; 13173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13183565c898SBarry Smith } 13193565c898SBarry Smith 13203565c898SBarry Smith /*@ 1321dc4c0fb0SBarry Smith SNESGetUseMatrixFree - indicates if the `SNES` uses matrix-free finite difference matrix vector products to apply the Jacobian. 13223565c898SBarry Smith 1323420bcc1bSBarry Smith Not Collective, but the resulting flags will be the same on all MPI processes 13243565c898SBarry Smith 13253565c898SBarry Smith Input Parameter: 1326f6dfbefdSBarry Smith . snes - `SNES` context 13273565c898SBarry Smith 13283565c898SBarry Smith Output Parameters: 1329f6dfbefdSBarry Smith + mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used 1330f6dfbefdSBarry 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 13313565c898SBarry Smith 13323565c898SBarry Smith Level: intermediate 13333565c898SBarry Smith 13341cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUseMatrixFree()`, `MatCreateSNESMF()` 13353565c898SBarry Smith @*/ 1336d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUseMatrixFree(SNES snes, PetscBool *mf_operator, PetscBool *mf) 1337d71ae5a4SJacob Faibussowitsch { 13383565c898SBarry Smith PetscFunctionBegin; 13393565c898SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 13403565c898SBarry Smith if (mf) *mf = snes->mf; 13413565c898SBarry Smith if (mf_operator) *mf_operator = snes->mf_operator; 13423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13433565c898SBarry Smith } 13443565c898SBarry Smith 13453565c898SBarry Smith /*@ 1346420bcc1bSBarry Smith SNESGetIterationNumber - Gets the number of nonlinear iterations completed in the current or most recent `SNESSolve()` 13479b94acceSBarry Smith 1348c7afd0dbSLois Curfman McInnes Not Collective 1349c7afd0dbSLois Curfman McInnes 13509b94acceSBarry Smith Input Parameter: 1351f6dfbefdSBarry Smith . snes - `SNES` context 13529b94acceSBarry Smith 13539b94acceSBarry Smith Output Parameter: 13549b94acceSBarry Smith . iter - iteration number 13559b94acceSBarry Smith 1356dc4c0fb0SBarry Smith Level: intermediate 1357dc4c0fb0SBarry Smith 1358c8228a4eSBarry Smith Notes: 1359c8228a4eSBarry Smith For example, during the computation of iteration 2 this would return 1. 1360c8228a4eSBarry Smith 1361c8228a4eSBarry Smith This is useful for using lagged Jacobians (where one does not recompute the 1362f6dfbefdSBarry Smith Jacobian at each `SNES` iteration). For example, the code 136308405cd6SLois Curfman McInnes .vb 136408405cd6SLois Curfman McInnes ierr = SNESGetIterationNumber(snes,&it); 136508405cd6SLois Curfman McInnes if (!(it % 2)) { 136608405cd6SLois Curfman McInnes [compute Jacobian here] 136708405cd6SLois Curfman McInnes } 136808405cd6SLois Curfman McInnes .ve 1369f6dfbefdSBarry Smith can be used in your function that computes the Jacobian to cause the Jacobian to be 1370f6dfbefdSBarry Smith recomputed every second `SNES` iteration. See also `SNESSetLagJacobian()` 1371c8228a4eSBarry Smith 1372f6dfbefdSBarry Smith After the `SNES` solve is complete this will return the number of nonlinear iterations used. 1373c04deec6SBarry Smith 1374420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetLagJacobian()`, `SNESGetLinearSolveIterations()`, `SNESSetMonitor()` 13759b94acceSBarry Smith @*/ 1376d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetIterationNumber(SNES snes, PetscInt *iter) 1377d71ae5a4SJacob Faibussowitsch { 13783a40ed3dSBarry Smith PetscFunctionBegin; 13790700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 13804f572ea9SToby Isaac PetscAssertPointer(iter, 2); 13819b94acceSBarry Smith *iter = snes->iter; 13823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13839b94acceSBarry Smith } 138474679c65SBarry Smith 1385360c497dSPeter Brune /*@ 1386360c497dSPeter Brune SNESSetIterationNumber - Sets the current iteration number. 1387360c497dSPeter Brune 1388360c497dSPeter Brune Not Collective 1389360c497dSPeter Brune 1390d8d19677SJose E. Roman Input Parameters: 1391f6dfbefdSBarry Smith + snes - `SNES` context 1392a2b725a8SWilliam Gropp - iter - iteration number 1393360c497dSPeter Brune 1394360c497dSPeter Brune Level: developer 1395360c497dSPeter Brune 1396420bcc1bSBarry Smith Note: 1397420bcc1bSBarry Smith This should only be called inside a `SNES` nonlinear solver. 1398420bcc1bSBarry Smith 13991cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetLinearSolveIterations()` 1400360c497dSPeter Brune @*/ 1401d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetIterationNumber(SNES snes, PetscInt iter) 1402d71ae5a4SJacob Faibussowitsch { 1403360c497dSPeter Brune PetscFunctionBegin; 1404360c497dSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 14059566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes)); 1406360c497dSPeter Brune snes->iter = iter; 14079566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes)); 14083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1409360c497dSPeter Brune } 1410360c497dSPeter Brune 14119b94acceSBarry Smith /*@ 1412b850b91aSLisandro Dalcin SNESGetNonlinearStepFailures - Gets the number of unsuccessful steps 1413420bcc1bSBarry Smith attempted by the nonlinear solver in the current or most recent `SNESSolve()` . 14149b94acceSBarry Smith 1415c7afd0dbSLois Curfman McInnes Not Collective 1416c7afd0dbSLois Curfman McInnes 14179b94acceSBarry Smith Input Parameter: 1418f6dfbefdSBarry Smith . snes - `SNES` context 14199b94acceSBarry Smith 14209b94acceSBarry Smith Output Parameter: 14219b94acceSBarry Smith . nfails - number of unsuccessful steps attempted 14229b94acceSBarry Smith 1423dc4c0fb0SBarry Smith Level: intermediate 1424dc4c0fb0SBarry Smith 1425f6dfbefdSBarry Smith Note: 1426f6dfbefdSBarry Smith This counter is reset to zero for each successive call to `SNESSolve()`. 1427c96a6f78SLois Curfman McInnes 14281cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, 1429db781477SPatrick Sanan `SNESSetMaxNonlinearStepFailures()`, `SNESGetMaxNonlinearStepFailures()` 14309b94acceSBarry Smith @*/ 1431d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNonlinearStepFailures(SNES snes, PetscInt *nfails) 1432d71ae5a4SJacob Faibussowitsch { 14333a40ed3dSBarry Smith PetscFunctionBegin; 14340700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 14354f572ea9SToby Isaac PetscAssertPointer(nfails, 2); 143650ffb88aSMatthew Knepley *nfails = snes->numFailures; 14373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 143850ffb88aSMatthew Knepley } 143950ffb88aSMatthew Knepley 144050ffb88aSMatthew Knepley /*@ 1441b850b91aSLisandro Dalcin SNESSetMaxNonlinearStepFailures - Sets the maximum number of unsuccessful steps 1442420bcc1bSBarry Smith attempted by the nonlinear solver before it gives up and returns unconverged or generates an error 144350ffb88aSMatthew Knepley 144450ffb88aSMatthew Knepley Not Collective 144550ffb88aSMatthew Knepley 144650ffb88aSMatthew Knepley Input Parameters: 1447f6dfbefdSBarry Smith + snes - `SNES` context 144850ffb88aSMatthew Knepley - maxFails - maximum of unsuccessful steps 144950ffb88aSMatthew Knepley 1450420bcc1bSBarry Smith Options Database Key: 1451420bcc1bSBarry Smith . -snes_max_fail <n> - maximum number of unsuccessful steps allowed 1452420bcc1bSBarry Smith 145350ffb88aSMatthew Knepley Level: intermediate 145450ffb88aSMatthew Knepley 1455420bcc1bSBarry Smith Developer Note: 1456420bcc1bSBarry Smith The options database key is wrong for this function name 1457420bcc1bSBarry Smith 14581cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, 1459db781477SPatrick Sanan `SNESGetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()` 146050ffb88aSMatthew Knepley @*/ 1461d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxNonlinearStepFailures(SNES snes, PetscInt maxFails) 1462d71ae5a4SJacob Faibussowitsch { 146350ffb88aSMatthew Knepley PetscFunctionBegin; 14640700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 146550ffb88aSMatthew Knepley snes->maxFailures = maxFails; 14663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 146750ffb88aSMatthew Knepley } 146850ffb88aSMatthew Knepley 146950ffb88aSMatthew Knepley /*@ 1470b850b91aSLisandro Dalcin SNESGetMaxNonlinearStepFailures - Gets the maximum number of unsuccessful steps 1471420bcc1bSBarry Smith attempted by the nonlinear solver before it gives up and returns unconverged or generates an error 147250ffb88aSMatthew Knepley 147350ffb88aSMatthew Knepley Not Collective 147450ffb88aSMatthew Knepley 147550ffb88aSMatthew Knepley Input Parameter: 147620f4b53cSBarry Smith . snes - `SNES` context 147750ffb88aSMatthew Knepley 147850ffb88aSMatthew Knepley Output Parameter: 147950ffb88aSMatthew Knepley . maxFails - maximum of unsuccessful steps 148050ffb88aSMatthew Knepley 148150ffb88aSMatthew Knepley Level: intermediate 148250ffb88aSMatthew Knepley 14831cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, 1484db781477SPatrick Sanan `SNESSetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()` 148550ffb88aSMatthew Knepley @*/ 1486d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxNonlinearStepFailures(SNES snes, PetscInt *maxFails) 1487d71ae5a4SJacob Faibussowitsch { 148850ffb88aSMatthew Knepley PetscFunctionBegin; 14890700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 14904f572ea9SToby Isaac PetscAssertPointer(maxFails, 2); 149150ffb88aSMatthew Knepley *maxFails = snes->maxFailures; 14923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14939b94acceSBarry Smith } 1494a847f771SSatish Balay 14952541af92SBarry Smith /*@ 14962541af92SBarry Smith SNESGetNumberFunctionEvals - Gets the number of user provided function evaluations 1497420bcc1bSBarry Smith done by the `SNES` object in the current or most recent `SNESSolve()` 14982541af92SBarry Smith 14992541af92SBarry Smith Not Collective 15002541af92SBarry Smith 15012541af92SBarry Smith Input Parameter: 1502f6dfbefdSBarry Smith . snes - `SNES` context 15032541af92SBarry Smith 15042541af92SBarry Smith Output Parameter: 15052541af92SBarry Smith . nfuncs - number of evaluations 15062541af92SBarry Smith 15072541af92SBarry Smith Level: intermediate 15082541af92SBarry Smith 1509f6dfbefdSBarry Smith Note: 1510f6dfbefdSBarry Smith Reset every time `SNESSolve()` is called unless `SNESSetCountersReset()` is used. 1511971e163fSPeter Brune 15121cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, `SNESSetCountersReset()` 15132541af92SBarry Smith @*/ 1514d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNumberFunctionEvals(SNES snes, PetscInt *nfuncs) 1515d71ae5a4SJacob Faibussowitsch { 15162541af92SBarry Smith PetscFunctionBegin; 15170700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 15184f572ea9SToby Isaac PetscAssertPointer(nfuncs, 2); 15192541af92SBarry Smith *nfuncs = snes->nfuncs; 15203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15212541af92SBarry Smith } 15222541af92SBarry Smith 15233d4c4710SBarry Smith /*@ 15243d4c4710SBarry Smith SNESGetLinearSolveFailures - Gets the number of failed (non-converged) 1525420bcc1bSBarry Smith linear solvers in the current or most recent `SNESSolve()` 15263d4c4710SBarry Smith 15273d4c4710SBarry Smith Not Collective 15283d4c4710SBarry Smith 15293d4c4710SBarry Smith Input Parameter: 1530f6dfbefdSBarry Smith . snes - `SNES` context 15313d4c4710SBarry Smith 15323d4c4710SBarry Smith Output Parameter: 15333d4c4710SBarry Smith . nfails - number of failed solves 15343d4c4710SBarry Smith 1535f6dfbefdSBarry Smith Options Database Key: 15369d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated 15379d85da0cSMatthew G. Knepley 1538f6dfbefdSBarry Smith Level: intermediate 1539f6dfbefdSBarry Smith 1540f6dfbefdSBarry Smith Note: 1541f6dfbefdSBarry Smith This counter is reset to zero for each successive call to `SNESSolve()`. 15423d4c4710SBarry Smith 15431cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()` 15443d4c4710SBarry Smith @*/ 1545d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveFailures(SNES snes, PetscInt *nfails) 1546d71ae5a4SJacob Faibussowitsch { 15473d4c4710SBarry Smith PetscFunctionBegin; 15480700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 15494f572ea9SToby Isaac PetscAssertPointer(nfails, 2); 15503d4c4710SBarry Smith *nfails = snes->numLinearSolveFailures; 15513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15523d4c4710SBarry Smith } 15533d4c4710SBarry Smith 15543d4c4710SBarry Smith /*@ 15553d4c4710SBarry Smith SNESSetMaxLinearSolveFailures - the number of failed linear solve attempts 1556f6dfbefdSBarry Smith allowed before `SNES` returns with a diverged reason of `SNES_DIVERGED_LINEAR_SOLVE` 15573d4c4710SBarry Smith 1558c3339decSBarry Smith Logically Collective 15593d4c4710SBarry Smith 15603d4c4710SBarry Smith Input Parameters: 1561f6dfbefdSBarry Smith + snes - `SNES` context 15623d4c4710SBarry Smith - maxFails - maximum allowed linear solve failures 15633d4c4710SBarry Smith 1564f6dfbefdSBarry Smith Options Database Key: 15659d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated 15669d85da0cSMatthew G. Knepley 1567dc4c0fb0SBarry Smith Level: intermediate 1568dc4c0fb0SBarry Smith 1569f6dfbefdSBarry Smith Note: 1570f6dfbefdSBarry Smith By default this is 0; that is `SNES` returns on the first failed linear solve 15713d4c4710SBarry Smith 1572420bcc1bSBarry Smith Developer Note: 1573420bcc1bSBarry Smith The options database key is wrong for this function name 1574420bcc1bSBarry Smith 15751cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()` 15763d4c4710SBarry Smith @*/ 1577d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxLinearSolveFailures(SNES snes, PetscInt maxFails) 1578d71ae5a4SJacob Faibussowitsch { 15793d4c4710SBarry Smith PetscFunctionBegin; 15800700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1581c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, maxFails, 2); 15823d4c4710SBarry Smith snes->maxLinearSolveFailures = maxFails; 15833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15843d4c4710SBarry Smith } 15853d4c4710SBarry Smith 15863d4c4710SBarry Smith /*@ 15873d4c4710SBarry Smith SNESGetMaxLinearSolveFailures - gets the maximum number of linear solve failures that 1588f6dfbefdSBarry Smith are allowed before `SNES` returns as unsuccessful 15893d4c4710SBarry Smith 15903d4c4710SBarry Smith Not Collective 15913d4c4710SBarry Smith 15923d4c4710SBarry Smith Input Parameter: 1593f6dfbefdSBarry Smith . snes - `SNES` context 15943d4c4710SBarry Smith 15953d4c4710SBarry Smith Output Parameter: 15963d4c4710SBarry Smith . maxFails - maximum of unsuccessful solves allowed 15973d4c4710SBarry Smith 15983d4c4710SBarry Smith Level: intermediate 15993d4c4710SBarry Smith 1600f6dfbefdSBarry Smith Note: 1601f6dfbefdSBarry Smith By default this is 1; that is `SNES` returns on the first failed linear solve 16023d4c4710SBarry Smith 16031cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, 16043d4c4710SBarry Smith @*/ 1605d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxLinearSolveFailures(SNES snes, PetscInt *maxFails) 1606d71ae5a4SJacob Faibussowitsch { 16073d4c4710SBarry Smith PetscFunctionBegin; 16080700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 16094f572ea9SToby Isaac PetscAssertPointer(maxFails, 2); 16103d4c4710SBarry Smith *maxFails = snes->maxLinearSolveFailures; 16113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16123d4c4710SBarry Smith } 16133d4c4710SBarry Smith 1614c96a6f78SLois Curfman McInnes /*@ 1615b850b91aSLisandro Dalcin SNESGetLinearSolveIterations - Gets the total number of linear iterations 1616420bcc1bSBarry Smith used by the nonlinear solver in the most recent `SNESSolve()` 1617c96a6f78SLois Curfman McInnes 1618c7afd0dbSLois Curfman McInnes Not Collective 1619c7afd0dbSLois Curfman McInnes 1620c96a6f78SLois Curfman McInnes Input Parameter: 1621f6dfbefdSBarry Smith . snes - `SNES` context 1622c96a6f78SLois Curfman McInnes 1623c96a6f78SLois Curfman McInnes Output Parameter: 1624c96a6f78SLois Curfman McInnes . lits - number of linear iterations 1625c96a6f78SLois Curfman McInnes 1626dc4c0fb0SBarry Smith Level: intermediate 1627dc4c0fb0SBarry Smith 1628c96a6f78SLois Curfman McInnes Notes: 1629f6dfbefdSBarry Smith This counter is reset to zero for each successive call to `SNESSolve()` unless `SNESSetCountersReset()` is used. 1630c96a6f78SLois Curfman McInnes 1631f6dfbefdSBarry 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 1632f6dfbefdSBarry Smith then call `KSPGetIterationNumber()` after the failed solve. 1633010be392SBarry Smith 16341cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetIterationNumber()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESSetCountersReset()` 1635c96a6f78SLois Curfman McInnes @*/ 1636d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveIterations(SNES snes, PetscInt *lits) 1637d71ae5a4SJacob Faibussowitsch { 16383a40ed3dSBarry Smith PetscFunctionBegin; 16390700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 16404f572ea9SToby Isaac PetscAssertPointer(lits, 2); 1641c96a6f78SLois Curfman McInnes *lits = snes->linear_its; 16423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1643c96a6f78SLois Curfman McInnes } 1644c96a6f78SLois Curfman McInnes 1645971e163fSPeter Brune /*@ 1646971e163fSPeter Brune SNESSetCountersReset - Sets whether or not the counters for linear iterations and function evaluations 1647f6dfbefdSBarry Smith are reset every time `SNESSolve()` is called. 1648971e163fSPeter Brune 1649c3339decSBarry Smith Logically Collective 1650971e163fSPeter Brune 1651d8d19677SJose E. Roman Input Parameters: 1652f6dfbefdSBarry Smith + snes - `SNES` context 1653f6dfbefdSBarry Smith - reset - whether to reset the counters or not, defaults to `PETSC_TRUE` 1654971e163fSPeter Brune 1655971e163fSPeter Brune Level: developer 1656971e163fSPeter Brune 16571cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()` 1658971e163fSPeter Brune @*/ 1659d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCountersReset(SNES snes, PetscBool reset) 1660d71ae5a4SJacob Faibussowitsch { 1661971e163fSPeter Brune PetscFunctionBegin; 1662971e163fSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1663971e163fSPeter Brune PetscValidLogicalCollectiveBool(snes, reset, 2); 1664971e163fSPeter Brune snes->counters_reset = reset; 16653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1666971e163fSPeter Brune } 1667971e163fSPeter Brune 16682999313aSBarry Smith /*@ 1669f6dfbefdSBarry Smith SNESSetKSP - Sets a `KSP` context for the `SNES` object to use 16702999313aSBarry Smith 1671420bcc1bSBarry Smith Not Collective, but the `SNES` and `KSP` objects must live on the same `MPI_Comm` 16722999313aSBarry Smith 16732999313aSBarry Smith Input Parameters: 1674f6dfbefdSBarry Smith + snes - the `SNES` context 1675f6dfbefdSBarry Smith - ksp - the `KSP` context 16762999313aSBarry Smith 1677dc4c0fb0SBarry Smith Level: developer 1678dc4c0fb0SBarry Smith 16792999313aSBarry Smith Notes: 1680f6dfbefdSBarry Smith The `SNES` object already has its `KSP` object, you can obtain with `SNESGetKSP()` 16812999313aSBarry Smith so this routine is rarely needed. 16822999313aSBarry Smith 1683f6dfbefdSBarry Smith The `KSP` object that is already in the `SNES` object has its reference count 1684420bcc1bSBarry Smith decreased by one when this is called. 16852999313aSBarry Smith 168642747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `KSP`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()` 16872999313aSBarry Smith @*/ 1688d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetKSP(SNES snes, KSP ksp) 1689d71ae5a4SJacob Faibussowitsch { 16902999313aSBarry Smith PetscFunctionBegin; 16910700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 16920700a824SBarry Smith PetscValidHeaderSpecific(ksp, KSP_CLASSID, 2); 16932999313aSBarry Smith PetscCheckSameComm(snes, 1, ksp, 2); 16949566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)ksp)); 16959566063dSJacob Faibussowitsch if (snes->ksp) PetscCall(PetscObjectDereference((PetscObject)snes->ksp)); 16962999313aSBarry Smith snes->ksp = ksp; 16973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16982999313aSBarry Smith } 16992999313aSBarry Smith 170052baeb72SSatish Balay /*@ 1701dc4c0fb0SBarry Smith SNESCreate - Creates a nonlinear solver context used to manage a set of nonlinear solves 17029b94acceSBarry Smith 1703d083f849SBarry Smith Collective 1704c7afd0dbSLois Curfman McInnes 1705f6dfbefdSBarry Smith Input Parameter: 1706906ed7ccSBarry Smith . comm - MPI communicator 17079b94acceSBarry Smith 17089b94acceSBarry Smith Output Parameter: 170920f4b53cSBarry Smith . outsnes - the new `SNES` context 17109b94acceSBarry Smith 1711c7afd0dbSLois Curfman McInnes Options Database Keys: 1712dc4c0fb0SBarry Smith + -snes_mf - Activates default matrix-free Jacobian-vector products, and no preconditioning matrix 1713dc4c0fb0SBarry Smith . -snes_mf_operator - Activates default matrix-free Jacobian-vector products, and a user-provided preconditioning matrix 1714dc4c0fb0SBarry Smith as set by `SNESSetJacobian()` 1715dc4c0fb0SBarry Smith . -snes_fd_coloring - uses a relative fast computation of the Jacobian using finite differences and a graph coloring 1716c7afd0dbSLois Curfman McInnes - -snes_fd - Uses (slow!) finite differences to compute Jacobian 1717c1f60f51SBarry Smith 171836851e7fSLois Curfman McInnes Level: beginner 171936851e7fSLois Curfman McInnes 172095452b02SPatrick Sanan Developer Notes: 1721f6dfbefdSBarry Smith `SNES` always creates a `KSP` object even though many `SNES` methods do not use it. This is 1722efd4aadfSBarry Smith unfortunate and should be fixed at some point. The flag snes->usesksp indicates if the 1723f6dfbefdSBarry Smith particular method does use `KSP` and regulates if the information about the `KSP` is printed 1724f6dfbefdSBarry Smith in `SNESView()`. 1725efd4aadfSBarry Smith 1726f6dfbefdSBarry Smith `TSSetFromOptions()` does call `SNESSetFromOptions()` which can lead to users being confused 1727f6dfbefdSBarry Smith by help messages about meaningless `SNES` options. 1728f6dfbefdSBarry Smith 1729dc4c0fb0SBarry Smith `SNES` always creates the snes->kspconvctx even though it is used by only one type. This should be fixed. 1730efd4aadfSBarry Smith 1731e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()` 17329b94acceSBarry Smith @*/ 1733d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESCreate(MPI_Comm comm, SNES *outsnes) 1734d71ae5a4SJacob Faibussowitsch { 17359b94acceSBarry Smith SNES snes; 1736fa9f3622SBarry Smith SNESKSPEW *kctx; 173737fcc0dbSBarry Smith 17383a40ed3dSBarry Smith PetscFunctionBegin; 17394f572ea9SToby Isaac PetscAssertPointer(outsnes, 2); 17400298fd71SBarry Smith *outsnes = NULL; 17419566063dSJacob Faibussowitsch PetscCall(SNESInitializePackage()); 17428ba1e511SMatthew Knepley 17439566063dSJacob Faibussowitsch PetscCall(PetscHeaderCreate(snes, SNES_CLASSID, "SNES", "Nonlinear solver", "SNES", comm, SNESDestroy, SNESView)); 17447adad957SLisandro Dalcin 17458d359177SBarry Smith snes->ops->converged = SNESConvergedDefault; 17462c155ee1SBarry Smith snes->usesksp = PETSC_TRUE; 174788976e71SPeter Brune snes->tolerancesset = PETSC_FALSE; 17489b94acceSBarry Smith snes->max_its = 50; 17499750a799SBarry Smith snes->max_funcs = 10000; 17509b94acceSBarry Smith snes->norm = 0.0; 1751c1e67a49SFande Kong snes->xnorm = 0.0; 1752c1e67a49SFande Kong snes->ynorm = 0.0; 1753365a6726SPeter Brune snes->normschedule = SNES_NORM_ALWAYS; 17546c67d002SPeter Brune snes->functype = SNES_FUNCTION_DEFAULT; 17558ca48ce9SPierre Jolivet snes->rtol = PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8; 1756b4874afaSBarry Smith snes->ttol = 0.0; 17578ca48ce9SPierre Jolivet snes->abstol = PetscDefined(USE_REAL_SINGLE) ? 1.e-25 : 1.e-50; 17588ca48ce9SPierre Jolivet snes->stol = PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8; 17598ca48ce9SPierre Jolivet snes->deltatol = PetscDefined(USE_REAL_SINGLE) ? 1.e-6 : 1.e-12; 1760e37c518bSBarry Smith snes->divtol = 1.e4; 1761e37c518bSBarry Smith snes->rnorm0 = 0; 17629b94acceSBarry Smith snes->nfuncs = 0; 176350ffb88aSMatthew Knepley snes->numFailures = 0; 176450ffb88aSMatthew Knepley snes->maxFailures = 1; 17657a00f4a9SLois Curfman McInnes snes->linear_its = 0; 1766e35cf81dSBarry Smith snes->lagjacobian = 1; 176737ec4e1aSPeter Brune snes->jac_iter = 0; 176837ec4e1aSPeter Brune snes->lagjac_persist = PETSC_FALSE; 1769a8054027SBarry Smith snes->lagpreconditioner = 1; 177037ec4e1aSPeter Brune snes->pre_iter = 0; 177137ec4e1aSPeter Brune snes->lagpre_persist = PETSC_FALSE; 1772639f9d9dSBarry Smith snes->numbermonitors = 0; 1773c4421ceaSFande Kong snes->numberreasonviews = 0; 17749e5d0892SLisandro Dalcin snes->data = NULL; 17754dc4c822SBarry Smith snes->setupcalled = PETSC_FALSE; 1776186905e3SBarry Smith snes->ksp_ewconv = PETSC_FALSE; 17776f24a144SLois Curfman McInnes snes->nwork = 0; 17789e5d0892SLisandro Dalcin snes->work = NULL; 177958c9b817SLisandro Dalcin snes->nvwork = 0; 17809e5d0892SLisandro Dalcin snes->vwork = NULL; 1781758f92a0SBarry Smith snes->conv_hist_len = 0; 1782758f92a0SBarry Smith snes->conv_hist_max = 0; 17830298fd71SBarry Smith snes->conv_hist = NULL; 17840298fd71SBarry Smith snes->conv_hist_its = NULL; 1785758f92a0SBarry Smith snes->conv_hist_reset = PETSC_TRUE; 1786971e163fSPeter Brune snes->counters_reset = PETSC_TRUE; 1787e4ed7901SPeter Brune snes->vec_func_init_set = PETSC_FALSE; 1788184914b5SBarry Smith snes->reason = SNES_CONVERGED_ITERATING; 1789efd4aadfSBarry Smith snes->npcside = PC_RIGHT; 1790b3cd9a81SMatthew G. Knepley snes->setfromoptionscalled = 0; 1791c40d0f55SPeter Brune 1792d8f46077SPeter Brune snes->mf = PETSC_FALSE; 1793d8f46077SPeter Brune snes->mf_operator = PETSC_FALSE; 1794d8f46077SPeter Brune snes->mf_version = 1; 1795d8f46077SPeter Brune 17963d4c4710SBarry Smith snes->numLinearSolveFailures = 0; 17973d4c4710SBarry Smith snes->maxLinearSolveFailures = 1; 17983d4c4710SBarry Smith 1799349187a7SBarry Smith snes->vizerotolerance = 1.e-8; 180076bd3646SJed Brown snes->checkjacdomainerror = PetscDefined(USE_DEBUG) ? PETSC_TRUE : PETSC_FALSE; 1801349187a7SBarry Smith 18024fc747eaSLawrence Mitchell /* Set this to true if the implementation of SNESSolve_XXX does compute the residual at the final solution. */ 18034fc747eaSLawrence Mitchell snes->alwayscomputesfinalresidual = PETSC_FALSE; 18044fc747eaSLawrence Mitchell 18059b94acceSBarry Smith /* Create context to compute Eisenstat-Walker relative tolerance for KSP */ 18064dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&kctx)); 1807f5af7f23SKarl Rupp 18089b94acceSBarry Smith snes->kspconvctx = (void *)kctx; 18099b94acceSBarry Smith kctx->version = 2; 18100f0abf79SStefano Zampini kctx->rtol_0 = 0.3; /* Eisenstat and Walker suggest rtol_0=.5, but 18119b94acceSBarry Smith this was too large for some test cases */ 181275567043SBarry Smith kctx->rtol_last = 0.0; 18130f0abf79SStefano Zampini kctx->rtol_max = 0.9; 18149b94acceSBarry Smith kctx->gamma = 1.0; 18150f0abf79SStefano Zampini kctx->alpha = 0.5 * (1.0 + PetscSqrtReal(5.0)); 181671f87433Sdalcinl kctx->alpha2 = kctx->alpha; 18170f0abf79SStefano Zampini kctx->threshold = 0.1; 181875567043SBarry Smith kctx->lresid_last = 0.0; 181975567043SBarry Smith kctx->norm_last = 0.0; 18209b94acceSBarry Smith 18210f0abf79SStefano Zampini kctx->rk_last = 0.0; 18220f0abf79SStefano Zampini kctx->rk_last_2 = 0.0; 18230f0abf79SStefano Zampini kctx->rtol_last_2 = 0.0; 18240f0abf79SStefano Zampini kctx->v4_p1 = 0.1; 18250f0abf79SStefano Zampini kctx->v4_p2 = 0.4; 18260f0abf79SStefano Zampini kctx->v4_p3 = 0.7; 18270f0abf79SStefano Zampini kctx->v4_m1 = 0.8; 18280f0abf79SStefano Zampini kctx->v4_m2 = 0.5; 18290f0abf79SStefano Zampini kctx->v4_m3 = 0.1; 18300f0abf79SStefano Zampini kctx->v4_m4 = 0.5; 18310f0abf79SStefano Zampini 18329b94acceSBarry Smith *outsnes = snes; 18333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18349b94acceSBarry Smith } 18359b94acceSBarry Smith 18369b94acceSBarry Smith /*@C 18379b94acceSBarry Smith SNESSetFunction - Sets the function evaluation routine and function 1838f6dfbefdSBarry Smith vector for use by the `SNES` routines in solving systems of nonlinear 18399b94acceSBarry Smith equations. 18409b94acceSBarry Smith 1841c3339decSBarry Smith Logically Collective 1842fee21e36SBarry Smith 1843c7afd0dbSLois Curfman McInnes Input Parameters: 1844f6dfbefdSBarry Smith + snes - the `SNES` context 1845dc4c0fb0SBarry Smith . r - vector to store function values, may be `NULL` 18468434afd1SBarry Smith . f - function evaluation routine; for calling sequence see `SNESFunctionFn` 1847c7afd0dbSLois Curfman McInnes - ctx - [optional] user-defined context for private data for the 1848dc4c0fb0SBarry Smith function evaluation routine (may be `NULL`) 18499b94acceSBarry Smith 185036851e7fSLois Curfman McInnes Level: beginner 185136851e7fSLois Curfman McInnes 18528434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetPicard()`, `SNESFunctionFn` 18539b94acceSBarry Smith @*/ 18548434afd1SBarry Smith PetscErrorCode SNESSetFunction(SNES snes, Vec r, SNESFunctionFn *f, void *ctx) 1855d71ae5a4SJacob Faibussowitsch { 18566cab3a1bSJed Brown DM dm; 18576cab3a1bSJed Brown 18583a40ed3dSBarry Smith PetscFunctionBegin; 18590700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1860d2a683ecSLisandro Dalcin if (r) { 1861d2a683ecSLisandro Dalcin PetscValidHeaderSpecific(r, VEC_CLASSID, 2); 1862d2a683ecSLisandro Dalcin PetscCheckSameComm(snes, 1, r, 2); 18639566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)r)); 18649566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_func)); 186585385478SLisandro Dalcin snes->vec_func = r; 1866d2a683ecSLisandro Dalcin } 18679566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 18689566063dSJacob Faibussowitsch PetscCall(DMSNESSetFunction(dm, f, ctx)); 186948a46eb9SPierre Jolivet if (f == SNESPicardComputeFunction) PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx)); 18703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18719b94acceSBarry Smith } 18729b94acceSBarry Smith 1873e4ed7901SPeter Brune /*@C 18740b4db180SJacob Faibussowitsch SNESSetInitialFunction - Set an already computed function evaluation at the initial guess to be reused by `SNESSolve()`. 1875e4ed7901SPeter Brune 1876c3339decSBarry Smith Logically Collective 1877e4ed7901SPeter Brune 1878e4ed7901SPeter Brune Input Parameters: 1879f6dfbefdSBarry Smith + snes - the `SNES` context 1880e4ed7901SPeter Brune - f - vector to store function value 1881e4ed7901SPeter Brune 1882dc4c0fb0SBarry Smith Level: developer 1883dc4c0fb0SBarry Smith 1884e4ed7901SPeter Brune Notes: 1885e4ed7901SPeter Brune This should not be modified during the solution procedure. 1886e4ed7901SPeter Brune 1887f6dfbefdSBarry Smith This is used extensively in the `SNESFAS` hierarchy and in nonlinear preconditioning. 1888e4ed7901SPeter Brune 18891cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetInitialFunctionNorm()` 1890e4ed7901SPeter Brune @*/ 1891d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetInitialFunction(SNES snes, Vec f) 1892d71ae5a4SJacob Faibussowitsch { 1893e4ed7901SPeter Brune Vec vec_func; 1894e4ed7901SPeter Brune 1895e4ed7901SPeter Brune PetscFunctionBegin; 1896e4ed7901SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1897e4ed7901SPeter Brune PetscValidHeaderSpecific(f, VEC_CLASSID, 2); 1898e4ed7901SPeter Brune PetscCheckSameComm(snes, 1, f, 2); 1899efd4aadfSBarry Smith if (snes->npcside == PC_LEFT && snes->functype == SNES_FUNCTION_PRECONDITIONED) { 1900902f982fSPeter Brune snes->vec_func_init_set = PETSC_FALSE; 19013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1902902f982fSPeter Brune } 19039566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &vec_func, NULL, NULL)); 19049566063dSJacob Faibussowitsch PetscCall(VecCopy(f, vec_func)); 1905f5af7f23SKarl Rupp 1906217b9c2eSPeter Brune snes->vec_func_init_set = PETSC_TRUE; 19073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1908e4ed7901SPeter Brune } 1909e4ed7901SPeter Brune 1910534ebe21SPeter Brune /*@ 1911f6dfbefdSBarry Smith SNESSetNormSchedule - Sets the `SNESNormSchedule` used in convergence and monitoring 1912f6dfbefdSBarry Smith of the `SNES` method, when norms are computed in the solving process 1913534ebe21SPeter Brune 1914c3339decSBarry Smith Logically Collective 1915534ebe21SPeter Brune 1916534ebe21SPeter Brune Input Parameters: 1917f6dfbefdSBarry Smith + snes - the `SNES` context 1918365a6726SPeter Brune - normschedule - the frequency of norm computation 1919534ebe21SPeter Brune 1920517f1916SMatthew G. Knepley Options Database Key: 192167b8a455SSatish Balay . -snes_norm_schedule <none, always, initialonly, finalonly, initialfinalonly> - set the schedule 1922517f1916SMatthew G. Knepley 1923dc4c0fb0SBarry Smith Level: advanced 1924dc4c0fb0SBarry Smith 1925534ebe21SPeter Brune Notes: 1926f6dfbefdSBarry Smith Only certain `SNES` methods support certain `SNESNormSchedules`. Most require evaluation 1927534ebe21SPeter Brune of the nonlinear function and the taking of its norm at every iteration to 1928534ebe21SPeter Brune even ensure convergence at all. However, methods such as custom Gauss-Seidel methods 1929f6dfbefdSBarry Smith `SNESNGS` and the like do not require the norm of the function to be computed, and therefore 1930534ebe21SPeter Brune may either be monitored for convergence or not. As these are often used as nonlinear 1931534ebe21SPeter Brune preconditioners, monitoring the norm of their error is not a useful enterprise within 1932534ebe21SPeter Brune their solution. 1933534ebe21SPeter Brune 1934e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNESNormSchedule`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()` 1935534ebe21SPeter Brune @*/ 1936d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNormSchedule(SNES snes, SNESNormSchedule normschedule) 1937d71ae5a4SJacob Faibussowitsch { 1938534ebe21SPeter Brune PetscFunctionBegin; 1939534ebe21SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1940365a6726SPeter Brune snes->normschedule = normschedule; 19413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1942534ebe21SPeter Brune } 1943534ebe21SPeter Brune 1944534ebe21SPeter Brune /*@ 1945f6dfbefdSBarry Smith SNESGetNormSchedule - Gets the `SNESNormSchedule` used in convergence and monitoring 1946f6dfbefdSBarry Smith of the `SNES` method. 1947534ebe21SPeter Brune 1948c3339decSBarry Smith Logically Collective 1949534ebe21SPeter Brune 1950534ebe21SPeter Brune Input Parameters: 1951f6dfbefdSBarry Smith + snes - the `SNES` context 1952365a6726SPeter Brune - normschedule - the type of the norm used 1953534ebe21SPeter Brune 1954534ebe21SPeter Brune Level: advanced 1955534ebe21SPeter Brune 19561cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 1957534ebe21SPeter Brune @*/ 1958d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNormSchedule(SNES snes, SNESNormSchedule *normschedule) 1959d71ae5a4SJacob Faibussowitsch { 1960534ebe21SPeter Brune PetscFunctionBegin; 1961534ebe21SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1962365a6726SPeter Brune *normschedule = snes->normschedule; 19633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1964534ebe21SPeter Brune } 1965534ebe21SPeter Brune 1966c5ce4427SMatthew G. Knepley /*@ 1967c5ce4427SMatthew G. Knepley SNESSetFunctionNorm - Sets the last computed residual norm. 1968c5ce4427SMatthew G. Knepley 1969c3339decSBarry Smith Logically Collective 1970c5ce4427SMatthew G. Knepley 1971c5ce4427SMatthew G. Knepley Input Parameters: 1972f6dfbefdSBarry Smith + snes - the `SNES` context 1973f6dfbefdSBarry Smith - norm - the value of the norm 1974c5ce4427SMatthew G. Knepley 1975c5ce4427SMatthew G. Knepley Level: developer 1976c5ce4427SMatthew G. Knepley 19771cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 1978c5ce4427SMatthew G. Knepley @*/ 1979d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionNorm(SNES snes, PetscReal norm) 1980d71ae5a4SJacob Faibussowitsch { 1981c5ce4427SMatthew G. Knepley PetscFunctionBegin; 1982c5ce4427SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1983c5ce4427SMatthew G. Knepley snes->norm = norm; 19843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1985c5ce4427SMatthew G. Knepley } 1986c5ce4427SMatthew G. Knepley 1987c5ce4427SMatthew G. Knepley /*@ 1988c5ce4427SMatthew G. Knepley SNESGetFunctionNorm - Gets the last computed norm of the residual 1989c5ce4427SMatthew G. Knepley 1990c5ce4427SMatthew G. Knepley Not Collective 1991c5ce4427SMatthew G. Knepley 1992c5ce4427SMatthew G. Knepley Input Parameter: 1993f6dfbefdSBarry Smith . snes - the `SNES` context 1994c5ce4427SMatthew G. Knepley 1995c5ce4427SMatthew G. Knepley Output Parameter: 1996c5ce4427SMatthew G. Knepley . norm - the last computed residual norm 1997c5ce4427SMatthew G. Knepley 1998c5ce4427SMatthew G. Knepley Level: developer 1999c5ce4427SMatthew G. Knepley 20001cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 2001c5ce4427SMatthew G. Knepley @*/ 2002d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionNorm(SNES snes, PetscReal *norm) 2003d71ae5a4SJacob Faibussowitsch { 2004c5ce4427SMatthew G. Knepley PetscFunctionBegin; 2005c5ce4427SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 20064f572ea9SToby Isaac PetscAssertPointer(norm, 2); 2007c5ce4427SMatthew G. Knepley *norm = snes->norm; 20083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2009c5ce4427SMatthew G. Knepley } 2010c5ce4427SMatthew G. Knepley 2011c1e67a49SFande Kong /*@ 2012f6dfbefdSBarry Smith SNESGetUpdateNorm - Gets the last computed norm of the solution update 2013c1e67a49SFande Kong 2014c1e67a49SFande Kong Not Collective 2015c1e67a49SFande Kong 2016c1e67a49SFande Kong Input Parameter: 2017f6dfbefdSBarry Smith . snes - the `SNES` context 2018c1e67a49SFande Kong 2019c1e67a49SFande Kong Output Parameter: 2020c1e67a49SFande Kong . ynorm - the last computed update norm 2021c1e67a49SFande Kong 2022c1e67a49SFande Kong Level: developer 2023c1e67a49SFande Kong 2024f6dfbefdSBarry Smith Note: 2025f6dfbefdSBarry Smith The new solution is the current solution plus the update, so this norm is an indication of the size of the update 2026f6dfbefdSBarry Smith 20271cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()` 2028c1e67a49SFande Kong @*/ 2029d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUpdateNorm(SNES snes, PetscReal *ynorm) 2030d71ae5a4SJacob Faibussowitsch { 2031c1e67a49SFande Kong PetscFunctionBegin; 2032c1e67a49SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 20334f572ea9SToby Isaac PetscAssertPointer(ynorm, 2); 2034c1e67a49SFande Kong *ynorm = snes->ynorm; 20353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2036c1e67a49SFande Kong } 2037c1e67a49SFande Kong 2038c1e67a49SFande Kong /*@ 20394591eaf2SFande Kong SNESGetSolutionNorm - Gets the last computed norm of the solution 2040c1e67a49SFande Kong 2041c1e67a49SFande Kong Not Collective 2042c1e67a49SFande Kong 2043c1e67a49SFande Kong Input Parameter: 2044f6dfbefdSBarry Smith . snes - the `SNES` context 2045c1e67a49SFande Kong 2046c1e67a49SFande Kong Output Parameter: 2047c1e67a49SFande Kong . xnorm - the last computed solution norm 2048c1e67a49SFande Kong 2049c1e67a49SFande Kong Level: developer 2050c1e67a49SFande Kong 20511cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`, `SNESGetUpdateNorm()` 2052c1e67a49SFande Kong @*/ 2053d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionNorm(SNES snes, PetscReal *xnorm) 2054d71ae5a4SJacob Faibussowitsch { 2055c1e67a49SFande Kong PetscFunctionBegin; 2056c1e67a49SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 20574f572ea9SToby Isaac PetscAssertPointer(xnorm, 2); 2058c1e67a49SFande Kong *xnorm = snes->xnorm; 20593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2060c1e67a49SFande Kong } 2061c1e67a49SFande Kong 206247073ea2SPeter Brune /*@C 2063f6dfbefdSBarry Smith SNESSetFunctionType - Sets the `SNESFunctionType` 2064f6dfbefdSBarry Smith of the `SNES` method. 206547073ea2SPeter Brune 2066c3339decSBarry Smith Logically Collective 206747073ea2SPeter Brune 206847073ea2SPeter Brune Input Parameters: 2069f6dfbefdSBarry Smith + snes - the `SNES` context 2070f6dfbefdSBarry Smith - type - the function type 207147073ea2SPeter Brune 207247073ea2SPeter Brune Level: developer 207347073ea2SPeter Brune 2074420bcc1bSBarry Smith Values of the function type\: 2075f6dfbefdSBarry Smith + `SNES_FUNCTION_DEFAULT` - the default for the given `SNESType` 2076f6dfbefdSBarry Smith . `SNES_FUNCTION_UNPRECONDITIONED` - an unpreconditioned function evaluation (this is the function provided with `SNESSetFunction()` 2077f6dfbefdSBarry Smith - `SNES_FUNCTION_PRECONDITIONED` - a transformation of the function provided with `SNESSetFunction()` 2078f6dfbefdSBarry Smith 2079420bcc1bSBarry Smith Note: 2080f6dfbefdSBarry Smith Different `SNESType`s use this value in different ways 2081f6dfbefdSBarry Smith 20821cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFunctionType`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 208347073ea2SPeter Brune @*/ 2084d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionType(SNES snes, SNESFunctionType type) 2085d71ae5a4SJacob Faibussowitsch { 208647073ea2SPeter Brune PetscFunctionBegin; 208747073ea2SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 208847073ea2SPeter Brune snes->functype = type; 20893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 209047073ea2SPeter Brune } 209147073ea2SPeter Brune 209247073ea2SPeter Brune /*@C 2093f6dfbefdSBarry Smith SNESGetFunctionType - Gets the `SNESFunctionType` used in convergence and monitoring set with `SNESSetFunctionType()` 209447073ea2SPeter Brune of the SNES method. 209547073ea2SPeter Brune 2096c3339decSBarry Smith Logically Collective 209747073ea2SPeter Brune 209847073ea2SPeter Brune Input Parameters: 2099f6dfbefdSBarry Smith + snes - the `SNES` context 2100f6dfbefdSBarry Smith - type - the type of the function evaluation, see `SNESSetFunctionType()` 210147073ea2SPeter Brune 210247073ea2SPeter Brune Level: advanced 210347073ea2SPeter Brune 21041cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetFunctionType()`, `SNESFunctionType`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 210547073ea2SPeter Brune @*/ 2106d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionType(SNES snes, SNESFunctionType *type) 2107d71ae5a4SJacob Faibussowitsch { 210847073ea2SPeter Brune PetscFunctionBegin; 210947073ea2SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 211047073ea2SPeter Brune *type = snes->functype; 21113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2112534ebe21SPeter Brune } 2113534ebe21SPeter Brune 2114c79ef259SPeter Brune /*@C 2115be95d8f1SBarry Smith SNESSetNGS - Sets the user nonlinear Gauss-Seidel routine for 2116c79ef259SPeter Brune use with composed nonlinear solvers. 2117c79ef259SPeter Brune 2118c79ef259SPeter Brune Input Parameters: 21199bcc50f1SBarry Smith + snes - the `SNES` context, usually of the `SNESType` `SNESNGS` 21208434afd1SBarry Smith . f - function evaluation routine to apply Gauss-Seidel, see `SNESNGSFn` for calling sequence 2121c79ef259SPeter Brune - ctx - [optional] user-defined context for private data for the 2122dc4c0fb0SBarry Smith smoother evaluation routine (may be `NULL`) 2123c79ef259SPeter Brune 2124dc4c0fb0SBarry Smith Level: intermediate 2125dc4c0fb0SBarry Smith 2126f6dfbefdSBarry Smith Note: 2127f6dfbefdSBarry Smith The `SNESNGS` routines are used by the composed nonlinear solver to generate 2128f6dfbefdSBarry Smith a problem appropriate update to the solution, particularly `SNESFAS`. 2129c79ef259SPeter Brune 21308434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGS`, `SNESGetNGS()`, `SNESNCG`, `SNESGetFunction()`, `SNESComputeNGS()`, `SNESNGSFn` 2131c79ef259SPeter Brune @*/ 21328434afd1SBarry Smith PetscErrorCode SNESSetNGS(SNES snes, SNESNGSFn *f, void *ctx) 2133d71ae5a4SJacob Faibussowitsch { 21346cab3a1bSJed Brown DM dm; 21356cab3a1bSJed Brown 2136646217ecSPeter Brune PetscFunctionBegin; 21376cab3a1bSJed Brown PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 21389566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 21399566063dSJacob Faibussowitsch PetscCall(DMSNESSetNGS(dm, f, ctx)); 21403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2141646217ecSPeter Brune } 2142646217ecSPeter Brune 2143bbc1464cSBarry Smith /* 2144bbc1464cSBarry Smith This is used for -snes_mf_operator; it uses a duplicate of snes->jacobian_pre because snes->jacobian_pre cannot be 2145bbc1464cSBarry Smith changed during the KSPSolve() 2146bbc1464cSBarry Smith */ 2147d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeMFFunction(SNES snes, Vec x, Vec f, void *ctx) 2148d71ae5a4SJacob Faibussowitsch { 2149bbc1464cSBarry Smith DM dm; 2150bbc1464cSBarry Smith DMSNES sdm; 2151bbc1464cSBarry Smith 2152bbc1464cSBarry Smith PetscFunctionBegin; 21539566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 21549566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 2155bbc1464cSBarry Smith /* A(x)*x - b(x) */ 2156bbc1464cSBarry Smith if (sdm->ops->computepfunction) { 2157792fecdfSBarry Smith PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx)); 21589566063dSJacob Faibussowitsch PetscCall(VecScale(f, -1.0)); 21590df40c35SBarry Smith /* Cannot share nonzero pattern because of the possible use of SNESComputeJacobianDefault() */ 2160ef1023bdSBarry Smith if (!snes->picard) PetscCall(MatDuplicate(snes->jacobian_pre, MAT_DO_NOT_COPY_VALUES, &snes->picard)); 2161792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx)); 21629566063dSJacob Faibussowitsch PetscCall(MatMultAdd(snes->picard, x, f, f)); 2163bbc1464cSBarry Smith } else { 2164792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx)); 21659566063dSJacob Faibussowitsch PetscCall(MatMult(snes->picard, x, f)); 2166bbc1464cSBarry Smith } 21673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2168bbc1464cSBarry Smith } 2169bbc1464cSBarry Smith 2170d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeFunction(SNES snes, Vec x, Vec f, void *ctx) 2171d71ae5a4SJacob Faibussowitsch { 2172e03ab78fSPeter Brune DM dm; 2173942e3340SBarry Smith DMSNES sdm; 21746cab3a1bSJed Brown 21758b0a5094SBarry Smith PetscFunctionBegin; 21769566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 21779566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 21788b0a5094SBarry Smith /* A(x)*x - b(x) */ 2179bbc1464cSBarry Smith if (sdm->ops->computepfunction) { 2180792fecdfSBarry Smith PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx)); 21819566063dSJacob Faibussowitsch PetscCall(VecScale(f, -1.0)); 2182792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx)); 21839566063dSJacob Faibussowitsch PetscCall(MatMultAdd(snes->jacobian_pre, x, f, f)); 2184bbc1464cSBarry Smith } else { 2185792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx)); 21869566063dSJacob Faibussowitsch PetscCall(MatMult(snes->jacobian_pre, x, f)); 2187bbc1464cSBarry Smith } 21883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 21898b0a5094SBarry Smith } 21908b0a5094SBarry Smith 2191d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeJacobian(SNES snes, Vec x1, Mat J, Mat B, void *ctx) 2192d71ae5a4SJacob Faibussowitsch { 21938b0a5094SBarry Smith PetscFunctionBegin; 2194e03ab78fSPeter Brune /* the jacobian matrix should be pre-filled in SNESPicardComputeFunction */ 2195bbc1464cSBarry Smith /* must assembly if matrix-free to get the last SNES solution */ 21969566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 21979566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 21983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 21998b0a5094SBarry Smith } 22008b0a5094SBarry Smith 22018b0a5094SBarry Smith /*@C 22021d27aa22SBarry Smith SNESSetPicard - Use `SNES` to solve the system $A(x) x = bp(x) + b $ via a Picard type iteration (Picard linearization) 22038b0a5094SBarry Smith 2204c3339decSBarry Smith Logically Collective 22058b0a5094SBarry Smith 22068b0a5094SBarry Smith Input Parameters: 2207f6dfbefdSBarry Smith + snes - the `SNES` context 2208dc4c0fb0SBarry Smith . r - vector to store function values, may be `NULL` 22098434afd1SBarry Smith . bp - function evaluation routine, may be `NULL`, for the calling sequence see `SNESFunctionFn` 22106b7fb656SBarry Smith . Amat - matrix with which A(x) x - bp(x) - b is to be computed 2211dc4c0fb0SBarry Smith . Pmat - matrix from which preconditioner is computed (usually the same as `Amat`) 22128434afd1SBarry Smith . J - function to compute matrix values, for the calling sequence see `SNESJacobianFn` 2213dc4c0fb0SBarry Smith - ctx - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`) 2214dc4c0fb0SBarry Smith 2215dc4c0fb0SBarry Smith Level: intermediate 22168b0a5094SBarry Smith 22178b0a5094SBarry Smith Notes: 22186b7fb656SBarry Smith It is often better to provide the nonlinear function F() and some approximation to its Jacobian directly and use 2219f450aa47SBarry 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. 2220f450aa47SBarry Smith 2221f6dfbefdSBarry Smith One can call `SNESSetPicard()` or `SNESSetFunction()` (and possibly `SNESSetJacobian()`) but cannot call both 22228b0a5094SBarry Smith 22231d27aa22SBarry 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}$. 22241d27aa22SBarry Smith When an exact solver is used this corresponds to the "classic" Picard $A(x^{n}) x^{n+1} = bp(x^{n}) + b$ iteration. 22258b0a5094SBarry Smith 2226dc4c0fb0SBarry Smith Run with `-snes_mf_operator` to solve the system with Newton's method using A(x^{n}) to construct the preconditioner. 22278b0a5094SBarry Smith 22280d04baf8SBarry Smith We implement the defect correction form of the Picard iteration because it converges much more generally when inexact linear solvers are used then 22291d27aa22SBarry Smith the direct Picard iteration $A(x^n) x^{n+1} = bp(x^n) + b$ 22308b0a5094SBarry Smith 22318b0a5094SBarry 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 22321d27aa22SBarry 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 22331d27aa22SBarry Smith different please contact us at petsc-dev@mcs.anl.gov and we'll have an entirely new argument \:-). 22348b0a5094SBarry Smith 22351d27aa22SBarry 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 2236f6dfbefdSBarry Smith A(x^{n}) is used to build the preconditioner 22376b7fb656SBarry Smith 223815229ffcSPierre 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. 22396b7fb656SBarry Smith 2240dc4c0fb0SBarry 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 22416b7fb656SBarry 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 2242f6dfbefdSBarry 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`. 2243aaa8cc7dSPierre Jolivet See the comment in src/snes/tutorials/ex15.c. 2244bbc1464cSBarry Smith 22459bcc50f1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESGetPicard()`, `SNESLineSearchPreCheckPicard()`, 22468434afd1SBarry Smith `SNESFunctionFn`, `SNESJacobianFn` 22478b0a5094SBarry Smith @*/ 22488434afd1SBarry Smith PetscErrorCode SNESSetPicard(SNES snes, Vec r, SNESFunctionFn *bp, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx) 2249d71ae5a4SJacob Faibussowitsch { 2250e03ab78fSPeter Brune DM dm; 2251e03ab78fSPeter Brune 22528b0a5094SBarry Smith PetscFunctionBegin; 22538b0a5094SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 22549566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 22559566063dSJacob Faibussowitsch PetscCall(DMSNESSetPicard(dm, bp, J, ctx)); 22569566063dSJacob Faibussowitsch PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx)); 22579566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes, r, SNESPicardComputeFunction, ctx)); 22589566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESPicardComputeJacobian, ctx)); 22593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22608b0a5094SBarry Smith } 22618b0a5094SBarry Smith 22627971a8bfSPeter Brune /*@C 22637971a8bfSPeter Brune SNESGetPicard - Returns the context for the Picard iteration 22647971a8bfSPeter Brune 2265f6dfbefdSBarry Smith Not Collective, but `Vec` is parallel if `SNES` is parallel. Collective if `Vec` is requested, but has not been created yet. 22667971a8bfSPeter Brune 22677971a8bfSPeter Brune Input Parameter: 2268f6dfbefdSBarry Smith . snes - the `SNES` context 22697971a8bfSPeter Brune 2270d8d19677SJose E. Roman Output Parameters: 2271dc4c0fb0SBarry Smith + r - the function (or `NULL`) 22728434afd1SBarry Smith . f - the function (or `NULL`); for calling sequence see `SNESFunctionFn` 2273dc4c0fb0SBarry Smith . Amat - the matrix used to defined the operation A(x) x - b(x) (or `NULL`) 2274dc4c0fb0SBarry Smith . Pmat - the matrix from which the preconditioner will be constructed (or `NULL`) 22758434afd1SBarry Smith . J - the function for matrix evaluation (or `NULL`); for calling sequence see `SNESJacobianFn` 2276dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`) 22777971a8bfSPeter Brune 22787971a8bfSPeter Brune Level: advanced 22797971a8bfSPeter Brune 22808434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetFunction()`, `SNESSetPicard()`, `SNESGetFunction()`, `SNESGetJacobian()`, `SNESGetDM()`, `SNESFunctionFn`, `SNESJacobianFn` 22817971a8bfSPeter Brune @*/ 22828434afd1SBarry Smith PetscErrorCode SNESGetPicard(SNES snes, Vec *r, SNESFunctionFn **f, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx) 2283d71ae5a4SJacob Faibussowitsch { 22847971a8bfSPeter Brune DM dm; 22857971a8bfSPeter Brune 22867971a8bfSPeter Brune PetscFunctionBegin; 22877971a8bfSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 22889566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, r, NULL, NULL)); 22899566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL)); 22909566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 22919566063dSJacob Faibussowitsch PetscCall(DMSNESGetPicard(dm, f, J, ctx)); 22923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22937971a8bfSPeter Brune } 22947971a8bfSPeter Brune 2295d25893d9SBarry Smith /*@C 2296dc4c0fb0SBarry Smith SNESSetComputeInitialGuess - Sets a routine used to compute an initial guess for the nonlinear problem 2297d25893d9SBarry Smith 2298c3339decSBarry Smith Logically Collective 2299d25893d9SBarry Smith 2300d25893d9SBarry Smith Input Parameters: 2301f6dfbefdSBarry Smith + snes - the `SNES` context 23028434afd1SBarry Smith . func - function evaluation routine, see `SNESInitialGuessFn` for the calling sequence 2303d25893d9SBarry Smith - ctx - [optional] user-defined context for private data for the 2304dc4c0fb0SBarry Smith function evaluation routine (may be `NULL`) 2305d25893d9SBarry Smith 2306d25893d9SBarry Smith Level: intermediate 2307d25893d9SBarry Smith 23088434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESInitialGuessFn` 2309d25893d9SBarry Smith @*/ 23108434afd1SBarry Smith PetscErrorCode SNESSetComputeInitialGuess(SNES snes, SNESInitialGuessFn *func, void *ctx) 2311d71ae5a4SJacob Faibussowitsch { 2312d25893d9SBarry Smith PetscFunctionBegin; 2313d25893d9SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2314d25893d9SBarry Smith if (func) snes->ops->computeinitialguess = func; 2315d25893d9SBarry Smith if (ctx) snes->initialguessP = ctx; 23163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2317d25893d9SBarry Smith } 2318d25893d9SBarry Smith 23191096aae1SMatthew Knepley /*@C 2320dc4c0fb0SBarry Smith SNESGetRhs - Gets the vector for solving F(x) = `rhs`. If `rhs` is not set 23211096aae1SMatthew Knepley it assumes a zero right hand side. 23221096aae1SMatthew Knepley 2323c3339decSBarry Smith Logically Collective 23241096aae1SMatthew Knepley 23251096aae1SMatthew Knepley Input Parameter: 2326f6dfbefdSBarry Smith . snes - the `SNES` context 23271096aae1SMatthew Knepley 23281096aae1SMatthew Knepley Output Parameter: 2329420bcc1bSBarry Smith . rhs - the right hand side vector or `NULL` if there is no right-hand side vector 23301096aae1SMatthew Knepley 23311096aae1SMatthew Knepley Level: intermediate 23321096aae1SMatthew Knepley 23331cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetFunction()` 23341096aae1SMatthew Knepley @*/ 2335d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetRhs(SNES snes, Vec *rhs) 2336d71ae5a4SJacob Faibussowitsch { 23371096aae1SMatthew Knepley PetscFunctionBegin; 23380700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 23394f572ea9SToby Isaac PetscAssertPointer(rhs, 2); 234085385478SLisandro Dalcin *rhs = snes->vec_rhs; 23413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23421096aae1SMatthew Knepley } 23431096aae1SMatthew Knepley 23449b94acceSBarry Smith /*@ 2345f6dfbefdSBarry Smith SNESComputeFunction - Calls the function that has been set with `SNESSetFunction()`. 23469b94acceSBarry Smith 2347c3339decSBarry Smith Collective 2348c7afd0dbSLois Curfman McInnes 23499b94acceSBarry Smith Input Parameters: 2350f6dfbefdSBarry Smith + snes - the `SNES` context 2351c7afd0dbSLois Curfman McInnes - x - input vector 23529b94acceSBarry Smith 23539b94acceSBarry Smith Output Parameter: 2354f6dfbefdSBarry Smith . y - function vector, as set by `SNESSetFunction()` 23559b94acceSBarry Smith 2356dc4c0fb0SBarry Smith Level: developer 2357dc4c0fb0SBarry Smith 235800677de2SStefano Zampini Notes: 2359f6dfbefdSBarry Smith `SNESComputeFunction()` is typically used within nonlinear solvers 2360bbc1464cSBarry Smith implementations, so users would not generally call this routine themselves. 236136851e7fSLois Curfman McInnes 236200677de2SStefano Zampini When solving for $F(x) = b$, this routine computes $y = F(x) - b$. 236300677de2SStefano Zampini 23641cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeMFFunction()` 23659b94acceSBarry Smith @*/ 2366d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeFunction(SNES snes, Vec x, Vec y) 2367d71ae5a4SJacob Faibussowitsch { 23686cab3a1bSJed Brown DM dm; 2369942e3340SBarry Smith DMSNES sdm; 23709b94acceSBarry Smith 23713a40ed3dSBarry Smith PetscFunctionBegin; 23720700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 23730700a824SBarry Smith PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 23740700a824SBarry Smith PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2375c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, x, 2); 2376c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, y, 3); 2377e0f629ddSJacob Faibussowitsch PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2378184914b5SBarry Smith 23799566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 23809566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 23810fdf79fbSJacob 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()."); 238232f3f7c2SPeter Brune if (sdm->ops->computefunction) { 238348a46eb9SPierre Jolivet if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0)); 23849566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(x)); 23858ddeebeaSSteve Benbow /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */ 23868ddeebeaSSteve Benbow snes->domainerror = PETSC_FALSE; 2387800f99ffSJeremy L Thompson { 2388800f99ffSJeremy L Thompson void *ctx; 23898434afd1SBarry Smith SNESFunctionFn *computefunction; 2390800f99ffSJeremy L Thompson PetscCall(DMSNESGetFunction(dm, &computefunction, &ctx)); 2391800f99ffSJeremy L Thompson PetscCallBack("SNES callback function", (*computefunction)(snes, x, y, ctx)); 2392800f99ffSJeremy L Thompson } 23939566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(x)); 239448a46eb9SPierre Jolivet if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0)); 23950fdf79fbSJacob Faibussowitsch } else /* if (snes->vec_rhs) */ { 23969566063dSJacob Faibussowitsch PetscCall(MatMult(snes->jacobian, x, y)); 23970fdf79fbSJacob Faibussowitsch } 23981baa6e33SBarry Smith if (snes->vec_rhs) PetscCall(VecAXPY(y, -1.0, snes->vec_rhs)); 2399ae3c334cSLois Curfman McInnes snes->nfuncs++; 2400422a814eSBarry Smith /* 2401422a814eSBarry Smith domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will 2402422a814eSBarry Smith propagate the value to all processes 2403422a814eSBarry Smith */ 24041baa6e33SBarry Smith if (snes->domainerror) PetscCall(VecSetInf(y)); 24053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24069b94acceSBarry Smith } 24079b94acceSBarry Smith 2408c79ef259SPeter Brune /*@ 2409f6dfbefdSBarry Smith SNESComputeMFFunction - Calls the function that has been set with `SNESSetMFFunction()`. 2410bbc1464cSBarry Smith 2411c3339decSBarry Smith Collective 2412bbc1464cSBarry Smith 2413bbc1464cSBarry Smith Input Parameters: 2414f6dfbefdSBarry Smith + snes - the `SNES` context 2415bbc1464cSBarry Smith - x - input vector 2416bbc1464cSBarry Smith 2417bbc1464cSBarry Smith Output Parameter: 2418f6dfbefdSBarry Smith . y - function vector, as set by `SNESSetMFFunction()` 2419bbc1464cSBarry Smith 2420dc4c0fb0SBarry Smith Level: developer 2421dc4c0fb0SBarry Smith 2422bbc1464cSBarry Smith Notes: 2423420bcc1bSBarry Smith `SNESComputeMFFunction()` is used within the matrix-vector products called by the matrix created with `MatCreateSNESMF()` 2424bbc1464cSBarry Smith so users would not generally call this routine themselves. 2425bbc1464cSBarry Smith 2426f6dfbefdSBarry Smith Since this function is intended for use with finite differencing it does not subtract the right hand side vector provided with `SNESSolve()` 2427f6dfbefdSBarry Smith while `SNESComputeFunction()` does. As such, this routine cannot be used with `MatMFFDSetBase()` with a provided F function value even if it applies the 2428f6dfbefdSBarry Smith 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. 2429bbc1464cSBarry Smith 24301cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `MatCreateSNESMF` 2431bbc1464cSBarry Smith @*/ 2432d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeMFFunction(SNES snes, Vec x, Vec y) 2433d71ae5a4SJacob Faibussowitsch { 2434bbc1464cSBarry Smith DM dm; 2435bbc1464cSBarry Smith DMSNES sdm; 2436bbc1464cSBarry Smith 2437bbc1464cSBarry Smith PetscFunctionBegin; 2438bbc1464cSBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2439bbc1464cSBarry Smith PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2440bbc1464cSBarry Smith PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2441bbc1464cSBarry Smith PetscCheckSameComm(snes, 1, x, 2); 2442bbc1464cSBarry Smith PetscCheckSameComm(snes, 1, y, 3); 2443e0f629ddSJacob Faibussowitsch PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2444bbc1464cSBarry Smith 24459566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 24469566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 24479566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0)); 24489566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(x)); 2449bbc1464cSBarry Smith /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */ 2450bbc1464cSBarry Smith snes->domainerror = PETSC_FALSE; 2451792fecdfSBarry Smith PetscCallBack("SNES callback function", (*sdm->ops->computemffunction)(snes, x, y, sdm->mffunctionctx)); 24529566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(x)); 24539566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0)); 2454bbc1464cSBarry Smith snes->nfuncs++; 2455bbc1464cSBarry Smith /* 2456bbc1464cSBarry Smith domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will 2457bbc1464cSBarry Smith propagate the value to all processes 2458bbc1464cSBarry Smith */ 24591baa6e33SBarry Smith if (snes->domainerror) PetscCall(VecSetInf(y)); 24603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2461bbc1464cSBarry Smith } 2462bbc1464cSBarry Smith 2463bbc1464cSBarry Smith /*@ 2464f6dfbefdSBarry Smith SNESComputeNGS - Calls the Gauss-Seidel function that has been set with `SNESSetNGS()`. 2465c79ef259SPeter Brune 2466c3339decSBarry Smith Collective 2467c79ef259SPeter Brune 2468c79ef259SPeter Brune Input Parameters: 2469f6dfbefdSBarry Smith + snes - the `SNES` context 2470c79ef259SPeter Brune . x - input vector 2471c79ef259SPeter Brune - b - rhs vector 2472c79ef259SPeter Brune 2473c79ef259SPeter Brune Output Parameter: 2474c79ef259SPeter Brune . x - new solution vector 2475c79ef259SPeter Brune 2476dc4c0fb0SBarry Smith Level: developer 2477dc4c0fb0SBarry Smith 2478f6dfbefdSBarry Smith Note: 2479f6dfbefdSBarry Smith `SNESComputeNGS()` is typically used within composed nonlinear solver 2480c79ef259SPeter Brune implementations, so most users would not generally call this routine 2481c79ef259SPeter Brune themselves. 2482c79ef259SPeter Brune 24838434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGSFn`, `SNESSetNGS()`, `SNESComputeFunction()`, `SNESNGS` 2484c79ef259SPeter Brune @*/ 2485d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeNGS(SNES snes, Vec b, Vec x) 2486d71ae5a4SJacob Faibussowitsch { 24876cab3a1bSJed Brown DM dm; 2488942e3340SBarry Smith DMSNES sdm; 2489646217ecSPeter Brune 2490646217ecSPeter Brune PetscFunctionBegin; 2491646217ecSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2492064a246eSJacob Faibussowitsch PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 2493064a246eSJacob Faibussowitsch if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 2494064a246eSJacob Faibussowitsch PetscCheckSameComm(snes, 1, x, 3); 2495064a246eSJacob Faibussowitsch if (b) PetscCheckSameComm(snes, 1, b, 2); 2496e0f629ddSJacob Faibussowitsch if (b) PetscCall(VecValidValues_Internal(b, 2, PETSC_TRUE)); 24979566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_NGSEval, snes, x, b, 0)); 24989566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 24999566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 25000fdf79fbSJacob Faibussowitsch PetscCheck(sdm->ops->computegs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetNGS() before SNESComputeNGS(), likely called from SNESSolve()."); 25019566063dSJacob Faibussowitsch if (b) PetscCall(VecLockReadPush(b)); 2502792fecdfSBarry Smith PetscCallBack("SNES callback NGS", (*sdm->ops->computegs)(snes, x, b, sdm->gsctx)); 25039566063dSJacob Faibussowitsch if (b) PetscCall(VecLockReadPop(b)); 25049566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_NGSEval, snes, x, b, 0)); 25053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2506646217ecSPeter Brune } 2507646217ecSPeter Brune 2508494a190aSStefano Zampini static PetscErrorCode SNESComputeFunction_FD(SNES snes, Vec Xin, Vec G) 2509494a190aSStefano Zampini { 2510494a190aSStefano Zampini Vec X; 2511494a190aSStefano Zampini PetscScalar *g; 2512494a190aSStefano Zampini PetscReal f, f2; 2513494a190aSStefano Zampini PetscInt low, high, N, i; 2514494a190aSStefano Zampini PetscBool flg; 2515494a190aSStefano Zampini PetscReal h = .5 * PETSC_SQRT_MACHINE_EPSILON; 2516494a190aSStefano Zampini 2517494a190aSStefano Zampini PetscFunctionBegin; 2518494a190aSStefano Zampini PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_fd_delta", &h, &flg)); 2519494a190aSStefano Zampini PetscCall(VecDuplicate(Xin, &X)); 2520494a190aSStefano Zampini PetscCall(VecCopy(Xin, X)); 2521494a190aSStefano Zampini PetscCall(VecGetSize(X, &N)); 2522494a190aSStefano Zampini PetscCall(VecGetOwnershipRange(X, &low, &high)); 2523494a190aSStefano Zampini PetscCall(VecSetOption(X, VEC_IGNORE_OFF_PROC_ENTRIES, PETSC_TRUE)); 2524494a190aSStefano Zampini PetscCall(VecGetArray(G, &g)); 2525494a190aSStefano Zampini for (i = 0; i < N; i++) { 2526494a190aSStefano Zampini PetscCall(VecSetValue(X, i, -h, ADD_VALUES)); 2527494a190aSStefano Zampini PetscCall(VecAssemblyBegin(X)); 2528494a190aSStefano Zampini PetscCall(VecAssemblyEnd(X)); 2529494a190aSStefano Zampini PetscCall(SNESComputeObjective(snes, X, &f)); 2530494a190aSStefano Zampini PetscCall(VecSetValue(X, i, 2.0 * h, ADD_VALUES)); 2531494a190aSStefano Zampini PetscCall(VecAssemblyBegin(X)); 2532494a190aSStefano Zampini PetscCall(VecAssemblyEnd(X)); 2533494a190aSStefano Zampini PetscCall(SNESComputeObjective(snes, X, &f2)); 2534494a190aSStefano Zampini PetscCall(VecSetValue(X, i, -h, ADD_VALUES)); 2535494a190aSStefano Zampini PetscCall(VecAssemblyBegin(X)); 2536494a190aSStefano Zampini PetscCall(VecAssemblyEnd(X)); 2537494a190aSStefano Zampini if (i >= low && i < high) g[i - low] = (f2 - f) / (2.0 * h); 2538494a190aSStefano Zampini } 2539494a190aSStefano Zampini PetscCall(VecRestoreArray(G, &g)); 2540494a190aSStefano Zampini PetscCall(VecDestroy(&X)); 2541494a190aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2542494a190aSStefano Zampini } 2543494a190aSStefano Zampini 2544494a190aSStefano Zampini PetscErrorCode SNESTestFunction(SNES snes) 2545494a190aSStefano Zampini { 2546494a190aSStefano Zampini Vec x, g1, g2, g3; 2547494a190aSStefano Zampini PetscBool complete_print = PETSC_FALSE, test = PETSC_FALSE; 2548494a190aSStefano Zampini PetscReal hcnorm, fdnorm, hcmax, fdmax, diffmax, diffnorm; 2549494a190aSStefano Zampini PetscScalar dot; 2550494a190aSStefano Zampini MPI_Comm comm; 2551494a190aSStefano Zampini PetscViewer viewer, mviewer; 2552494a190aSStefano Zampini PetscViewerFormat format; 2553494a190aSStefano Zampini PetscInt tabs; 2554494a190aSStefano Zampini static PetscBool directionsprinted = PETSC_FALSE; 25558434afd1SBarry Smith SNESObjectiveFn *objective; 2556494a190aSStefano Zampini 2557494a190aSStefano Zampini PetscFunctionBegin; 2558494a190aSStefano Zampini PetscCall(SNESGetObjective(snes, &objective, NULL)); 2559494a190aSStefano Zampini if (!objective) PetscFunctionReturn(PETSC_SUCCESS); 2560494a190aSStefano Zampini 2561494a190aSStefano Zampini PetscObjectOptionsBegin((PetscObject)snes); 2562494a190aSStefano Zampini PetscCall(PetscOptionsName("-snes_test_function", "Compare hand-coded and finite difference function", "None", &test)); 2563494a190aSStefano Zampini PetscCall(PetscOptionsViewer("-snes_test_function_view", "View difference between hand-coded and finite difference function element entries", "None", &mviewer, &format, &complete_print)); 2564494a190aSStefano Zampini PetscOptionsEnd(); 2565494a190aSStefano Zampini if (!test) { 2566494a190aSStefano Zampini if (complete_print) PetscCall(PetscViewerDestroy(&mviewer)); 2567494a190aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2568494a190aSStefano Zampini } 2569494a190aSStefano Zampini 2570494a190aSStefano Zampini PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 2571494a190aSStefano Zampini PetscCall(PetscViewerASCIIGetStdout(comm, &viewer)); 2572494a190aSStefano Zampini PetscCall(PetscViewerASCIIGetTab(viewer, &tabs)); 2573494a190aSStefano Zampini PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel)); 2574494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Function -------------\n")); 2575494a190aSStefano Zampini if (!complete_print && !directionsprinted) { 2576494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Run with -snes_test_function_view and optionally -snes_test_function <threshold> to show difference\n")); 2577494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " of hand-coded and finite difference function entries greater than <threshold>.\n")); 2578494a190aSStefano Zampini } 2579494a190aSStefano Zampini if (!directionsprinted) { 2580494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Testing hand-coded Function, if (for double precision runs) ||F - Ffd||/||F|| is\n")); 2581494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " O(1.e-8), the hand-coded Function is probably correct.\n")); 2582494a190aSStefano Zampini directionsprinted = PETSC_TRUE; 2583494a190aSStefano Zampini } 2584494a190aSStefano Zampini if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format)); 2585494a190aSStefano Zampini 2586494a190aSStefano Zampini PetscCall(SNESGetSolution(snes, &x)); 2587494a190aSStefano Zampini PetscCall(VecDuplicate(x, &g1)); 2588494a190aSStefano Zampini PetscCall(VecDuplicate(x, &g2)); 2589494a190aSStefano Zampini PetscCall(VecDuplicate(x, &g3)); 2590494a190aSStefano Zampini PetscCall(SNESComputeFunction(snes, x, g1)); 2591494a190aSStefano Zampini PetscCall(SNESComputeFunction_FD(snes, x, g2)); 2592494a190aSStefano Zampini 2593494a190aSStefano Zampini PetscCall(VecNorm(g2, NORM_2, &fdnorm)); 2594494a190aSStefano Zampini PetscCall(VecNorm(g1, NORM_2, &hcnorm)); 2595494a190aSStefano Zampini PetscCall(VecNorm(g2, NORM_INFINITY, &fdmax)); 2596494a190aSStefano Zampini PetscCall(VecNorm(g1, NORM_INFINITY, &hcmax)); 2597494a190aSStefano Zampini PetscCall(VecDot(g1, g2, &dot)); 2598494a190aSStefano Zampini PetscCall(VecCopy(g1, g3)); 2599494a190aSStefano Zampini PetscCall(VecAXPY(g3, -1.0, g2)); 2600494a190aSStefano Zampini PetscCall(VecNorm(g3, NORM_2, &diffnorm)); 2601494a190aSStefano Zampini PetscCall(VecNorm(g3, NORM_INFINITY, &diffmax)); 2602494a190aSStefano 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)))); 2603494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " 2-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffnorm / PetscMax(hcnorm, fdnorm)), (double)diffnorm)); 2604494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " max-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffmax / PetscMax(hcmax, fdmax)), (double)diffmax)); 2605494a190aSStefano Zampini 2606494a190aSStefano Zampini if (complete_print) { 2607494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded function ----------\n")); 2608494a190aSStefano Zampini PetscCall(VecView(g1, mviewer)); 2609494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Finite difference function ----------\n")); 2610494a190aSStefano Zampini PetscCall(VecView(g2, mviewer)); 2611494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded minus finite-difference function ----------\n")); 2612494a190aSStefano Zampini PetscCall(VecView(g3, mviewer)); 2613494a190aSStefano Zampini } 2614494a190aSStefano Zampini PetscCall(VecDestroy(&g1)); 2615494a190aSStefano Zampini PetscCall(VecDestroy(&g2)); 2616494a190aSStefano Zampini PetscCall(VecDestroy(&g3)); 2617494a190aSStefano Zampini 2618494a190aSStefano Zampini if (complete_print) { 2619494a190aSStefano Zampini PetscCall(PetscViewerPopFormat(mviewer)); 2620494a190aSStefano Zampini PetscCall(PetscViewerDestroy(&mviewer)); 2621494a190aSStefano Zampini } 2622494a190aSStefano Zampini PetscCall(PetscViewerASCIISetTab(viewer, tabs)); 2623494a190aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2624494a190aSStefano Zampini } 2625494a190aSStefano Zampini 2626d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestJacobian(SNES snes) 2627d71ae5a4SJacob Faibussowitsch { 262812837594SBarry Smith Mat A, B, C, D, jacobian; 26294df93895SStefano Zampini Vec x = snes->vec_sol, f; 2630e885f1abSBarry Smith PetscReal nrm, gnorm; 263181e7118cSBarry Smith PetscReal threshold = 1.e-5; 26320e276705SLisandro Dalcin MatType mattype; 2633e885f1abSBarry Smith PetscInt m, n, M, N; 2634e885f1abSBarry Smith void *functx; 26352cd624f9SStefano Zampini PetscBool complete_print = PETSC_FALSE, threshold_print = PETSC_FALSE, test = PETSC_FALSE, flg, istranspose; 26363325ff46SBarry Smith PetscViewer viewer, mviewer; 2637e885f1abSBarry Smith MPI_Comm comm; 2638e885f1abSBarry Smith PetscInt tabs; 263912837594SBarry Smith static PetscBool directionsprinted = PETSC_FALSE; 26403325ff46SBarry Smith PetscViewerFormat format; 2641e885f1abSBarry Smith 2642e885f1abSBarry Smith PetscFunctionBegin; 2643d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)snes); 26449566063dSJacob Faibussowitsch PetscCall(PetscOptionsName("-snes_test_jacobian", "Compare hand-coded and finite difference Jacobians", "None", &test)); 26459566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-snes_test_jacobian", "Threshold for element difference between hand-coded and finite difference being meaningful", "None", threshold, &threshold, NULL)); 26469566063dSJacob Faibussowitsch PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display", "-snes_test_jacobian_view", "3.13", NULL)); 26474ead3382SBarry Smith PetscCall(PetscOptionsViewer("-snes_test_jacobian_view", "View difference between hand-coded and finite difference Jacobians element entries", "None", &mviewer, &format, &complete_print)); 26489566063dSJacob Faibussowitsch PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display_threshold", "-snes_test_jacobian", "3.13", "-snes_test_jacobian accepts an optional threshold (since v3.10)")); 26499566063dSJacob 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)); 2650d0609cedSBarry Smith PetscOptionsEnd(); 26513ba16761SJacob Faibussowitsch if (!test) PetscFunctionReturn(PETSC_SUCCESS); 2652e885f1abSBarry Smith 26539566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 26549566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(comm, &viewer)); 26559566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetTab(viewer, &tabs)); 26569566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel)); 26579566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Jacobian -------------\n")); 265812837594SBarry Smith if (!complete_print && !directionsprinted) { 26599566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Run with -snes_test_jacobian_view and optionally -snes_test_jacobian <threshold> to show difference\n")); 26609566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " of hand-coded and finite difference Jacobian entries greater than <threshold>.\n")); 266112837594SBarry Smith } 266212837594SBarry Smith if (!directionsprinted) { 26639566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Testing hand-coded Jacobian, if (for double precision runs) ||J - Jfd||_F/||J||_F is\n")); 26649566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " O(1.e-8), the hand-coded Jacobian is probably correct.\n")); 266512837594SBarry Smith directionsprinted = PETSC_TRUE; 2666e885f1abSBarry Smith } 26671baa6e33SBarry Smith if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format)); 2668e885f1abSBarry Smith 26699566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes->jacobian, MATMFFD, &flg)); 267012837594SBarry Smith if (!flg) jacobian = snes->jacobian; 267112837594SBarry Smith else jacobian = snes->jacobian_pre; 267212837594SBarry Smith 26734df93895SStefano Zampini if (!x) PetscCall(MatCreateVecs(jacobian, &x, NULL)); 26744df93895SStefano Zampini else PetscCall(PetscObjectReference((PetscObject)x)); 26759566063dSJacob Faibussowitsch PetscCall(VecDuplicate(x, &f)); 26764df93895SStefano Zampini 2677a82339d0SMatthew G. Knepley /* evaluate the function at this point because SNESComputeJacobianDefault() assumes that the function has been evaluated and put into snes->vec_func */ 26789566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, x, f)); 26799566063dSJacob Faibussowitsch PetscCall(VecDestroy(&f)); 26809566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESKSPTRANSPOSEONLY, &istranspose)); 268112837594SBarry Smith while (jacobian) { 26822cd624f9SStefano Zampini Mat JT = NULL, Jsave = NULL; 26832cd624f9SStefano Zampini 26842cd624f9SStefano Zampini if (istranspose) { 26859566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(jacobian, &JT)); 26862cd624f9SStefano Zampini Jsave = jacobian; 26872cd624f9SStefano Zampini jacobian = JT; 26882cd624f9SStefano Zampini } 26899566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)jacobian, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, "")); 269012837594SBarry Smith if (flg) { 269112837594SBarry Smith A = jacobian; 26929566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 269312837594SBarry Smith } else { 26949566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(jacobian, MATAIJ, &A)); 269512837594SBarry Smith } 2696e885f1abSBarry Smith 26979566063dSJacob Faibussowitsch PetscCall(MatGetType(A, &mattype)); 26989566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &M, &N)); 26999566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &m, &n)); 27009566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B)); 27019566063dSJacob Faibussowitsch PetscCall(MatSetType(B, mattype)); 27029566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, m, n, M, N)); 27039566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(B, A, A)); 27049566063dSJacob Faibussowitsch PetscCall(MatSetUp(B)); 27059566063dSJacob Faibussowitsch PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 2706e885f1abSBarry Smith 27079566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, NULL, &functx)); 27089566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobianDefault(snes, x, B, B, functx)); 270912837594SBarry Smith 27109566063dSJacob Faibussowitsch PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &D)); 27119566063dSJacob Faibussowitsch PetscCall(MatAYPX(D, -1.0, A, DIFFERENT_NONZERO_PATTERN)); 27129566063dSJacob Faibussowitsch PetscCall(MatNorm(D, NORM_FROBENIUS, &nrm)); 27139566063dSJacob Faibussowitsch PetscCall(MatNorm(A, NORM_FROBENIUS, &gnorm)); 27149566063dSJacob Faibussowitsch PetscCall(MatDestroy(&D)); 271512837594SBarry Smith if (!gnorm) gnorm = 1; /* just in case */ 27169566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " ||J - Jfd||_F/||J||_F = %g, ||J - Jfd||_F = %g\n", (double)(nrm / gnorm), (double)nrm)); 271712837594SBarry Smith 2718e885f1abSBarry Smith if (complete_print) { 27199566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded Jacobian ----------\n")); 27209566063dSJacob Faibussowitsch PetscCall(MatView(A, mviewer)); 27219566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Finite difference Jacobian ----------\n")); 27229566063dSJacob Faibussowitsch PetscCall(MatView(B, mviewer)); 2723e885f1abSBarry Smith } 2724e885f1abSBarry Smith 2725df10fb39SFande Kong if (threshold_print || complete_print) { 2726e885f1abSBarry Smith PetscInt Istart, Iend, *ccols, bncols, cncols, j, row; 2727e885f1abSBarry Smith PetscScalar *cvals; 2728e885f1abSBarry Smith const PetscInt *bcols; 2729e885f1abSBarry Smith const PetscScalar *bvals; 2730e885f1abSBarry Smith 27319566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C)); 27329566063dSJacob Faibussowitsch PetscCall(MatSetType(C, mattype)); 27339566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, m, n, M, N)); 27349566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(C, A, A)); 27359566063dSJacob Faibussowitsch PetscCall(MatSetUp(C)); 27369566063dSJacob Faibussowitsch PetscCall(MatSetOption(C, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 27370e276705SLisandro Dalcin 27389566063dSJacob Faibussowitsch PetscCall(MatAYPX(B, -1.0, A, DIFFERENT_NONZERO_PATTERN)); 27399566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(B, &Istart, &Iend)); 2740e885f1abSBarry Smith 2741e885f1abSBarry Smith for (row = Istart; row < Iend; row++) { 27429566063dSJacob Faibussowitsch PetscCall(MatGetRow(B, row, &bncols, &bcols, &bvals)); 27439566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(bncols, &ccols, bncols, &cvals)); 2744e885f1abSBarry Smith for (j = 0, cncols = 0; j < bncols; j++) { 274523a52b1dSBarry Smith if (PetscAbsScalar(bvals[j]) > threshold) { 2746e885f1abSBarry Smith ccols[cncols] = bcols[j]; 2747e885f1abSBarry Smith cvals[cncols] = bvals[j]; 2748e885f1abSBarry Smith cncols += 1; 2749e885f1abSBarry Smith } 2750e885f1abSBarry Smith } 275148a46eb9SPierre Jolivet if (cncols) PetscCall(MatSetValues(C, 1, &row, cncols, ccols, cvals, INSERT_VALUES)); 27529566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(B, row, &bncols, &bcols, &bvals)); 27539566063dSJacob Faibussowitsch PetscCall(PetscFree2(ccols, cvals)); 2754e885f1abSBarry Smith } 27559566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 27569566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 27579566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded minus finite-difference Jacobian with tolerance %g ----------\n", (double)threshold)); 27589566063dSJacob Faibussowitsch PetscCall(MatView(C, complete_print ? mviewer : viewer)); 27599566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C)); 2760e885f1abSBarry Smith } 27619566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A)); 27629566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 27639566063dSJacob Faibussowitsch PetscCall(MatDestroy(&JT)); 27642cd624f9SStefano Zampini if (Jsave) jacobian = Jsave; 276512837594SBarry Smith if (jacobian != snes->jacobian_pre) { 276612837594SBarry Smith jacobian = snes->jacobian_pre; 27679566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Jacobian for preconditioner -------------\n")); 27689371c9d4SSatish Balay } else jacobian = NULL; 276912837594SBarry Smith } 27709566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); 27711baa6e33SBarry Smith if (complete_print) PetscCall(PetscViewerPopFormat(mviewer)); 2772cd791dc2SBarry Smith if (mviewer) PetscCall(PetscOptionsRestoreViewer(&mviewer)); 27739566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISetTab(viewer, tabs)); 27743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2775e885f1abSBarry Smith } 2776e885f1abSBarry Smith 277762fef451SLois Curfman McInnes /*@ 2778f6dfbefdSBarry Smith SNESComputeJacobian - Computes the Jacobian matrix that has been set with `SNESSetJacobian()`. 277962fef451SLois Curfman McInnes 2780c3339decSBarry Smith Collective 2781c7afd0dbSLois Curfman McInnes 278262fef451SLois Curfman McInnes Input Parameters: 2783f6dfbefdSBarry Smith + snes - the `SNES` context 2784e4094ef1SJacob Faibussowitsch - X - input vector 278562fef451SLois Curfman McInnes 278662fef451SLois Curfman McInnes Output Parameters: 2787c7afd0dbSLois Curfman McInnes + A - Jacobian matrix 2788420bcc1bSBarry Smith - B - optional matrix for building the preconditioner, usually the same as `A` 2789fee21e36SBarry Smith 2790e35cf81dSBarry Smith Options Database Keys: 279167b8a455SSatish Balay + -snes_lag_preconditioner <lag> - how often to rebuild preconditioner 279267b8a455SSatish Balay . -snes_lag_jacobian <lag> - how often to rebuild Jacobian 2793455a5933SJed 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. 2794455a5933SJed 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 2795693365a8SJed Brown . -snes_compare_explicit - Compare the computed Jacobian to the finite difference Jacobian and output the differences 2796693365a8SJed Brown . -snes_compare_explicit_draw - Compare the computed Jacobian to the finite difference Jacobian and draw the result 2797693365a8SJed Brown . -snes_compare_explicit_contour - Compare the computed Jacobian to the finite difference Jacobian and draw a contour plot with the result 27984c30e9fbSJed Brown . -snes_compare_operator - Make the comparison options above use the operator instead of the preconditioning matrix 279994d6a431SBarry Smith . -snes_compare_coloring - Compute the finite difference Jacobian using coloring and display norms of difference 2800a5b23f4aSJose E. Roman . -snes_compare_coloring_display - Compute the finite difference Jacobian using coloring and display verbose differences 2801c01495d3SJed Brown . -snes_compare_coloring_threshold - Display only those matrix entries that differ by more than a given threshold 2802dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_atol - Absolute tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold` 2803dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_rtol - Relative tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold` 2804a5b23f4aSJose E. Roman . -snes_compare_coloring_draw - Compute the finite difference Jacobian using coloring and draw differences 2805a5b23f4aSJose E. Roman - -snes_compare_coloring_draw_contour - Compute the finite difference Jacobian using coloring and show contours of matrices and differences 2806c01495d3SJed Brown 2807dc4c0fb0SBarry Smith Level: developer 2808dc4c0fb0SBarry Smith 2809f6dfbefdSBarry Smith Note: 281062fef451SLois Curfman McInnes Most users should not need to explicitly call this routine, as it 281162fef451SLois Curfman McInnes is used internally within the nonlinear solvers. 281262fef451SLois Curfman McInnes 2813420bcc1bSBarry Smith Developer Note: 2814dc4c0fb0SBarry 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 2815420bcc1bSBarry Smith with the `SNESType` of test that has been removed. 2816e885f1abSBarry Smith 28171cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetJacobian()`, `KSPSetOperators()`, `MatStructure`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()` 281862fef451SLois Curfman McInnes @*/ 2819d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeJacobian(SNES snes, Vec X, Mat A, Mat B) 2820d71ae5a4SJacob Faibussowitsch { 2821ace3abfcSBarry Smith PetscBool flag; 28226cab3a1bSJed Brown DM dm; 2823942e3340SBarry Smith DMSNES sdm; 2824e0e3a89bSBarry Smith KSP ksp; 28253a40ed3dSBarry Smith 28263a40ed3dSBarry Smith PetscFunctionBegin; 28270700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 28280700a824SBarry Smith PetscValidHeaderSpecific(X, VEC_CLASSID, 2); 2829c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, X, 2); 2830e0f629ddSJacob Faibussowitsch PetscCall(VecValidValues_Internal(X, 2, PETSC_TRUE)); 28319566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 28329566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 28333232da50SPeter Brune 283401c1178eSBarry Smith /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix-free */ 2835fe3ffe1eSBarry Smith if (snes->lagjacobian == -2) { 2836fe3ffe1eSBarry Smith snes->lagjacobian = -1; 2837f5af7f23SKarl Rupp 28389566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n")); 2839fe3ffe1eSBarry Smith } else if (snes->lagjacobian == -1) { 28409566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is -1\n")); 28419566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag)); 2842ebd3b9afSBarry Smith if (flag) { 28439566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 28449566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 2845ebd3b9afSBarry Smith } 28463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 284737ec4e1aSPeter Brune } else if (snes->lagjacobian > 1 && (snes->iter + snes->jac_iter) % snes->lagjacobian) { 284863a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagjacobian, snes->iter)); 28499566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag)); 2850ebd3b9afSBarry Smith if (flag) { 28519566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 28529566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 2853ebd3b9afSBarry Smith } 28543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2855e35cf81dSBarry Smith } 2856efd4aadfSBarry Smith if (snes->npc && snes->npcside == PC_LEFT) { 28579566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 28589566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 28593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2860d728fb7dSPeter Brune } 2861e35cf81dSBarry Smith 28629566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_JacobianEval, snes, X, A, B)); 28639566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(X)); 2864800f99ffSJeremy L Thompson { 2865800f99ffSJeremy L Thompson void *ctx; 28668434afd1SBarry Smith SNESJacobianFn *J; 2867800f99ffSJeremy L Thompson PetscCall(DMSNESGetJacobian(dm, &J, &ctx)); 2868800f99ffSJeremy L Thompson PetscCallBack("SNES callback Jacobian", (*J)(snes, X, A, B, ctx)); 2869800f99ffSJeremy L Thompson } 28709566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(X)); 28719566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_JacobianEval, snes, X, A, B)); 287228d58a37SPierre Jolivet 287328d58a37SPierre Jolivet /* attach latest linearization point to the preconditioning matrix */ 28749566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)B, "__SNES_latest_X", (PetscObject)X)); 2875a8054027SBarry Smith 2876e0e3a89bSBarry Smith /* the next line ensures that snes->ksp exists */ 28779566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 28783b4f5425SBarry Smith if (snes->lagpreconditioner == -2) { 28799566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Rebuilding preconditioner exactly once since lag is -2\n")); 28809566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE)); 28813b4f5425SBarry Smith snes->lagpreconditioner = -1; 28823b4f5425SBarry Smith } else if (snes->lagpreconditioner == -1) { 28839566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is -1\n")); 28849566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE)); 288537ec4e1aSPeter Brune } else if (snes->lagpreconditioner > 1 && (snes->iter + snes->pre_iter) % snes->lagpreconditioner) { 288663a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagpreconditioner, snes->iter)); 28879566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE)); 2888d1e9a80fSBarry Smith } else { 28899566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Rebuilding preconditioner\n")); 28909566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE)); 2891a8054027SBarry Smith } 2892a8054027SBarry Smith 28934df93895SStefano Zampini /* monkey business to allow testing Jacobians in multilevel solvers. 28944df93895SStefano Zampini This is needed because the SNESTestXXX interface does not accept vectors and matrices */ 28954df93895SStefano Zampini { 28964df93895SStefano Zampini Vec xsave = snes->vec_sol; 28974df93895SStefano Zampini Mat jacobiansave = snes->jacobian; 28984df93895SStefano Zampini Mat jacobian_presave = snes->jacobian_pre; 28994df93895SStefano Zampini 29004df93895SStefano Zampini snes->vec_sol = X; 29014df93895SStefano Zampini snes->jacobian = A; 29024df93895SStefano Zampini snes->jacobian_pre = B; 2903494a190aSStefano Zampini PetscCall(SNESTestFunction(snes)); 29049566063dSJacob Faibussowitsch PetscCall(SNESTestJacobian(snes)); 2905494a190aSStefano Zampini 29064df93895SStefano Zampini snes->vec_sol = xsave; 29074df93895SStefano Zampini snes->jacobian = jacobiansave; 29084df93895SStefano Zampini snes->jacobian_pre = jacobian_presave; 29094df93895SStefano Zampini } 29104df93895SStefano Zampini 2911693365a8SJed Brown { 2912693365a8SJed Brown PetscBool flag = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_operator = PETSC_FALSE; 29139566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit", NULL, NULL, &flag)); 29149566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw", NULL, NULL, &flag_draw)); 29159566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw_contour", NULL, NULL, &flag_contour)); 29169566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_operator", NULL, NULL, &flag_operator)); 2917693365a8SJed Brown if (flag || flag_draw || flag_contour) { 29180298fd71SBarry Smith Mat Bexp_mine = NULL, Bexp, FDexp; 2919693365a8SJed Brown PetscViewer vdraw, vstdout; 29206b3a5b13SJed Brown PetscBool flg; 2921693365a8SJed Brown if (flag_operator) { 29229566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(A, MATAIJ, &Bexp_mine)); 2923693365a8SJed Brown Bexp = Bexp_mine; 2924693365a8SJed Brown } else { 2925693365a8SJed Brown /* See if the preconditioning matrix can be viewed and added directly */ 29269566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)B, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPIBAIJ, "")); 292794ab13aaSBarry Smith if (flg) Bexp = B; 2928693365a8SJed Brown else { 2929693365a8SJed Brown /* If the "preconditioning" matrix is itself MATSHELL or some other type without direct support */ 29309566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(B, MATAIJ, &Bexp_mine)); 2931693365a8SJed Brown Bexp = Bexp_mine; 2932693365a8SJed Brown } 2933693365a8SJed Brown } 29349566063dSJacob Faibussowitsch PetscCall(MatConvert(Bexp, MATSAME, MAT_INITIAL_MATRIX, &FDexp)); 29359566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobianDefault(snes, X, FDexp, FDexp, NULL)); 29369566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout)); 2937693365a8SJed Brown if (flag_draw || flag_contour) { 29389566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Explicit Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw)); 29399566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 29400298fd71SBarry Smith } else vdraw = NULL; 29419566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit %s\n", flag_operator ? "Jacobian" : "preconditioning Jacobian")); 29429566063dSJacob Faibussowitsch if (flag) PetscCall(MatView(Bexp, vstdout)); 29439566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(Bexp, vdraw)); 29449566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Finite difference Jacobian\n")); 29459566063dSJacob Faibussowitsch if (flag) PetscCall(MatView(FDexp, vstdout)); 29469566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(FDexp, vdraw)); 29479566063dSJacob Faibussowitsch PetscCall(MatAYPX(FDexp, -1.0, Bexp, SAME_NONZERO_PATTERN)); 29489566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian\n")); 29499566063dSJacob Faibussowitsch if (flag) PetscCall(MatView(FDexp, vstdout)); 2950693365a8SJed Brown if (vdraw) { /* Always use contour for the difference */ 29519566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 29529566063dSJacob Faibussowitsch PetscCall(MatView(FDexp, vdraw)); 29539566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(vdraw)); 2954693365a8SJed Brown } 29559566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw)); 29569566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&vdraw)); 29579566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bexp_mine)); 29589566063dSJacob Faibussowitsch PetscCall(MatDestroy(&FDexp)); 2959693365a8SJed Brown } 2960693365a8SJed Brown } 29614c30e9fbSJed Brown { 29626719d8e4SJed Brown PetscBool flag = PETSC_FALSE, flag_display = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_threshold = PETSC_FALSE; 29636719d8e4SJed Brown PetscReal threshold_atol = PETSC_SQRT_MACHINE_EPSILON, threshold_rtol = 10 * PETSC_SQRT_MACHINE_EPSILON; 29649566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring", NULL, NULL, &flag)); 29659566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_display", NULL, NULL, &flag_display)); 29669566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw", NULL, NULL, &flag_draw)); 29679566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw_contour", NULL, NULL, &flag_contour)); 29689566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold", NULL, NULL, &flag_threshold)); 296927b0f280SBarry Smith if (flag_threshold) { 29709566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_rtol", &threshold_rtol, NULL)); 29719566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_atol", &threshold_atol, NULL)); 297227b0f280SBarry Smith } 29736719d8e4SJed Brown if (flag || flag_display || flag_draw || flag_contour || flag_threshold) { 29744c30e9fbSJed Brown Mat Bfd; 29754c30e9fbSJed Brown PetscViewer vdraw, vstdout; 2976335efc43SPeter Brune MatColoring coloring; 29774c30e9fbSJed Brown ISColoring iscoloring; 29784c30e9fbSJed Brown MatFDColoring matfdcoloring; 29798434afd1SBarry Smith SNESFunctionFn *func; 29804c30e9fbSJed Brown void *funcctx; 29816719d8e4SJed Brown PetscReal norm1, norm2, normmax; 29824c30e9fbSJed Brown 29839566063dSJacob Faibussowitsch PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &Bfd)); 29849566063dSJacob Faibussowitsch PetscCall(MatColoringCreate(Bfd, &coloring)); 29859566063dSJacob Faibussowitsch PetscCall(MatColoringSetType(coloring, MATCOLORINGSL)); 29869566063dSJacob Faibussowitsch PetscCall(MatColoringSetFromOptions(coloring)); 29879566063dSJacob Faibussowitsch PetscCall(MatColoringApply(coloring, &iscoloring)); 29889566063dSJacob Faibussowitsch PetscCall(MatColoringDestroy(&coloring)); 29899566063dSJacob Faibussowitsch PetscCall(MatFDColoringCreate(Bfd, iscoloring, &matfdcoloring)); 29909566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFromOptions(matfdcoloring)); 29919566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetUp(Bfd, iscoloring, matfdcoloring)); 29929566063dSJacob Faibussowitsch PetscCall(ISColoringDestroy(&iscoloring)); 29934c30e9fbSJed Brown 29944c30e9fbSJed Brown /* This method of getting the function is currently unreliable since it doesn't work for DM local functions. */ 29959566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, &func, &funcctx)); 29969566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFunction(matfdcoloring, (PetscErrorCode(*)(void))func, funcctx)); 29979566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)matfdcoloring, ((PetscObject)snes)->prefix)); 29989566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)matfdcoloring, "coloring_")); 29999566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFromOptions(matfdcoloring)); 30009566063dSJacob Faibussowitsch PetscCall(MatFDColoringApply(Bfd, matfdcoloring, X, snes)); 30019566063dSJacob Faibussowitsch PetscCall(MatFDColoringDestroy(&matfdcoloring)); 30024c30e9fbSJed Brown 30039566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout)); 30044c30e9fbSJed Brown if (flag_draw || flag_contour) { 30059566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Colored Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw)); 30069566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 30070298fd71SBarry Smith } else vdraw = NULL; 30089566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit preconditioning Jacobian\n")); 30099566063dSJacob Faibussowitsch if (flag_display) PetscCall(MatView(B, vstdout)); 30109566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(B, vdraw)); 30119566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Colored Finite difference Jacobian\n")); 30129566063dSJacob Faibussowitsch if (flag_display) PetscCall(MatView(Bfd, vstdout)); 30139566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(Bfd, vdraw)); 30149566063dSJacob Faibussowitsch PetscCall(MatAYPX(Bfd, -1.0, B, SAME_NONZERO_PATTERN)); 30159566063dSJacob Faibussowitsch PetscCall(MatNorm(Bfd, NORM_1, &norm1)); 30169566063dSJacob Faibussowitsch PetscCall(MatNorm(Bfd, NORM_FROBENIUS, &norm2)); 30179566063dSJacob Faibussowitsch PetscCall(MatNorm(Bfd, NORM_MAX, &normmax)); 30189566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian, norm1=%g normFrob=%g normmax=%g\n", (double)norm1, (double)norm2, (double)normmax)); 30199566063dSJacob Faibussowitsch if (flag_display) PetscCall(MatView(Bfd, vstdout)); 30204c30e9fbSJed Brown if (vdraw) { /* Always use contour for the difference */ 30219566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 30229566063dSJacob Faibussowitsch PetscCall(MatView(Bfd, vdraw)); 30239566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(vdraw)); 30244c30e9fbSJed Brown } 30259566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw)); 30266719d8e4SJed Brown 30276719d8e4SJed Brown if (flag_threshold) { 30286719d8e4SJed Brown PetscInt bs, rstart, rend, i; 30299566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(B, &bs)); 30309566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(B, &rstart, &rend)); 30316719d8e4SJed Brown for (i = rstart; i < rend; i++) { 30326719d8e4SJed Brown const PetscScalar *ba, *ca; 30336719d8e4SJed Brown const PetscInt *bj, *cj; 30346719d8e4SJed Brown PetscInt bn, cn, j, maxentrycol = -1, maxdiffcol = -1, maxrdiffcol = -1; 30356719d8e4SJed Brown PetscReal maxentry = 0, maxdiff = 0, maxrdiff = 0; 30369566063dSJacob Faibussowitsch PetscCall(MatGetRow(B, i, &bn, &bj, &ba)); 30379566063dSJacob Faibussowitsch PetscCall(MatGetRow(Bfd, i, &cn, &cj, &ca)); 30385f80ce2aSJacob Faibussowitsch PetscCheck(bn == cn, ((PetscObject)A)->comm, PETSC_ERR_PLIB, "Unexpected different nonzero pattern in -snes_compare_coloring_threshold"); 30396719d8e4SJed Brown for (j = 0; j < bn; j++) { 30406719d8e4SJed Brown PetscReal rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j])); 30416719d8e4SJed Brown if (PetscAbsScalar(ba[j]) > PetscAbs(maxentry)) { 30426719d8e4SJed Brown maxentrycol = bj[j]; 30436719d8e4SJed Brown maxentry = PetscRealPart(ba[j]); 30446719d8e4SJed Brown } 30456719d8e4SJed Brown if (PetscAbsScalar(ca[j]) > PetscAbs(maxdiff)) { 30466719d8e4SJed Brown maxdiffcol = bj[j]; 30476719d8e4SJed Brown maxdiff = PetscRealPart(ca[j]); 30486719d8e4SJed Brown } 30496719d8e4SJed Brown if (rdiff > maxrdiff) { 30506719d8e4SJed Brown maxrdiffcol = bj[j]; 30516719d8e4SJed Brown maxrdiff = rdiff; 30526719d8e4SJed Brown } 30536719d8e4SJed Brown } 30546719d8e4SJed Brown if (maxrdiff > 1) { 305563a3b9bcSJacob 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)); 30566719d8e4SJed Brown for (j = 0; j < bn; j++) { 30576719d8e4SJed Brown PetscReal rdiff; 30586719d8e4SJed Brown rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j])); 305948a46eb9SPierre Jolivet if (rdiff > 1) PetscCall(PetscViewerASCIIPrintf(vstdout, " (%" PetscInt_FMT ",%g:%g)", bj[j], (double)PetscRealPart(ba[j]), (double)PetscRealPart(ca[j]))); 30606719d8e4SJed Brown } 306163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "\n")); 30626719d8e4SJed Brown } 30639566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(B, i, &bn, &bj, &ba)); 30649566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(Bfd, i, &cn, &cj, &ca)); 30656719d8e4SJed Brown } 30666719d8e4SJed Brown } 30679566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&vdraw)); 30689566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bfd)); 30694c30e9fbSJed Brown } 30704c30e9fbSJed Brown } 30713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30729b94acceSBarry Smith } 30739b94acceSBarry Smith 30749b94acceSBarry Smith /*@C 30759b94acceSBarry Smith SNESSetJacobian - Sets the function to compute Jacobian as well as the 3076044dda88SLois Curfman McInnes location to store the matrix. 30779b94acceSBarry Smith 3078c3339decSBarry Smith Logically Collective 3079c7afd0dbSLois Curfman McInnes 30809b94acceSBarry Smith Input Parameters: 3081f6dfbefdSBarry Smith + snes - the `SNES` context 3082e5d3d808SBarry Smith . Amat - the matrix that defines the (approximate) Jacobian 3083dc4c0fb0SBarry Smith . Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`. 30848434afd1SBarry Smith . J - Jacobian evaluation routine (if `NULL` then `SNES` retains any previously set value), see `SNESJacobianFn` for details 3085c7afd0dbSLois Curfman McInnes - ctx - [optional] user-defined context for private data for the 3086dc4c0fb0SBarry Smith Jacobian evaluation routine (may be `NULL`) (if `NULL` then `SNES` retains any previously set value) 3087dc4c0fb0SBarry Smith 3088dc4c0fb0SBarry Smith Level: beginner 30899b94acceSBarry Smith 30909b94acceSBarry Smith Notes: 3091dc4c0fb0SBarry Smith If the `Amat` matrix and `Pmat` matrix are different you must call `MatAssemblyBegin()`/`MatAssemblyEnd()` on 309216913363SBarry Smith each matrix. 309316913363SBarry Smith 3094dc4c0fb0SBarry Smith If you know the operator `Amat` has a null space you can use `MatSetNullSpace()` and `MatSetTransposeNullSpace()` to supply the null 3095dc4c0fb0SBarry Smith space to `Amat` and the `KSP` solvers will automatically use that null space as needed during the solution process. 3096895c21f2SBarry Smith 3097dc4c0fb0SBarry Smith If using `SNESComputeJacobianDefaultColor()` to assemble a Jacobian, the `ctx` argument 3098f6dfbefdSBarry Smith must be a `MatFDColoring`. 3099a8a26c1eSJed Brown 3100c3cc8fd1SJed Brown Other defect-correction schemes can be used by computing a different matrix in place of the Jacobian. One common 3101f6dfbefdSBarry Smith example is to use the "Picard linearization" which only differentiates through the highest order parts of each term using `SNESSetPicard()` 3102c3cc8fd1SJed Brown 31031cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSPSetOperators()`, `SNESSetFunction()`, `MatMFFDComputeJacobian()`, `SNESComputeJacobianDefaultColor()`, `MatStructure`, 31048434afd1SBarry Smith `SNESSetPicard()`, `SNESJacobianFn`, `SNESFunctionFn` 31059b94acceSBarry Smith @*/ 31068434afd1SBarry Smith PetscErrorCode SNESSetJacobian(SNES snes, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx) 3107d71ae5a4SJacob Faibussowitsch { 31086cab3a1bSJed Brown DM dm; 31093a7fca6bSBarry Smith 31103a40ed3dSBarry Smith PetscFunctionBegin; 31110700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3112e5d3d808SBarry Smith if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2); 3113e5d3d808SBarry Smith if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3); 3114e5d3d808SBarry Smith if (Amat) PetscCheckSameComm(snes, 1, Amat, 2); 3115e5d3d808SBarry Smith if (Pmat) PetscCheckSameComm(snes, 1, Pmat, 3); 31169566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 31179566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, J, ctx)); 3118e5d3d808SBarry Smith if (Amat) { 31199566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)Amat)); 31209566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian)); 3121f5af7f23SKarl Rupp 3122e5d3d808SBarry Smith snes->jacobian = Amat; 31233a7fca6bSBarry Smith } 3124e5d3d808SBarry Smith if (Pmat) { 31259566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)Pmat)); 31269566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian_pre)); 3127f5af7f23SKarl Rupp 3128e5d3d808SBarry Smith snes->jacobian_pre = Pmat; 31293a7fca6bSBarry Smith } 31303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 31319b94acceSBarry Smith } 313262fef451SLois Curfman McInnes 3133c2aafc4cSSatish Balay /*@C 3134b4fd4287SBarry Smith SNESGetJacobian - Returns the Jacobian matrix and optionally the user 3135b4fd4287SBarry Smith provided context for evaluating the Jacobian. 3136b4fd4287SBarry Smith 3137420bcc1bSBarry Smith Not Collective, but `Mat` object will be parallel if `SNES` is 3138c7afd0dbSLois Curfman McInnes 3139b4fd4287SBarry Smith Input Parameter: 3140b4fd4287SBarry Smith . snes - the nonlinear solver context 3141b4fd4287SBarry Smith 3142b4fd4287SBarry Smith Output Parameters: 3143dc4c0fb0SBarry Smith + Amat - location to stash (approximate) Jacobian matrix (or `NULL`) 3144dc4c0fb0SBarry Smith . Pmat - location to stash matrix used to compute the preconditioner (or `NULL`) 31458434afd1SBarry Smith . J - location to put Jacobian function (or `NULL`), for calling sequence see `SNESJacobianFn` 3146dc4c0fb0SBarry Smith - ctx - location to stash Jacobian ctx (or `NULL`) 3147fee21e36SBarry Smith 314836851e7fSLois Curfman McInnes Level: advanced 314936851e7fSLois Curfman McInnes 31508434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `Mat`, `SNESSetJacobian()`, `SNESComputeJacobian()`, `SNESJacobianFn`, `SNESGetFunction()` 3151b4fd4287SBarry Smith @*/ 31528434afd1SBarry Smith PetscErrorCode SNESGetJacobian(SNES snes, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx) 3153d71ae5a4SJacob Faibussowitsch { 31546cab3a1bSJed Brown DM dm; 31556cab3a1bSJed Brown 31563a40ed3dSBarry Smith PetscFunctionBegin; 31570700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3158e5d3d808SBarry Smith if (Amat) *Amat = snes->jacobian; 3159e5d3d808SBarry Smith if (Pmat) *Pmat = snes->jacobian_pre; 31609566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 3161800f99ffSJeremy L Thompson PetscCall(DMSNESGetJacobian(dm, J, ctx)); 31623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3163b4fd4287SBarry Smith } 3164b4fd4287SBarry Smith 3165d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetDefaultComputeJacobian(SNES snes) 3166d71ae5a4SJacob Faibussowitsch { 316758b371f3SBarry Smith DM dm; 316858b371f3SBarry Smith DMSNES sdm; 316958b371f3SBarry Smith 317058b371f3SBarry Smith PetscFunctionBegin; 31719566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 31729566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 317358b371f3SBarry Smith if (!sdm->ops->computejacobian && snes->jacobian_pre) { 317458b371f3SBarry Smith DM dm; 317558b371f3SBarry Smith PetscBool isdense, ismf; 317658b371f3SBarry Smith 31779566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 31789566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &isdense, MATSEQDENSE, MATMPIDENSE, MATDENSE, NULL)); 31799566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &ismf, MATMFFD, MATSHELL, NULL)); 318058b371f3SBarry Smith if (isdense) { 31819566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefault, NULL)); 318258b371f3SBarry Smith } else if (!ismf) { 31839566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefaultColor, NULL)); 318458b371f3SBarry Smith } 318558b371f3SBarry Smith } 31863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 318758b371f3SBarry Smith } 318858b371f3SBarry Smith 31899b94acceSBarry Smith /*@ 31909b94acceSBarry Smith SNESSetUp - Sets up the internal data structures for the later use 3191272ac6f2SLois Curfman McInnes of a nonlinear solver. 31929b94acceSBarry Smith 3193c3339decSBarry Smith Collective 3194fee21e36SBarry Smith 31952fe279fdSBarry Smith Input Parameter: 3196f6dfbefdSBarry Smith . snes - the `SNES` context 3197c7afd0dbSLois Curfman McInnes 3198dc4c0fb0SBarry Smith Level: advanced 3199dc4c0fb0SBarry Smith 3200f6dfbefdSBarry Smith Note: 3201f6dfbefdSBarry Smith For basic use of the `SNES` solvers the user need not explicitly call 3202f6dfbefdSBarry Smith `SNESSetUp()`, since these actions will automatically occur during 3203f6dfbefdSBarry Smith the call to `SNESSolve()`. However, if one wishes to control this 3204f6dfbefdSBarry Smith phase separately, `SNESSetUp()` should be called after `SNESCreate()` 3205f6dfbefdSBarry Smith and optional routines of the form SNESSetXXX(), but before `SNESSolve()`. 3206272ac6f2SLois Curfman McInnes 32071cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`, `SNESDestroy()` 32089b94acceSBarry Smith @*/ 3209d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUp(SNES snes) 3210d71ae5a4SJacob Faibussowitsch { 32116cab3a1bSJed Brown DM dm; 3212942e3340SBarry Smith DMSNES sdm; 3213c35f09e5SBarry Smith SNESLineSearch linesearch, pclinesearch; 32146e2a1849SPeter Brune void *lsprectx, *lspostctx; 32159b5c1c08SStefano Zampini PetscBool mf_operator, mf; 32169b5c1c08SStefano Zampini Vec f, fpc; 32179b5c1c08SStefano Zampini void *funcctx; 32189b5c1c08SStefano Zampini void *jacctx, *appctx; 32199b5c1c08SStefano Zampini Mat j, jpre; 32206b2b7091SBarry Smith PetscErrorCode (*precheck)(SNESLineSearch, Vec, Vec, PetscBool *, void *); 32216b2b7091SBarry Smith PetscErrorCode (*postcheck)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *); 32228434afd1SBarry Smith SNESFunctionFn *func; 32238434afd1SBarry Smith SNESJacobianFn *jac; 32243a40ed3dSBarry Smith 32253a40ed3dSBarry Smith PetscFunctionBegin; 32260700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 32273ba16761SJacob Faibussowitsch if (snes->setupcalled) PetscFunctionReturn(PETSC_SUCCESS); 3228fc8bc0e3SRichard Tran Mills PetscCall(PetscLogEventBegin(SNES_SetUp, snes, 0, 0, 0)); 32299b94acceSBarry Smith 323048a46eb9SPierre Jolivet if (!((PetscObject)snes)->type_name) PetscCall(SNESSetType(snes, SNESNEWTONLS)); 323185385478SLisandro Dalcin 32329566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &snes->vec_func, NULL, NULL)); 323358c9b817SLisandro Dalcin 32349566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 32359566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 32369566063dSJacob Faibussowitsch PetscCall(SNESSetDefaultComputeJacobian(snes)); 323758b371f3SBarry Smith 323848a46eb9SPierre Jolivet if (!snes->vec_func) PetscCall(DMCreateGlobalVector(dm, &snes->vec_func)); 3239efd51863SBarry Smith 324048a46eb9SPierre Jolivet if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 3241b710008aSBarry Smith 3242d8d34be6SBarry Smith if (snes->linesearch) { 32439566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 32449566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetFunction(snes->linesearch, SNESComputeFunction)); 3245d8d34be6SBarry Smith } 32469e764e56SPeter Brune 32479b5c1c08SStefano Zampini PetscCall(SNESGetUseMatrixFree(snes, &mf_operator, &mf)); 3248b552625fSStefano Zampini if (snes->npc && snes->npcside == PC_LEFT) { 3249172a4300SPeter Brune snes->mf = PETSC_TRUE; 3250172a4300SPeter Brune snes->mf_operator = PETSC_FALSE; 3251172a4300SPeter Brune } 3252d8f46077SPeter Brune 3253efd4aadfSBarry Smith if (snes->npc) { 32546e2a1849SPeter Brune /* copy the DM over */ 32559566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 32569566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes->npc, dm)); 32576e2a1849SPeter Brune 32589566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &f, &func, &funcctx)); 32599566063dSJacob Faibussowitsch PetscCall(VecDuplicate(f, &fpc)); 32609566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes->npc, fpc, func, funcctx)); 32619566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, &j, &jpre, &jac, &jacctx)); 32629566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes->npc, j, jpre, jac, jacctx)); 32639566063dSJacob Faibussowitsch PetscCall(SNESGetApplicationContext(snes, &appctx)); 32649566063dSJacob Faibussowitsch PetscCall(SNESSetApplicationContext(snes->npc, appctx)); 32659b5c1c08SStefano Zampini PetscCall(SNESSetUseMatrixFree(snes->npc, mf_operator, mf)); 32669566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fpc)); 32676e2a1849SPeter Brune 32686e2a1849SPeter Brune /* copy the function pointers over */ 32699566063dSJacob Faibussowitsch PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)snes->npc)); 32706e2a1849SPeter Brune 32716e2a1849SPeter Brune /* default to 1 iteration */ 32729566063dSJacob Faibussowitsch PetscCall(SNESSetTolerances(snes->npc, 0.0, 0.0, 0.0, 1, snes->npc->max_funcs)); 3273efd4aadfSBarry Smith if (snes->npcside == PC_RIGHT) { 32749566063dSJacob Faibussowitsch PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_FINAL_ONLY)); 3275a9936a0cSPeter Brune } else { 32769566063dSJacob Faibussowitsch PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_NONE)); 3277a9936a0cSPeter Brune } 32789566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes->npc)); 32796e2a1849SPeter Brune 32806e2a1849SPeter Brune /* copy the line search context over */ 3281d8d34be6SBarry Smith if (snes->linesearch && snes->npc->linesearch) { 32829566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &linesearch)); 32839566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes->npc, &pclinesearch)); 32849566063dSJacob Faibussowitsch PetscCall(SNESLineSearchGetPreCheck(linesearch, &precheck, &lsprectx)); 32859566063dSJacob Faibussowitsch PetscCall(SNESLineSearchGetPostCheck(linesearch, &postcheck, &lspostctx)); 32869566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetPreCheck(pclinesearch, precheck, lsprectx)); 32879566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetPostCheck(pclinesearch, postcheck, lspostctx)); 32889566063dSJacob Faibussowitsch PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch)); 32896e2a1849SPeter Brune } 3290d8d34be6SBarry Smith } 32911baa6e33SBarry Smith if (snes->mf) PetscCall(SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version)); 32929927e4dfSBarry Smith if (snes->ops->usercompute && !snes->user) PetscCallBack("SNES callback compute application context", (*snes->ops->usercompute)(snes, (void **)&snes->user)); 32936e2a1849SPeter Brune 329437ec4e1aSPeter Brune snes->jac_iter = 0; 329537ec4e1aSPeter Brune snes->pre_iter = 0; 329637ec4e1aSPeter Brune 3297dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, setup); 329858c9b817SLisandro Dalcin 32999566063dSJacob Faibussowitsch PetscCall(SNESSetDefaultComputeJacobian(snes)); 330058b371f3SBarry Smith 3301b552625fSStefano Zampini if (snes->npc && snes->npcside == PC_LEFT) { 33026c67d002SPeter Brune if (snes->functype == SNES_FUNCTION_PRECONDITIONED) { 3303d8d34be6SBarry Smith if (snes->linesearch) { 33049566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &linesearch)); 33059566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunctionDefaultNPC)); 33066c67d002SPeter Brune } 33076c67d002SPeter Brune } 3308d8d34be6SBarry Smith } 3309fc8bc0e3SRichard Tran Mills PetscCall(PetscLogEventEnd(SNES_SetUp, snes, 0, 0, 0)); 33107aaed0d8SBarry Smith snes->setupcalled = PETSC_TRUE; 33113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 33129b94acceSBarry Smith } 33139b94acceSBarry Smith 331437596af1SLisandro Dalcin /*@ 3315f6dfbefdSBarry Smith SNESReset - Resets a `SNES` context to the snessetupcalled = 0 state and removes any allocated `Vec`s and `Mat`s 331637596af1SLisandro Dalcin 3317c3339decSBarry Smith Collective 331837596af1SLisandro Dalcin 331937596af1SLisandro Dalcin Input Parameter: 3320f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 332137596af1SLisandro Dalcin 3322d25893d9SBarry Smith Level: intermediate 3323d25893d9SBarry Smith 332495452b02SPatrick Sanan Notes: 3325f6dfbefdSBarry Smith Call this if you wish to reuse a `SNES` but with different size vectors 332637596af1SLisandro Dalcin 3327f6dfbefdSBarry Smith Also calls the application context destroy routine set with `SNESSetComputeApplicationContext()` 3328f6dfbefdSBarry Smith 33291cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESDestroy()`, `SNESCreate()`, `SNESSetUp()`, `SNESSolve()` 333037596af1SLisandro Dalcin @*/ 3331d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESReset(SNES snes) 3332d71ae5a4SJacob Faibussowitsch { 333337596af1SLisandro Dalcin PetscFunctionBegin; 333437596af1SLisandro Dalcin PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3335d25893d9SBarry Smith if (snes->ops->userdestroy && snes->user) { 33369927e4dfSBarry Smith PetscCallBack("SNES callback destroy application context", (*snes->ops->userdestroy)((void **)&snes->user)); 33370298fd71SBarry Smith snes->user = NULL; 3338d25893d9SBarry Smith } 33391baa6e33SBarry Smith if (snes->npc) PetscCall(SNESReset(snes->npc)); 33408a23116dSBarry Smith 3341dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, reset); 33421baa6e33SBarry Smith if (snes->ksp) PetscCall(KSPReset(snes->ksp)); 33439e764e56SPeter Brune 33441baa6e33SBarry Smith if (snes->linesearch) PetscCall(SNESLineSearchReset(snes->linesearch)); 33459e764e56SPeter Brune 33469566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_rhs)); 33479566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol)); 33489566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol_update)); 33499566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_func)); 33509566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian)); 33519566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian_pre)); 33529566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->picard)); 33539566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(snes->nwork, &snes->work)); 33549566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(snes->nvwork, &snes->vwork)); 3355f5af7f23SKarl Rupp 335640fdac6aSLawrence Mitchell snes->alwayscomputesfinalresidual = PETSC_FALSE; 335740fdac6aSLawrence Mitchell 335837596af1SLisandro Dalcin snes->nwork = snes->nvwork = 0; 335937596af1SLisandro Dalcin snes->setupcalled = PETSC_FALSE; 33603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 336137596af1SLisandro Dalcin } 336237596af1SLisandro Dalcin 336352baeb72SSatish Balay /*@ 3364420bcc1bSBarry Smith SNESConvergedReasonViewCancel - Clears all the reason view functions for a `SNES` object provided with `SNESConvergedReasonViewSet()` 3365c4421ceaSFande Kong 3366c3339decSBarry Smith Collective 3367c4421ceaSFande Kong 3368c4421ceaSFande Kong Input Parameter: 3369f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 3370c4421ceaSFande Kong 3371c4421ceaSFande Kong Level: intermediate 3372c4421ceaSFande Kong 3373420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESReset()`, `SNESConvergedReasonViewSet()` 3374c4421ceaSFande Kong @*/ 3375d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewCancel(SNES snes) 3376d71ae5a4SJacob Faibussowitsch { 3377c4421ceaSFande Kong PetscInt i; 3378c4421ceaSFande Kong 3379c4421ceaSFande Kong PetscFunctionBegin; 3380c4421ceaSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3381c4421ceaSFande Kong for (i = 0; i < snes->numberreasonviews; i++) { 338248a46eb9SPierre Jolivet if (snes->reasonviewdestroy[i]) PetscCall((*snes->reasonviewdestroy[i])(&snes->reasonviewcontext[i])); 3383c4421ceaSFande Kong } 3384c4421ceaSFande Kong snes->numberreasonviews = 0; 33853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3386c4421ceaSFande Kong } 3387c4421ceaSFande Kong 33881fb7b255SJunchao Zhang /*@C 33899b94acceSBarry Smith SNESDestroy - Destroys the nonlinear solver context that was created 3390f6dfbefdSBarry Smith with `SNESCreate()`. 33919b94acceSBarry Smith 3392c3339decSBarry Smith Collective 3393c7afd0dbSLois Curfman McInnes 33949b94acceSBarry Smith Input Parameter: 3395f6dfbefdSBarry Smith . snes - the `SNES` context 33969b94acceSBarry Smith 339736851e7fSLois Curfman McInnes Level: beginner 339836851e7fSLois Curfman McInnes 33991cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()` 34009b94acceSBarry Smith @*/ 3401d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESDestroy(SNES *snes) 3402d71ae5a4SJacob Faibussowitsch { 34033a40ed3dSBarry Smith PetscFunctionBegin; 34043ba16761SJacob Faibussowitsch if (!*snes) PetscFunctionReturn(PETSC_SUCCESS); 3405*f4f49eeaSPierre Jolivet PetscValidHeaderSpecific(*snes, SNES_CLASSID, 1); 3406*f4f49eeaSPierre Jolivet if (--((PetscObject)*snes)->refct > 0) { 34079371c9d4SSatish Balay *snes = NULL; 34083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 34099371c9d4SSatish Balay } 3410d4bb536fSBarry Smith 3411*f4f49eeaSPierre Jolivet PetscCall(SNESReset(*snes)); 34129566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&(*snes)->npc)); 34136b8b9a38SLisandro Dalcin 3414e04113cfSBarry Smith /* if memory was published with SAWs then destroy it */ 34159566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsViewOff((PetscObject)*snes)); 3416*f4f49eeaSPierre Jolivet PetscTryTypeMethod(*snes, destroy); 34176d4c513bSLisandro Dalcin 34189566063dSJacob Faibussowitsch if ((*snes)->dm) PetscCall(DMCoarsenHookRemove((*snes)->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, *snes)); 34199566063dSJacob Faibussowitsch PetscCall(DMDestroy(&(*snes)->dm)); 34209566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&(*snes)->ksp)); 34219566063dSJacob Faibussowitsch PetscCall(SNESLineSearchDestroy(&(*snes)->linesearch)); 34226b8b9a38SLisandro Dalcin 34239566063dSJacob Faibussowitsch PetscCall(PetscFree((*snes)->kspconvctx)); 342448a46eb9SPierre Jolivet if ((*snes)->ops->convergeddestroy) PetscCall((*(*snes)->ops->convergeddestroy)((*snes)->cnvP)); 342548a46eb9SPierre Jolivet if ((*snes)->conv_hist_alloc) PetscCall(PetscFree2((*snes)->conv_hist, (*snes)->conv_hist_its)); 3426*f4f49eeaSPierre Jolivet PetscCall(SNESMonitorCancel(*snes)); 3427*f4f49eeaSPierre Jolivet PetscCall(SNESConvergedReasonViewCancel(*snes)); 34289566063dSJacob Faibussowitsch PetscCall(PetscHeaderDestroy(snes)); 34293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 34309b94acceSBarry Smith } 34319b94acceSBarry Smith 34329b94acceSBarry Smith /* ----------- Routines to set solver parameters ---------- */ 34339b94acceSBarry Smith 3434a8054027SBarry Smith /*@ 3435a8054027SBarry Smith SNESSetLagPreconditioner - Determines when the preconditioner is rebuilt in the nonlinear solve. 3436a8054027SBarry Smith 3437c3339decSBarry Smith Logically Collective 3438a8054027SBarry Smith 3439a8054027SBarry Smith Input Parameters: 3440f6dfbefdSBarry Smith + snes - the `SNES` context 3441d8e291bfSBarry Smith - lag - 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time 34423b4f5425SBarry Smith the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that 3443a8054027SBarry Smith 3444a8054027SBarry Smith Options Database Keys: 3445420bcc1bSBarry Smith + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple `SNESSolve()` 34463d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 3447420bcc1bSBarry Smith . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple `SNESSolve()` 34483d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 3449a8054027SBarry Smith 3450dc4c0fb0SBarry Smith Level: intermediate 3451dc4c0fb0SBarry Smith 3452420bcc1bSBarry Smith Notes: 3453a8054027SBarry Smith The default is 1 3454420bcc1bSBarry Smith 3455f6dfbefdSBarry Smith The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagPreconditionerPersists()` was called 3456d8e291bfSBarry Smith 3457f6dfbefdSBarry Smith `SNESSetLagPreconditionerPersists()` allows using the same uniform lagging (for example every second linear solve) across multiple nonlinear solves. 3458a8054027SBarry Smith 34591cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetLagPreconditionerPersists()`, 3460f6dfbefdSBarry Smith `SNESSetLagJacobianPersists()`, `SNES`, `SNESSolve()` 3461a8054027SBarry Smith @*/ 3462d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditioner(SNES snes, PetscInt lag) 3463d71ae5a4SJacob Faibussowitsch { 3464a8054027SBarry Smith PetscFunctionBegin; 34650700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 34665f80ce2aSJacob Faibussowitsch PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater"); 34675f80ce2aSJacob Faibussowitsch PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0"); 3468c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, lag, 2); 3469a8054027SBarry Smith snes->lagpreconditioner = lag; 34703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3471a8054027SBarry Smith } 3472a8054027SBarry Smith 3473efd51863SBarry Smith /*@ 3474f6dfbefdSBarry Smith SNESSetGridSequence - sets the number of steps of grid sequencing that `SNES` will do 3475efd51863SBarry Smith 3476c3339decSBarry Smith Logically Collective 3477efd51863SBarry Smith 3478efd51863SBarry Smith Input Parameters: 3479f6dfbefdSBarry Smith + snes - the `SNES` context 3480efd51863SBarry Smith - steps - the number of refinements to do, defaults to 0 3481efd51863SBarry Smith 3482f6dfbefdSBarry Smith Options Database Key: 348367b8a455SSatish Balay . -snes_grid_sequence <steps> - Use grid sequencing to generate initial guess 3484efd51863SBarry Smith 3485efd51863SBarry Smith Level: intermediate 3486efd51863SBarry Smith 3487f6dfbefdSBarry Smith Note: 3488f6dfbefdSBarry Smith Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing. 3489c0df2a02SJed Brown 3490420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetGridSequence()`, 3491420bcc1bSBarry Smith `SNESetDM()` 3492efd51863SBarry Smith @*/ 3493d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetGridSequence(SNES snes, PetscInt steps) 3494d71ae5a4SJacob Faibussowitsch { 3495efd51863SBarry Smith PetscFunctionBegin; 3496efd51863SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3497efd51863SBarry Smith PetscValidLogicalCollectiveInt(snes, steps, 2); 3498efd51863SBarry Smith snes->gridsequence = steps; 34993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3500efd51863SBarry Smith } 3501efd51863SBarry Smith 3502fa19ca70SBarry Smith /*@ 3503f6dfbefdSBarry Smith SNESGetGridSequence - gets the number of steps of grid sequencing that `SNES` will do 3504fa19ca70SBarry Smith 3505c3339decSBarry Smith Logically Collective 3506fa19ca70SBarry Smith 3507fa19ca70SBarry Smith Input Parameter: 3508f6dfbefdSBarry Smith . snes - the `SNES` context 3509fa19ca70SBarry Smith 3510fa19ca70SBarry Smith Output Parameter: 3511fa19ca70SBarry Smith . steps - the number of refinements to do, defaults to 0 3512fa19ca70SBarry Smith 3513fa19ca70SBarry Smith Level: intermediate 3514fa19ca70SBarry Smith 35151cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetGridSequence()` 3516fa19ca70SBarry Smith @*/ 3517d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetGridSequence(SNES snes, PetscInt *steps) 3518d71ae5a4SJacob Faibussowitsch { 3519fa19ca70SBarry Smith PetscFunctionBegin; 3520fa19ca70SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3521fa19ca70SBarry Smith *steps = snes->gridsequence; 35223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3523fa19ca70SBarry Smith } 3524fa19ca70SBarry Smith 3525a8054027SBarry Smith /*@ 3526f6dfbefdSBarry Smith SNESGetLagPreconditioner - Return how often the preconditioner is rebuilt 3527a8054027SBarry Smith 35283f9fe445SBarry Smith Not Collective 3529a8054027SBarry Smith 3530a8054027SBarry Smith Input Parameter: 3531f6dfbefdSBarry Smith . snes - the `SNES` context 3532a8054027SBarry Smith 3533a8054027SBarry Smith Output Parameter: 3534a8054027SBarry 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 35353b4f5425SBarry Smith the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that 3536a8054027SBarry Smith 3537dc4c0fb0SBarry Smith Level: intermediate 3538dc4c0fb0SBarry Smith 3539a8054027SBarry Smith Notes: 3540a8054027SBarry Smith The default is 1 3541f6dfbefdSBarry Smith 3542a8054027SBarry Smith The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 3543a8054027SBarry Smith 35441cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3545a8054027SBarry Smith @*/ 3546d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagPreconditioner(SNES snes, PetscInt *lag) 3547d71ae5a4SJacob Faibussowitsch { 3548a8054027SBarry Smith PetscFunctionBegin; 35490700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3550a8054027SBarry Smith *lag = snes->lagpreconditioner; 35513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3552a8054027SBarry Smith } 3553a8054027SBarry Smith 3554e35cf81dSBarry Smith /*@ 3555f6dfbefdSBarry Smith SNESSetLagJacobian - Set when the Jacobian is rebuilt in the nonlinear solve. See `SNESSetLagPreconditioner()` for determining how 3556e35cf81dSBarry Smith often the preconditioner is rebuilt. 3557e35cf81dSBarry Smith 3558c3339decSBarry Smith Logically Collective 3559e35cf81dSBarry Smith 3560e35cf81dSBarry Smith Input Parameters: 3561f6dfbefdSBarry Smith + snes - the `SNES` context 3562e35cf81dSBarry 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 3563fe3ffe1eSBarry Smith the Jacobian is built etc. -2 means rebuild at next chance but then never again 3564e35cf81dSBarry Smith 3565e35cf81dSBarry Smith Options Database Keys: 356679a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 35673d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 356879a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 35693d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag. 3570e35cf81dSBarry Smith 3571dc4c0fb0SBarry Smith Level: intermediate 3572dc4c0fb0SBarry Smith 3573e35cf81dSBarry Smith Notes: 3574e35cf81dSBarry Smith The default is 1 3575f6dfbefdSBarry Smith 3576e35cf81dSBarry Smith The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 3577f6dfbefdSBarry Smith 3578fe3ffe1eSBarry 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 3579fe3ffe1eSBarry Smith at the next Newton step but never again (unless it is reset to another value) 3580e35cf81dSBarry Smith 35811cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagPreconditioner()`, `SNESGetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3582e35cf81dSBarry Smith @*/ 3583d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobian(SNES snes, PetscInt lag) 3584d71ae5a4SJacob Faibussowitsch { 3585e35cf81dSBarry Smith PetscFunctionBegin; 35860700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 35875f80ce2aSJacob Faibussowitsch PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater"); 35885f80ce2aSJacob Faibussowitsch PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0"); 3589c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, lag, 2); 3590e35cf81dSBarry Smith snes->lagjacobian = lag; 35913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3592e35cf81dSBarry Smith } 3593e35cf81dSBarry Smith 3594e35cf81dSBarry Smith /*@ 3595f6dfbefdSBarry Smith SNESGetLagJacobian - Get how often the Jacobian is rebuilt. See `SNESGetLagPreconditioner()` to determine when the preconditioner is rebuilt 3596e35cf81dSBarry Smith 35973f9fe445SBarry Smith Not Collective 3598e35cf81dSBarry Smith 3599e35cf81dSBarry Smith Input Parameter: 3600f6dfbefdSBarry Smith . snes - the `SNES` context 3601e35cf81dSBarry Smith 3602e35cf81dSBarry Smith Output Parameter: 3603e35cf81dSBarry 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 3604e35cf81dSBarry Smith the Jacobian is built etc. 3605e35cf81dSBarry Smith 3606dc4c0fb0SBarry Smith Level: intermediate 3607dc4c0fb0SBarry Smith 3608e35cf81dSBarry Smith Notes: 3609e35cf81dSBarry Smith The default is 1 3610f6dfbefdSBarry Smith 3611f6dfbefdSBarry Smith The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagJacobianPersists()` was called. 3612e35cf81dSBarry Smith 36131cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetLagJacobian()`, `SNESSetLagPreconditioner()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3614e35cf81dSBarry Smith 3615e35cf81dSBarry Smith @*/ 3616d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagJacobian(SNES snes, PetscInt *lag) 3617d71ae5a4SJacob Faibussowitsch { 3618e35cf81dSBarry Smith PetscFunctionBegin; 36190700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3620e35cf81dSBarry Smith *lag = snes->lagjacobian; 36213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3622e35cf81dSBarry Smith } 3623e35cf81dSBarry Smith 362437ec4e1aSPeter Brune /*@ 3625f6dfbefdSBarry Smith SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple nonlinear solves 362637ec4e1aSPeter Brune 3627c3339decSBarry Smith Logically collective 362837ec4e1aSPeter Brune 3629d8d19677SJose E. Roman Input Parameters: 3630f6dfbefdSBarry Smith + snes - the `SNES` context 36319d7e2deaSPeter Brune - flg - jacobian lagging persists if true 363237ec4e1aSPeter Brune 363337ec4e1aSPeter Brune Options Database Keys: 363479a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 36353d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 363679a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 36373d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 36383d5a8a6aSBarry Smith 3639dc4c0fb0SBarry Smith Level: advanced 3640dc4c0fb0SBarry Smith 364195452b02SPatrick Sanan Notes: 3642420bcc1bSBarry Smith Normally when `SNESSetLagJacobian()` is used, the Jacobian is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior 3643f6dfbefdSBarry Smith 364495452b02SPatrick Sanan This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by 364537ec4e1aSPeter Brune several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several 364637ec4e1aSPeter Brune timesteps may present huge efficiency gains. 364737ec4e1aSPeter Brune 364842747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditionerPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()` 364937ec4e1aSPeter Brune @*/ 3650d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobianPersists(SNES snes, PetscBool flg) 3651d71ae5a4SJacob Faibussowitsch { 365237ec4e1aSPeter Brune PetscFunctionBegin; 365337ec4e1aSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 365437ec4e1aSPeter Brune PetscValidLogicalCollectiveBool(snes, flg, 2); 365537ec4e1aSPeter Brune snes->lagjac_persist = flg; 36563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 365737ec4e1aSPeter Brune } 365837ec4e1aSPeter Brune 365937ec4e1aSPeter Brune /*@ 3660d8e291bfSBarry Smith SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple nonlinear solves 366137ec4e1aSPeter Brune 3662c3339decSBarry Smith Logically Collective 366337ec4e1aSPeter Brune 3664d8d19677SJose E. Roman Input Parameters: 3665f6dfbefdSBarry Smith + snes - the `SNES` context 36669d7e2deaSPeter Brune - flg - preconditioner lagging persists if true 366737ec4e1aSPeter Brune 366837ec4e1aSPeter Brune Options Database Keys: 366979a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 36703d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 367179a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 36723d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 367337ec4e1aSPeter Brune 3674dc4c0fb0SBarry Smith Level: developer 3675dc4c0fb0SBarry Smith 367695452b02SPatrick Sanan Notes: 3677420bcc1bSBarry Smith Normally when `SNESSetLagPreconditioner()` is used, the preconditioner is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior 3678f6dfbefdSBarry Smith 367995452b02SPatrick Sanan This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale 368037ec4e1aSPeter Brune by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over 368137ec4e1aSPeter Brune several timesteps may present huge efficiency gains. 368237ec4e1aSPeter Brune 36831cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobianPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagPreconditioner()` 368437ec4e1aSPeter Brune @*/ 3685d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes, PetscBool flg) 3686d71ae5a4SJacob Faibussowitsch { 368737ec4e1aSPeter Brune PetscFunctionBegin; 368837ec4e1aSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 368937ec4e1aSPeter Brune PetscValidLogicalCollectiveBool(snes, flg, 2); 369037ec4e1aSPeter Brune snes->lagpre_persist = flg; 36913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 369237ec4e1aSPeter Brune } 369337ec4e1aSPeter Brune 36949b94acceSBarry Smith /*@ 3695f6dfbefdSBarry Smith SNESSetForceIteration - force `SNESSolve()` to take at least one iteration regardless of the initial residual norm 3696be5caee7SBarry Smith 3697c3339decSBarry Smith Logically Collective 3698be5caee7SBarry Smith 3699be5caee7SBarry Smith Input Parameters: 3700f6dfbefdSBarry Smith + snes - the `SNES` context 3701f6dfbefdSBarry Smith - force - `PETSC_TRUE` require at least one iteration 3702be5caee7SBarry Smith 3703f6dfbefdSBarry Smith Options Database Key: 3704be5caee7SBarry Smith . -snes_force_iteration <force> - Sets forcing an iteration 3705be5caee7SBarry Smith 3706dc4c0fb0SBarry Smith Level: intermediate 3707dc4c0fb0SBarry Smith 3708f6dfbefdSBarry Smith Note: 3709f6dfbefdSBarry Smith This is used sometimes with `TS` to prevent `TS` from detecting a false steady state solution 3710be5caee7SBarry Smith 37111cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `TS`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()` 3712be5caee7SBarry Smith @*/ 3713d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetForceIteration(SNES snes, PetscBool force) 3714d71ae5a4SJacob Faibussowitsch { 3715be5caee7SBarry Smith PetscFunctionBegin; 3716be5caee7SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3717be5caee7SBarry Smith snes->forceiteration = force; 37183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3719be5caee7SBarry Smith } 3720be5caee7SBarry Smith 372185216dc7SFande Kong /*@ 3722f6dfbefdSBarry Smith SNESGetForceIteration - Check whether or not `SNESSolve()` take at least one iteration regardless of the initial residual norm 372385216dc7SFande Kong 3724c3339decSBarry Smith Logically Collective 372585216dc7SFande Kong 37262fe279fdSBarry Smith Input Parameter: 3727f6dfbefdSBarry Smith . snes - the `SNES` context 372885216dc7SFande Kong 372985216dc7SFande Kong Output Parameter: 3730dc4c0fb0SBarry Smith . force - `PETSC_TRUE` requires at least one iteration. 373185216dc7SFande Kong 373206dd6b0eSSatish Balay Level: intermediate 373306dd6b0eSSatish Balay 37341cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetForceIteration()`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()` 373585216dc7SFande Kong @*/ 3736d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetForceIteration(SNES snes, PetscBool *force) 3737d71ae5a4SJacob Faibussowitsch { 373885216dc7SFande Kong PetscFunctionBegin; 373985216dc7SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 374085216dc7SFande Kong *force = snes->forceiteration; 37413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 374285216dc7SFande Kong } 3743be5caee7SBarry Smith 3744be5caee7SBarry Smith /*@ 3745f6dfbefdSBarry Smith SNESSetTolerances - Sets `SNES` various parameters used in convergence tests. 37469b94acceSBarry Smith 3747c3339decSBarry Smith Logically Collective 3748c7afd0dbSLois Curfman McInnes 37499b94acceSBarry Smith Input Parameters: 3750f6dfbefdSBarry Smith + snes - the `SNES` context 375170441072SBarry Smith . abstol - absolute convergence tolerance 375233174efeSLois Curfman McInnes . rtol - relative convergence tolerance 37535358d0d4SBarry Smith . stol - convergence tolerance in terms of the norm of the change in the solution between steps, || delta x || < stol*|| x || 3754f6dfbefdSBarry Smith . maxit - maximum number of iterations, default 50. 3755f6dfbefdSBarry Smith - maxf - maximum number of function evaluations (-1 indicates no limit), default 1000 3756fee21e36SBarry Smith 375733174efeSLois Curfman McInnes Options Database Keys: 375870441072SBarry Smith + -snes_atol <abstol> - Sets abstol 3759c7afd0dbSLois Curfman McInnes . -snes_rtol <rtol> - Sets rtol 3760c7afd0dbSLois Curfman McInnes . -snes_stol <stol> - Sets stol 3761c7afd0dbSLois Curfman McInnes . -snes_max_it <maxit> - Sets maxit 3762c7afd0dbSLois Curfman McInnes - -snes_max_funcs <maxf> - Sets maxf 37639b94acceSBarry Smith 376436851e7fSLois Curfman McInnes Level: intermediate 376536851e7fSLois Curfman McInnes 376600677de2SStefano Zampini .seealso: [](ch_snes), `SNESSolve()`, `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()`, `SNESSetForceIteration()` 37679b94acceSBarry Smith @*/ 3768d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTolerances(SNES snes, PetscReal abstol, PetscReal rtol, PetscReal stol, PetscInt maxit, PetscInt maxf) 3769d71ae5a4SJacob Faibussowitsch { 37703a40ed3dSBarry Smith PetscFunctionBegin; 37710700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3772c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, abstol, 2); 3773c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, rtol, 3); 3774c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, stol, 4); 3775c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, maxit, 5); 3776c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, maxf, 6); 3777c5eb9154SBarry Smith 377813bcc0bdSJacob Faibussowitsch if (abstol != (PetscReal)PETSC_DEFAULT) { 37795f80ce2aSJacob Faibussowitsch PetscCheck(abstol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)abstol); 3780ab54825eSJed Brown snes->abstol = abstol; 3781ab54825eSJed Brown } 378213bcc0bdSJacob Faibussowitsch if (rtol != (PetscReal)PETSC_DEFAULT) { 37835f80ce2aSJacob 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); 3784ab54825eSJed Brown snes->rtol = rtol; 3785ab54825eSJed Brown } 378613bcc0bdSJacob Faibussowitsch if (stol != (PetscReal)PETSC_DEFAULT) { 37875f80ce2aSJacob Faibussowitsch PetscCheck(stol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Step tolerance %g must be non-negative", (double)stol); 3788c60f73f4SPeter Brune snes->stol = stol; 3789ab54825eSJed Brown } 3790ab54825eSJed Brown if (maxit != PETSC_DEFAULT) { 379163a3b9bcSJacob Faibussowitsch PetscCheck(maxit >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", maxit); 3792ab54825eSJed Brown snes->max_its = maxit; 3793ab54825eSJed Brown } 3794ab54825eSJed Brown if (maxf != PETSC_DEFAULT) { 379563a3b9bcSJacob Faibussowitsch PetscCheck(maxf >= -1, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations %" PetscInt_FMT " must be -1 or nonnegative", maxf); 3796ab54825eSJed Brown snes->max_funcs = maxf; 3797ab54825eSJed Brown } 379888976e71SPeter Brune snes->tolerancesset = PETSC_TRUE; 37993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 38009b94acceSBarry Smith } 38019b94acceSBarry Smith 3802e4d06f11SPatrick Farrell /*@ 3803f6dfbefdSBarry Smith SNESSetDivergenceTolerance - Sets the divergence tolerance used for the `SNES` divergence test. 3804e4d06f11SPatrick Farrell 3805c3339decSBarry Smith Logically Collective 3806e4d06f11SPatrick Farrell 3807e4d06f11SPatrick Farrell Input Parameters: 3808f6dfbefdSBarry Smith + snes - the `SNES` context 3809f6dfbefdSBarry Smith - divtol - the divergence tolerance. Use -1 to deactivate the test, default is 1e4 3810e4d06f11SPatrick Farrell 3811f6dfbefdSBarry Smith Options Database Key: 3812dc4c0fb0SBarry Smith . -snes_divergence_tolerance <divtol> - Sets `divtol` 3813e4d06f11SPatrick Farrell 3814e4d06f11SPatrick Farrell Level: intermediate 3815e4d06f11SPatrick Farrell 38161cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetTolerances()`, `SNESGetDivergenceTolerance` 3817e4d06f11SPatrick Farrell @*/ 3818d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDivergenceTolerance(SNES snes, PetscReal divtol) 3819d71ae5a4SJacob Faibussowitsch { 3820e4d06f11SPatrick Farrell PetscFunctionBegin; 3821e4d06f11SPatrick Farrell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3822e4d06f11SPatrick Farrell PetscValidLogicalCollectiveReal(snes, divtol, 2); 3823e4d06f11SPatrick Farrell 382413bcc0bdSJacob Faibussowitsch if (divtol != (PetscReal)PETSC_DEFAULT) { 3825e4d06f11SPatrick Farrell snes->divtol = divtol; 38269371c9d4SSatish Balay } else { 3827e4d06f11SPatrick Farrell snes->divtol = 1.0e4; 3828e4d06f11SPatrick Farrell } 38293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3830e4d06f11SPatrick Farrell } 3831e4d06f11SPatrick Farrell 38329b94acceSBarry Smith /*@ 383333174efeSLois Curfman McInnes SNESGetTolerances - Gets various parameters used in convergence tests. 383433174efeSLois Curfman McInnes 3835c7afd0dbSLois Curfman McInnes Not Collective 3836c7afd0dbSLois Curfman McInnes 383733174efeSLois Curfman McInnes Input Parameters: 3838f6dfbefdSBarry Smith + snes - the `SNES` context 383985385478SLisandro Dalcin . atol - absolute convergence tolerance 384033174efeSLois Curfman McInnes . rtol - relative convergence tolerance 384133174efeSLois Curfman McInnes . stol - convergence tolerance in terms of the norm 384233174efeSLois Curfman McInnes of the change in the solution between steps 384333174efeSLois Curfman McInnes . maxit - maximum number of iterations 3844c7afd0dbSLois Curfman McInnes - maxf - maximum number of function evaluations 3845fee21e36SBarry Smith 384636851e7fSLois Curfman McInnes Level: intermediate 384736851e7fSLois Curfman McInnes 3848dc4c0fb0SBarry Smith Note: 3849dc4c0fb0SBarry Smith The user can specify `NULL` for any parameter that is not needed. 3850dc4c0fb0SBarry Smith 38511cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTolerances()` 385233174efeSLois Curfman McInnes @*/ 3853d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetTolerances(SNES snes, PetscReal *atol, PetscReal *rtol, PetscReal *stol, PetscInt *maxit, PetscInt *maxf) 3854d71ae5a4SJacob Faibussowitsch { 38553a40ed3dSBarry Smith PetscFunctionBegin; 38560700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 385785385478SLisandro Dalcin if (atol) *atol = snes->abstol; 385833174efeSLois Curfman McInnes if (rtol) *rtol = snes->rtol; 3859c60f73f4SPeter Brune if (stol) *stol = snes->stol; 386033174efeSLois Curfman McInnes if (maxit) *maxit = snes->max_its; 386133174efeSLois Curfman McInnes if (maxf) *maxf = snes->max_funcs; 38623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 386333174efeSLois Curfman McInnes } 386433174efeSLois Curfman McInnes 3865e4d06f11SPatrick Farrell /*@ 3866e4d06f11SPatrick Farrell SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test. 3867e4d06f11SPatrick Farrell 3868e4d06f11SPatrick Farrell Not Collective 3869e4d06f11SPatrick Farrell 3870e4d06f11SPatrick Farrell Input Parameters: 3871f6dfbefdSBarry Smith + snes - the `SNES` context 3872e4d06f11SPatrick Farrell - divtol - divergence tolerance 3873e4d06f11SPatrick Farrell 3874e4d06f11SPatrick Farrell Level: intermediate 3875e4d06f11SPatrick Farrell 38761cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetDivergenceTolerance()` 3877e4d06f11SPatrick Farrell @*/ 3878d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDivergenceTolerance(SNES snes, PetscReal *divtol) 3879d71ae5a4SJacob Faibussowitsch { 3880e4d06f11SPatrick Farrell PetscFunctionBegin; 3881e4d06f11SPatrick Farrell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3882e4d06f11SPatrick Farrell if (divtol) *divtol = snes->divtol; 38833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3884e4d06f11SPatrick Farrell } 3885e4d06f11SPatrick Farrell 388633174efeSLois Curfman McInnes /*@ 38879b94acceSBarry Smith SNESSetTrustRegionTolerance - Sets the trust region parameter tolerance. 38889b94acceSBarry Smith 3889c3339decSBarry Smith Logically Collective 3890fee21e36SBarry Smith 3891c7afd0dbSLois Curfman McInnes Input Parameters: 3892f6dfbefdSBarry Smith + snes - the `SNES` context 3893c7afd0dbSLois Curfman McInnes - tol - tolerance 3894c7afd0dbSLois Curfman McInnes 38959b94acceSBarry Smith Options Database Key: 38964a221d59SStefano Zampini . -snes_tr_tol <tol> - Sets tol 38979b94acceSBarry Smith 389836851e7fSLois Curfman McInnes Level: intermediate 389936851e7fSLois Curfman McInnes 39009bcc50f1SBarry Smith Developer Note: 39019bcc50f1SBarry Smith Should be SNESTrustRegionSetTolerance() 39029bcc50f1SBarry Smith 39031cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNEWTONTR`, `SNESSetTolerances()` 39049b94acceSBarry Smith @*/ 3905d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTrustRegionTolerance(SNES snes, PetscReal tol) 3906d71ae5a4SJacob Faibussowitsch { 39073a40ed3dSBarry Smith PetscFunctionBegin; 39080700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3909c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, tol, 2); 39109b94acceSBarry Smith snes->deltatol = tol; 39113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 39129b94acceSBarry Smith } 39139b94acceSBarry Smith 39146ba87a44SLisandro Dalcin PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *); 39156ba87a44SLisandro Dalcin 3916d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorLGRange(SNES snes, PetscInt n, PetscReal rnorm, void *monctx) 3917d71ae5a4SJacob Faibussowitsch { 3918b271bb04SBarry Smith PetscDrawLG lg; 3919b271bb04SBarry Smith PetscReal x, y, per; 3920b271bb04SBarry Smith PetscViewer v = (PetscViewer)monctx; 3921b271bb04SBarry Smith static PetscReal prev; /* should be in the context */ 3922b271bb04SBarry Smith PetscDraw draw; 3923b271bb04SBarry Smith 3924459f5d12SBarry Smith PetscFunctionBegin; 39254d4332d5SBarry Smith PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 4); 39269566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 0, &lg)); 39279566063dSJacob Faibussowitsch if (!n) PetscCall(PetscDrawLGReset(lg)); 39289566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 39299566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "Residual norm")); 3930b271bb04SBarry Smith x = (PetscReal)n; 393177b4d14cSPeter Brune if (rnorm > 0.0) y = PetscLog10Real(rnorm); 393294c9c6d3SKarl Rupp else y = -15.0; 39339566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 39346934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 39359566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 39369566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 3937b271bb04SBarry Smith } 3938b271bb04SBarry Smith 39399566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 1, &lg)); 39409566063dSJacob Faibussowitsch if (!n) PetscCall(PetscDrawLGReset(lg)); 39419566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 3942aaa8cc7dSPierre Jolivet PetscCall(PetscDrawSetTitle(draw, "% elements > .2*max element")); 39439566063dSJacob Faibussowitsch PetscCall(SNESMonitorRange_Private(snes, n, &per)); 3944b271bb04SBarry Smith x = (PetscReal)n; 3945b271bb04SBarry Smith y = 100.0 * per; 39469566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 39476934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 39489566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 39499566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 3950b271bb04SBarry Smith } 3951b271bb04SBarry Smith 39529566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 2, &lg)); 39539371c9d4SSatish Balay if (!n) { 39549371c9d4SSatish Balay prev = rnorm; 39559371c9d4SSatish Balay PetscCall(PetscDrawLGReset(lg)); 39569371c9d4SSatish Balay } 39579566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 39589566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm")); 3959b271bb04SBarry Smith x = (PetscReal)n; 3960b271bb04SBarry Smith y = (prev - rnorm) / prev; 39619566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 39626934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 39639566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 39649566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 3965b271bb04SBarry Smith } 3966b271bb04SBarry Smith 39679566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 3, &lg)); 39689566063dSJacob Faibussowitsch if (!n) PetscCall(PetscDrawLGReset(lg)); 39699566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 39709566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm*(% > .2 max)")); 3971b271bb04SBarry Smith x = (PetscReal)n; 3972b271bb04SBarry Smith y = (prev - rnorm) / (prev * per); 3973b271bb04SBarry Smith if (n > 2) { /*skip initial crazy value */ 39749566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 3975b271bb04SBarry Smith } 39766934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 39779566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 39789566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 3979b271bb04SBarry Smith } 3980b271bb04SBarry Smith prev = rnorm; 39813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3982b271bb04SBarry Smith } 3983b271bb04SBarry Smith 3984228d79bcSJed Brown /*@ 39852d157150SStefano Zampini SNESConverged - Run the convergence test and update the `SNESConvergedReason`. 39862d157150SStefano Zampini 39872d157150SStefano Zampini Collective 39882d157150SStefano Zampini 39892d157150SStefano Zampini Input Parameters: 39902d157150SStefano Zampini + snes - the `SNES` context 39912d157150SStefano Zampini . it - current iteration 39922d157150SStefano Zampini . xnorm - 2-norm of current iterate 39932d157150SStefano Zampini . snorm - 2-norm of current step 39942d157150SStefano Zampini - fnorm - 2-norm of function 39952d157150SStefano Zampini 39962d157150SStefano Zampini Level: developer 39972d157150SStefano Zampini 39982d157150SStefano Zampini Note: 3999420bcc1bSBarry Smith This routine is called by the `SNESSolve()` implementations. 40002d157150SStefano Zampini It does not typically need to be called by the user. 40012d157150SStefano Zampini 4002be50c303SSatish Balay .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`, `SNESGetConvergenceTest()` 40032d157150SStefano Zampini @*/ 40042d157150SStefano Zampini PetscErrorCode SNESConverged(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm) 40052d157150SStefano Zampini { 40062d157150SStefano Zampini PetscFunctionBegin; 40072d157150SStefano Zampini if (!snes->reason) { 40082d157150SStefano Zampini if (snes->normschedule == SNES_NORM_ALWAYS) PetscUseTypeMethod(snes, converged, it, xnorm, snorm, fnorm, &snes->reason, snes->cnvP); 40092d157150SStefano Zampini if (it == snes->max_its && !snes->reason) { 40102d157150SStefano Zampini if (snes->normschedule == SNES_NORM_ALWAYS) { 40112d157150SStefano Zampini PetscCall(PetscInfo(snes, "Maximum number of iterations has been reached: %" PetscInt_FMT "\n", snes->max_its)); 40122d157150SStefano Zampini snes->reason = SNES_DIVERGED_MAX_IT; 40132d157150SStefano Zampini } else snes->reason = SNES_CONVERGED_ITS; 40142d157150SStefano Zampini } 40152d157150SStefano Zampini } 40162d157150SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 40172d157150SStefano Zampini } 40182d157150SStefano Zampini 40192d157150SStefano Zampini /*@ 4020228d79bcSJed Brown SNESMonitor - runs the user provided monitor routines, if they exist 4021228d79bcSJed Brown 4022c3339decSBarry Smith Collective 4023228d79bcSJed Brown 4024228d79bcSJed Brown Input Parameters: 4025f6dfbefdSBarry Smith + snes - nonlinear solver context obtained from `SNESCreate()` 4026228d79bcSJed Brown . iter - iteration number 4027228d79bcSJed Brown - rnorm - relative norm of the residual 4028228d79bcSJed Brown 4029dc4c0fb0SBarry Smith Level: developer 4030dc4c0fb0SBarry Smith 4031f6dfbefdSBarry Smith Note: 4032420bcc1bSBarry Smith This routine is called by the `SNESSolve()` implementations. 4033228d79bcSJed Brown It does not typically need to be called by the user. 4034228d79bcSJed Brown 40351cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorSet()` 4036228d79bcSJed Brown @*/ 4037d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitor(SNES snes, PetscInt iter, PetscReal rnorm) 4038d71ae5a4SJacob Faibussowitsch { 40397a03ce2fSLisandro Dalcin PetscInt i, n = snes->numbermonitors; 40407a03ce2fSLisandro Dalcin 40417a03ce2fSLisandro Dalcin PetscFunctionBegin; 40425f3c5e7aSBarry Smith if (n > 0) SNESCheckFunctionNorm(snes, rnorm); 40439566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(snes->vec_sol)); 404448a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall((*snes->monitor[i])(snes, iter, rnorm, snes->monitorcontext[i])); 40459566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(snes->vec_sol)); 40463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 40477a03ce2fSLisandro Dalcin } 40487a03ce2fSLisandro Dalcin 40499b94acceSBarry Smith /* ------------ Routines to set performance monitoring options ----------- */ 40509b94acceSBarry Smith 4051bf388a1fSBarry Smith /*MC 4052f6dfbefdSBarry Smith SNESMonitorFunction - functional form passed to `SNESMonitorSet()` to monitor convergence of nonlinear solver 4053bf388a1fSBarry Smith 4054bf388a1fSBarry Smith Synopsis: 4055aaa7dc30SBarry Smith #include <petscsnes.h> 405637fdd005SBarry Smith PetscErrorCode SNESMonitorFunction(SNES snes, PetscInt its, PetscReal norm, void *mctx) 4057bf388a1fSBarry Smith 4058c3339decSBarry Smith Collective 40591843f636SBarry Smith 40601843f636SBarry Smith Input Parameters: 4061f6dfbefdSBarry Smith + snes - the `SNES` context 4062bf388a1fSBarry Smith . its - iteration number 4063bf388a1fSBarry Smith . norm - 2-norm function value (may be estimated) 4064bf388a1fSBarry Smith - mctx - [optional] monitoring context 4065bf388a1fSBarry Smith 4066878cb397SSatish Balay Level: advanced 4067878cb397SSatish Balay 40681cc06b55SBarry Smith .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSet()`, `SNESMonitorGet()` 4069bf388a1fSBarry Smith M*/ 4070bf388a1fSBarry Smith 40719b94acceSBarry Smith /*@C 4072a6570f20SBarry Smith SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every 40739b94acceSBarry Smith iteration of the nonlinear solver to display the iteration's 40749b94acceSBarry Smith progress. 40759b94acceSBarry Smith 4076c3339decSBarry Smith Logically Collective 4077fee21e36SBarry Smith 4078c7afd0dbSLois Curfman McInnes Input Parameters: 4079f6dfbefdSBarry Smith + snes - the `SNES` context 408020f4b53cSBarry Smith . f - the monitor function, for the calling sequence see `SNESMonitorFunction` 4081420bcc1bSBarry Smith . mctx - [optional] user-defined context for private data for the monitor routine (use `NULL` if no context is desired) 4082dc4c0fb0SBarry Smith - monitordestroy - [optional] routine that frees monitor context (may be `NULL`) 40839b94acceSBarry Smith 40849665c990SLois Curfman McInnes Options Database Keys: 4085f6dfbefdSBarry Smith + -snes_monitor - sets `SNESMonitorDefault()` 4086798534f6SMatthew G. Knepley . -snes_monitor draw::draw_lg - sets line graph monitor, 4087dc4c0fb0SBarry 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 4088c7afd0dbSLois Curfman McInnes the options database. 40899665c990SLois Curfman McInnes 4090dc4c0fb0SBarry Smith Level: intermediate 4091dc4c0fb0SBarry Smith 4092f6dfbefdSBarry Smith Note: 40936bc08f3fSLois Curfman McInnes Several different monitoring routines may be set by calling 4094f6dfbefdSBarry Smith `SNESMonitorSet()` multiple times; all will be called in the 40956bc08f3fSLois Curfman McInnes order in which they were set. 4096639f9d9dSBarry Smith 4097420bcc1bSBarry Smith Fortran Note: 4098f6dfbefdSBarry Smith Only a single monitor function can be set for each `SNES` object 4099025f1a04SBarry Smith 41001cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESMonitorDefault()`, `SNESMonitorCancel()`, `SNESMonitorFunction` 41019b94acceSBarry Smith @*/ 4102d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorSet(SNES snes, PetscErrorCode (*f)(SNES, PetscInt, PetscReal, void *), void *mctx, PetscErrorCode (*monitordestroy)(void **)) 4103d71ae5a4SJacob Faibussowitsch { 4104b90d0a6eSBarry Smith PetscInt i; 410578064530SBarry Smith PetscBool identical; 4106b90d0a6eSBarry Smith 41073a40ed3dSBarry Smith PetscFunctionBegin; 41080700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4109b90d0a6eSBarry Smith for (i = 0; i < snes->numbermonitors; i++) { 41109566063dSJacob Faibussowitsch PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, mctx, monitordestroy, (PetscErrorCode(*)(void))snes->monitor[i], snes->monitorcontext[i], snes->monitordestroy[i], &identical)); 41113ba16761SJacob Faibussowitsch if (identical) PetscFunctionReturn(PETSC_SUCCESS); 4112649052a6SBarry Smith } 41135f80ce2aSJacob Faibussowitsch PetscCheck(snes->numbermonitors < MAXSNESMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set"); 41146e4dcb14SBarry Smith snes->monitor[snes->numbermonitors] = f; 4115b8a78c4aSBarry Smith snes->monitordestroy[snes->numbermonitors] = monitordestroy; 4116639f9d9dSBarry Smith snes->monitorcontext[snes->numbermonitors++] = (void *)mctx; 41173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 41189b94acceSBarry Smith } 41199b94acceSBarry Smith 4120a278d85bSSatish Balay /*@ 4121f6dfbefdSBarry Smith SNESMonitorCancel - Clears all the monitor functions for a `SNES` object. 41225cd90555SBarry Smith 4123c3339decSBarry Smith Logically Collective 4124c7afd0dbSLois Curfman McInnes 41252fe279fdSBarry Smith Input Parameter: 4126f6dfbefdSBarry Smith . snes - the `SNES` context 41275cd90555SBarry Smith 41281a480d89SAdministrator Options Database Key: 4129a6570f20SBarry Smith . -snes_monitor_cancel - cancels all monitors that have been hardwired 4130dc4c0fb0SBarry Smith into a code by calls to `SNESMonitorSet()`, but does not cancel those 4131c7afd0dbSLois Curfman McInnes set via the options database 41325cd90555SBarry Smith 4133dc4c0fb0SBarry Smith Level: intermediate 4134dc4c0fb0SBarry Smith 4135f6dfbefdSBarry Smith Note: 4136f6dfbefdSBarry Smith There is no way to clear one specific monitor from a `SNES` object. 41375cd90555SBarry Smith 41381cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorGet()`, `SNESMonitorDefault()`, `SNESMonitorSet()` 41395cd90555SBarry Smith @*/ 4140d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorCancel(SNES snes) 4141d71ae5a4SJacob Faibussowitsch { 4142d952e501SBarry Smith PetscInt i; 4143d952e501SBarry Smith 41445cd90555SBarry Smith PetscFunctionBegin; 41450700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4146d952e501SBarry Smith for (i = 0; i < snes->numbermonitors; i++) { 414748a46eb9SPierre Jolivet if (snes->monitordestroy[i]) PetscCall((*snes->monitordestroy[i])(&snes->monitorcontext[i])); 4148d952e501SBarry Smith } 41495cd90555SBarry Smith snes->numbermonitors = 0; 41503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 41515cd90555SBarry Smith } 41525cd90555SBarry Smith 4153bf388a1fSBarry Smith /*MC 4154bf388a1fSBarry Smith SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver 4155bf388a1fSBarry Smith 4156bf388a1fSBarry Smith Synopsis: 4157aaa7dc30SBarry Smith #include <petscsnes.h> 415837fdd005SBarry Smith PetscErrorCode SNESConvergenceTest(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *cctx) 4159bf388a1fSBarry Smith 4160c3339decSBarry Smith Collective 41611843f636SBarry Smith 41621843f636SBarry Smith Input Parameters: 4163f6dfbefdSBarry Smith + snes - the `SNES` context 4164bf388a1fSBarry Smith . it - current iteration (0 is the first and is before any Newton step) 4165bf388a1fSBarry Smith . xnorm - 2-norm of current iterate 4166bf388a1fSBarry Smith . gnorm - 2-norm of current step 41671843f636SBarry Smith . f - 2-norm of function 41681843f636SBarry Smith - cctx - [optional] convergence context 41691843f636SBarry Smith 41701843f636SBarry Smith Output Parameter: 41711843f636SBarry Smith . reason - reason for convergence/divergence, only needs to be set when convergence or divergence is detected 4172bf388a1fSBarry Smith 4173878cb397SSatish Balay Level: intermediate 4174bf388a1fSBarry Smith 41751cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`, `SNESGetConvergenceTest()` 4176bf388a1fSBarry Smith M*/ 4177bf388a1fSBarry Smith 41789b94acceSBarry Smith /*@C 41799b94acceSBarry Smith SNESSetConvergenceTest - Sets the function that is to be used 41809b94acceSBarry Smith to test for convergence of the nonlinear iterative solution. 41819b94acceSBarry Smith 4182c3339decSBarry Smith Logically Collective 4183fee21e36SBarry Smith 4184c7afd0dbSLois Curfman McInnes Input Parameters: 4185f6dfbefdSBarry Smith + snes - the `SNES` context 4186e4094ef1SJacob Faibussowitsch . SNESConvergenceTestFunction - routine to test for convergence 4187dc4c0fb0SBarry Smith . cctx - [optional] context for private data for the convergence routine (may be `NULL`) 4188dc4c0fb0SBarry Smith - destroy - [optional] destructor for the context (may be `NULL`; `PETSC_NULL_FUNCTION` in Fortran) 41899b94acceSBarry Smith 419036851e7fSLois Curfman McInnes Level: advanced 419136851e7fSLois Curfman McInnes 41921cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedDefault()`, `SNESConvergedSkip()`, `SNESConvergenceTestFunction` 41939b94acceSBarry Smith @*/ 4194d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceTest(SNES snes, PetscErrorCode (*SNESConvergenceTestFunction)(SNES, PetscInt, PetscReal, PetscReal, PetscReal, SNESConvergedReason *, void *), void *cctx, PetscErrorCode (*destroy)(void *)) 4195d71ae5a4SJacob Faibussowitsch { 41963a40ed3dSBarry Smith PetscFunctionBegin; 41970700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4198e2a6519dSDmitry Karpeev if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip; 41991baa6e33SBarry Smith if (snes->ops->convergeddestroy) PetscCall((*snes->ops->convergeddestroy)(snes->cnvP)); 4200bf388a1fSBarry Smith snes->ops->converged = SNESConvergenceTestFunction; 42017f7931b9SBarry Smith snes->ops->convergeddestroy = destroy; 420285385478SLisandro Dalcin snes->cnvP = cctx; 42033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 42049b94acceSBarry Smith } 42059b94acceSBarry Smith 420652baeb72SSatish Balay /*@ 4207f6dfbefdSBarry Smith SNESGetConvergedReason - Gets the reason the `SNES` iteration was stopped. 4208184914b5SBarry Smith 4209184914b5SBarry Smith Not Collective 4210184914b5SBarry Smith 4211184914b5SBarry Smith Input Parameter: 4212f6dfbefdSBarry Smith . snes - the `SNES` context 4213184914b5SBarry Smith 4214184914b5SBarry Smith Output Parameter: 4215f6dfbefdSBarry Smith . reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` for the individual convergence tests for complete lists 4216184914b5SBarry Smith 4217f6dfbefdSBarry Smith Options Database Key: 42186a4d7782SBarry Smith . -snes_converged_reason - prints the reason to standard out 42196a4d7782SBarry Smith 4220184914b5SBarry Smith Level: intermediate 4221184914b5SBarry Smith 4222f6dfbefdSBarry Smith Note: 4223f6dfbefdSBarry Smith Should only be called after the call the `SNESSolve()` is complete, if it is called earlier it returns the value `SNES__CONVERGED_ITERATING`. 4224184914b5SBarry Smith 42251cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESSetConvergedReason()`, `SNESConvergedReason`, `SNESGetConvergedReasonString()` 4226184914b5SBarry Smith @*/ 4227d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReason(SNES snes, SNESConvergedReason *reason) 4228d71ae5a4SJacob Faibussowitsch { 4229184914b5SBarry Smith PetscFunctionBegin; 42300700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 42314f572ea9SToby Isaac PetscAssertPointer(reason, 2); 4232184914b5SBarry Smith *reason = snes->reason; 42333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4234184914b5SBarry Smith } 4235184914b5SBarry Smith 4236c4421ceaSFande Kong /*@C 4237f6dfbefdSBarry Smith SNESGetConvergedReasonString - Return a human readable string for `SNESConvergedReason` 4238c4421ceaSFande Kong 4239c4421ceaSFande Kong Not Collective 4240c4421ceaSFande Kong 4241c4421ceaSFande Kong Input Parameter: 4242f6dfbefdSBarry Smith . snes - the `SNES` context 4243c4421ceaSFande Kong 4244c4421ceaSFande Kong Output Parameter: 4245dc4c0fb0SBarry Smith . strreason - a human readable string that describes `SNES` converged reason 4246c4421ceaSFande Kong 424799c90e12SSatish Balay Level: beginner 4248c4421ceaSFande Kong 42491cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetConvergedReason()` 4250c4421ceaSFande Kong @*/ 4251d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReasonString(SNES snes, const char **strreason) 4252d71ae5a4SJacob Faibussowitsch { 4253c4421ceaSFande Kong PetscFunctionBegin; 4254c4421ceaSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 42554f572ea9SToby Isaac PetscAssertPointer(strreason, 2); 4256c4421ceaSFande Kong *strreason = SNESConvergedReasons[snes->reason]; 42573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4258c4421ceaSFande Kong } 4259c4421ceaSFande Kong 426033866048SMatthew G. Knepley /*@ 4261f6dfbefdSBarry Smith SNESSetConvergedReason - Sets the reason the `SNES` iteration was stopped. 426233866048SMatthew G. Knepley 426333866048SMatthew G. Knepley Not Collective 426433866048SMatthew G. Knepley 426533866048SMatthew G. Knepley Input Parameters: 4266f6dfbefdSBarry Smith + snes - the `SNES` context 4267f6dfbefdSBarry Smith - reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` or the 426833866048SMatthew G. Knepley manual pages for the individual convergence tests for complete lists 426933866048SMatthew G. Knepley 4270f6dfbefdSBarry Smith Level: developer 4271f6dfbefdSBarry Smith 4272420bcc1bSBarry Smith Developer Note: 4273f6dfbefdSBarry Smith Called inside the various `SNESSolve()` implementations 427433866048SMatthew G. Knepley 42751cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetConvergedReason()`, `SNESSetConvergenceTest()`, `SNESConvergedReason` 427633866048SMatthew G. Knepley @*/ 4277d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergedReason(SNES snes, SNESConvergedReason reason) 4278d71ae5a4SJacob Faibussowitsch { 427933866048SMatthew G. Knepley PetscFunctionBegin; 428033866048SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 42815f3c5e7aSBarry Smith PetscCheck(!snes->errorifnotconverged || reason > 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "SNES code should have previously errored due to negative reason"); 428233866048SMatthew G. Knepley snes->reason = reason; 42833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 428433866048SMatthew G. Knepley } 428533866048SMatthew G. Knepley 4286c9005455SLois Curfman McInnes /*@ 4287420bcc1bSBarry Smith SNESSetConvergenceHistory - Sets the arrays used to hold the convergence history. 4288c9005455SLois Curfman McInnes 4289c3339decSBarry Smith Logically Collective 4290fee21e36SBarry Smith 4291c7afd0dbSLois Curfman McInnes Input Parameters: 4292f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 42938c7482ecSBarry Smith . a - array to hold history, this array will contain the function norms computed at each step 4294cd5578b5SBarry Smith . its - integer array holds the number of linear iterations for each solve. 4295420bcc1bSBarry Smith . na - size of `a` and `its` 4296f6dfbefdSBarry Smith - reset - `PETSC_TRUE` indicates each new nonlinear solve resets the history counter to zero, 4297758f92a0SBarry Smith else it continues storing new values for new nonlinear solves after the old ones 4298c7afd0dbSLois Curfman McInnes 4299dc4c0fb0SBarry Smith Level: intermediate 4300dc4c0fb0SBarry Smith 4301308dcc3eSBarry Smith Notes: 4302dc4c0fb0SBarry Smith If 'a' and 'its' are `NULL` then space is allocated for the history. If 'na' `PETSC_DECIDE` or `PETSC_DEFAULT` then a 4303308dcc3eSBarry Smith default array of length 10000 is allocated. 4304308dcc3eSBarry Smith 4305c9005455SLois Curfman McInnes This routine is useful, e.g., when running a code for purposes 4306c9005455SLois Curfman McInnes of accurate performance monitoring, when no I/O should be done 4307c9005455SLois Curfman McInnes during the section of code that is being timed. 4308c9005455SLois Curfman McInnes 4309420bcc1bSBarry Smith If the arrays run out of space after a number of iterations then the later values are not saved in the history 4310420bcc1bSBarry Smith 43111cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetConvergenceHistory()` 4312c9005455SLois Curfman McInnes @*/ 4313d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceHistory(SNES snes, PetscReal a[], PetscInt its[], PetscInt na, PetscBool reset) 4314d71ae5a4SJacob Faibussowitsch { 43153a40ed3dSBarry Smith PetscFunctionBegin; 43160700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 43174f572ea9SToby Isaac if (a) PetscAssertPointer(a, 2); 43184f572ea9SToby Isaac if (its) PetscAssertPointer(its, 3); 43197a1ec6d4SBarry Smith if (!a) { 4320308dcc3eSBarry Smith if (na == PETSC_DECIDE || na == PETSC_DEFAULT) na = 1000; 43219566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(na, &a, na, &its)); 4322071fcb05SBarry Smith snes->conv_hist_alloc = PETSC_TRUE; 4323308dcc3eSBarry Smith } 4324c9005455SLois Curfman McInnes snes->conv_hist = a; 4325758f92a0SBarry Smith snes->conv_hist_its = its; 4326115dd874SBarry Smith snes->conv_hist_max = (size_t)na; 4327a12bc48fSLisandro Dalcin snes->conv_hist_len = 0; 4328758f92a0SBarry Smith snes->conv_hist_reset = reset; 43293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4330758f92a0SBarry Smith } 4331758f92a0SBarry Smith 4332d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB) 4333c6db04a5SJed Brown #include <engine.h> /* MATLAB include file */ 4334c6db04a5SJed Brown #include <mex.h> /* MATLAB include file */ 433599e0435eSBarry Smith 4336d71ae5a4SJacob Faibussowitsch PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes) 4337d71ae5a4SJacob Faibussowitsch { 4338308dcc3eSBarry Smith mxArray *mat; 4339308dcc3eSBarry Smith PetscInt i; 4340308dcc3eSBarry Smith PetscReal *ar; 4341308dcc3eSBarry Smith 4342308dcc3eSBarry Smith mat = mxCreateDoubleMatrix(snes->conv_hist_len, 1, mxREAL); 4343308dcc3eSBarry Smith ar = (PetscReal *)mxGetData(mat); 4344f5af7f23SKarl Rupp for (i = 0; i < snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i]; 434511cc89d2SBarry Smith return mat; 4346308dcc3eSBarry Smith } 4347308dcc3eSBarry Smith #endif 4348308dcc3eSBarry Smith 43490c4c9dddSBarry Smith /*@C 4350420bcc1bSBarry Smith SNESGetConvergenceHistory - Gets the arrays used to hold the convergence history. 4351758f92a0SBarry Smith 43523f9fe445SBarry Smith Not Collective 4353758f92a0SBarry Smith 4354758f92a0SBarry Smith Input Parameter: 4355f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 4356758f92a0SBarry Smith 4357758f92a0SBarry Smith Output Parameters: 4358f6dfbefdSBarry Smith + a - array to hold history, usually was set with `SNESSetConvergenceHistory()` 4359758f92a0SBarry Smith . its - integer array holds the number of linear iterations (or 4360758f92a0SBarry Smith negative if not converged) for each solve. 436120f4b53cSBarry Smith - na - size of `a` and `its` 4362758f92a0SBarry Smith 4363dc4c0fb0SBarry Smith Level: intermediate 4364dc4c0fb0SBarry Smith 436520f4b53cSBarry Smith Note: 436620f4b53cSBarry Smith This routine is useful, e.g., when running a code for purposes 436720f4b53cSBarry Smith of accurate performance monitoring, when no I/O should be done 436820f4b53cSBarry Smith during the section of code that is being timed. 436920f4b53cSBarry Smith 4370420bcc1bSBarry Smith Fortran Note: 4371758f92a0SBarry Smith The calling sequence for this routine in Fortran is 4372dc4c0fb0SBarry Smith .vb 4373dc4c0fb0SBarry Smith call SNESGetConvergenceHistory(SNES snes, integer na, integer ierr) 4374dc4c0fb0SBarry Smith .ve 4375758f92a0SBarry Smith 43761cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceHistory()` 4377758f92a0SBarry Smith @*/ 4378d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergenceHistory(SNES snes, PetscReal *a[], PetscInt *its[], PetscInt *na) 4379d71ae5a4SJacob Faibussowitsch { 4380758f92a0SBarry Smith PetscFunctionBegin; 43810700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4382758f92a0SBarry Smith if (a) *a = snes->conv_hist; 4383758f92a0SBarry Smith if (its) *its = snes->conv_hist_its; 4384115dd874SBarry Smith if (na) *na = (PetscInt)snes->conv_hist_len; 43853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4386c9005455SLois Curfman McInnes } 4387c9005455SLois Curfman McInnes 4388ac226902SBarry Smith /*@C 438976b2cf59SMatthew Knepley SNESSetUpdate - Sets the general-purpose update function called 4390eec8f646SJed Brown at the beginning of every iteration of the nonlinear solve. Specifically 43917e4bb74cSBarry Smith it is called just before the Jacobian is "evaluated". 439276b2cf59SMatthew Knepley 4393c3339decSBarry Smith Logically Collective 439476b2cf59SMatthew Knepley 439576b2cf59SMatthew Knepley Input Parameters: 4396a2b725a8SWilliam Gropp + snes - The nonlinear solver context 4397a2b725a8SWilliam Gropp - func - The function 439876b2cf59SMatthew Knepley 439920f4b53cSBarry Smith Calling sequence of `func`: 440020f4b53cSBarry Smith + snes - the nonlinear solver context 440120f4b53cSBarry Smith - step - The current step of the iteration 440276b2cf59SMatthew Knepley 4403fe97e370SBarry Smith Level: advanced 4404fe97e370SBarry Smith 4405420bcc1bSBarry Smith Notes: 4406f6dfbefdSBarry 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 4407f6dfbefdSBarry Smith to `SNESSetFunction()`, or `SNESSetPicard()` 4408fe97e370SBarry Smith This is not used by most users. 440976b2cf59SMatthew Knepley 4410aaa8cc7dSPierre 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. 44116b7fb656SBarry Smith 4412e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetJacobian()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRSetPostCheck()`, 4413db781477SPatrick Sanan `SNESMonitorSet()`, `SNESSetDivergenceTest()` 441476b2cf59SMatthew Knepley @*/ 44150b4db180SJacob Faibussowitsch PetscErrorCode SNESSetUpdate(SNES snes, PetscErrorCode (*func)(SNES snes, PetscInt step)) 4416d71ae5a4SJacob Faibussowitsch { 441776b2cf59SMatthew Knepley PetscFunctionBegin; 44180700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4419e7788613SBarry Smith snes->ops->update = func; 44203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 442176b2cf59SMatthew Knepley } 442276b2cf59SMatthew Knepley 442391f3e32bSBarry Smith /*@C 4424f6dfbefdSBarry Smith SNESConvergedReasonView - Displays the reason a `SNES` solve converged or diverged to a viewer 44252a359c20SBarry Smith 4426c3339decSBarry Smith Collective 44272a359c20SBarry Smith 4428e4094ef1SJacob Faibussowitsch Input Parameters: 4429f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 44302a359c20SBarry Smith - viewer - the viewer to display the reason 44312a359c20SBarry Smith 44322a359c20SBarry Smith Options Database Keys: 4433ee300463SSatish Balay + -snes_converged_reason - print reason for converged or diverged, also prints number of iterations 4434ee300463SSatish Balay - -snes_converged_reason ::failed - only print reason and number of iterations when diverged 4435eafd5ff0SAlex Lindsay 4436420bcc1bSBarry Smith Level: beginner 4437420bcc1bSBarry Smith 4438f6dfbefdSBarry Smith Note: 4439f6dfbefdSBarry Smith To change the format of the output call `PetscViewerPushFormat`(viewer,format) before this call. Use `PETSC_VIEWER_DEFAULT` for the default, 4440f6dfbefdSBarry Smith use `PETSC_VIEWER_FAILED` to only display a reason if it fails. 44412a359c20SBarry Smith 44421cc06b55SBarry Smith .seealso: [](ch_snes), `SNESConvergedReason`, `PetscViewer`, `SNES`, 4443f6dfbefdSBarry Smith `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, 4444f6dfbefdSBarry Smith `SNESConvergedReasonViewFromOptions()`, 4445db781477SPatrick Sanan `PetscViewerPushFormat()`, `PetscViewerPopFormat()` 44462a359c20SBarry Smith @*/ 4447d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonView(SNES snes, PetscViewer viewer) 4448d71ae5a4SJacob Faibussowitsch { 444975cca76cSMatthew G. Knepley PetscViewerFormat format; 44502a359c20SBarry Smith PetscBool isAscii; 44512a359c20SBarry Smith 44522a359c20SBarry Smith PetscFunctionBegin; 445319a666eeSBarry Smith if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)); 44549566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii)); 44552a359c20SBarry Smith if (isAscii) { 44569566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 44579566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel)); 445875cca76cSMatthew G. Knepley if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 445975cca76cSMatthew G. Knepley DM dm; 446075cca76cSMatthew G. Knepley Vec u; 446175cca76cSMatthew G. Knepley PetscDS prob; 446275cca76cSMatthew G. Knepley PetscInt Nf, f; 446395cbbfd3SMatthew G. Knepley PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *); 446495cbbfd3SMatthew G. Knepley void **exactCtx; 446575cca76cSMatthew G. Knepley PetscReal error; 446675cca76cSMatthew G. Knepley 44679566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 44689566063dSJacob Faibussowitsch PetscCall(SNESGetSolution(snes, &u)); 44699566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob)); 44709566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(prob, &Nf)); 44719566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(Nf, &exactSol, Nf, &exactCtx)); 44729566063dSJacob Faibussowitsch for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f])); 44739566063dSJacob Faibussowitsch PetscCall(DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error)); 44749566063dSJacob Faibussowitsch PetscCall(PetscFree2(exactSol, exactCtx)); 44759566063dSJacob Faibussowitsch if (error < 1.0e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n")); 447663a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", (double)error)); 447775cca76cSMatthew G. Knepley } 4478eafd5ff0SAlex Lindsay if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) { 44792a359c20SBarry Smith if (((PetscObject)snes)->prefix) { 448063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter)); 44812a359c20SBarry Smith } else { 448263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve converged due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter)); 44832a359c20SBarry Smith } 4484eafd5ff0SAlex Lindsay } else if (snes->reason <= 0) { 44852a359c20SBarry Smith if (((PetscObject)snes)->prefix) { 448663a3b9bcSJacob 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)); 44872a359c20SBarry Smith } else { 448863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve did not converge due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter)); 44892a359c20SBarry Smith } 44902a359c20SBarry Smith } 44919566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel)); 44922a359c20SBarry Smith } 44933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 44942a359c20SBarry Smith } 44952a359c20SBarry Smith 4496c4421ceaSFande Kong /*@C 4497c4421ceaSFande Kong SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the 4498aaa8cc7dSPierre Jolivet end of the nonlinear solver to display the convergence reason of the nonlinear solver. 4499c4421ceaSFande Kong 4500c3339decSBarry Smith Logically Collective 4501c4421ceaSFande Kong 4502c4421ceaSFande Kong Input Parameters: 4503f6dfbefdSBarry Smith + snes - the `SNES` context 4504420bcc1bSBarry Smith . f - the `SNESConvergedReason` view function 4505420bcc1bSBarry Smith . vctx - [optional] user-defined context for private data for the `SNESConvergedReason` view function (use `NULL` if no context is desired) 4506420bcc1bSBarry Smith - reasonviewdestroy - [optional] routine that frees the context (may be `NULL`) 4507420bcc1bSBarry Smith 4508420bcc1bSBarry Smith Calling sequence of `f`: 4509420bcc1bSBarry Smith + snes - the `SNES` context 4510420bcc1bSBarry Smith - vctx - [optional] user-defined context for private data for the function 4511420bcc1bSBarry Smith 4512420bcc1bSBarry Smith Calling sequence of `reasonviewerdestroy`: 4513420bcc1bSBarry Smith . vctx - [optional] user-defined context for private data for the function 4514c4421ceaSFande Kong 4515c4421ceaSFande Kong Options Database Keys: 4516f6dfbefdSBarry Smith + -snes_converged_reason - sets a default `SNESConvergedReasonView()` 4517420bcc1bSBarry Smith - -snes_converged_reason_view_cancel - cancels all converged reason viewers that have been hardwired into a code by 4518420bcc1bSBarry Smith calls to `SNESConvergedReasonViewSet()`, but does not cancel those set via the options database. 4519c4421ceaSFande Kong 4520dc4c0fb0SBarry Smith Level: intermediate 4521dc4c0fb0SBarry Smith 4522f6dfbefdSBarry Smith Note: 4523c4421ceaSFande Kong Several different converged reason view routines may be set by calling 4524f6dfbefdSBarry Smith `SNESConvergedReasonViewSet()` multiple times; all will be called in the 4525c4421ceaSFande Kong order in which they were set. 4526c4421ceaSFande Kong 45271cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`, `SNESConvergedReasonViewCancel()` 4528c4421ceaSFande Kong @*/ 4529420bcc1bSBarry Smith PetscErrorCode SNESConvergedReasonViewSet(SNES snes, PetscErrorCode (*f)(SNES snes, void *vctx), void *vctx, PetscErrorCode (*reasonviewdestroy)(void **vctx)) 4530d71ae5a4SJacob Faibussowitsch { 4531c4421ceaSFande Kong PetscInt i; 4532c4421ceaSFande Kong PetscBool identical; 4533c4421ceaSFande Kong 4534c4421ceaSFande Kong PetscFunctionBegin; 4535c4421ceaSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4536c4421ceaSFande Kong for (i = 0; i < snes->numberreasonviews; i++) { 45379566063dSJacob Faibussowitsch PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, vctx, reasonviewdestroy, (PetscErrorCode(*)(void))snes->reasonview[i], snes->reasonviewcontext[i], snes->reasonviewdestroy[i], &identical)); 45383ba16761SJacob Faibussowitsch if (identical) PetscFunctionReturn(PETSC_SUCCESS); 4539c4421ceaSFande Kong } 45405f80ce2aSJacob Faibussowitsch PetscCheck(snes->numberreasonviews < MAXSNESREASONVIEWS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many SNES reasonview set"); 4541c4421ceaSFande Kong snes->reasonview[snes->numberreasonviews] = f; 4542c4421ceaSFande Kong snes->reasonviewdestroy[snes->numberreasonviews] = reasonviewdestroy; 4543c4421ceaSFande Kong snes->reasonviewcontext[snes->numberreasonviews++] = (void *)vctx; 45443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4545c4421ceaSFande Kong } 4546c4421ceaSFande Kong 454791f3e32bSBarry Smith /*@ 4548420bcc1bSBarry Smith SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a `SNESConvergedReason` is to be viewed at the end of `SNESSolve()` 4549c4421ceaSFande Kong All the user-provided convergedReasonView routines will be involved as well, if they exist. 45502a359c20SBarry Smith 4551c3339decSBarry Smith Collective 45522a359c20SBarry Smith 45532fe279fdSBarry Smith Input Parameter: 4554f6dfbefdSBarry Smith . snes - the `SNES` object 45552a359c20SBarry Smith 4556f6dfbefdSBarry Smith Level: advanced 45572a359c20SBarry Smith 45581cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESConvergedReasonViewSet()`, `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, 4559f6dfbefdSBarry Smith `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()` 45602a359c20SBarry Smith @*/ 4561d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes) 4562d71ae5a4SJacob Faibussowitsch { 45632a359c20SBarry Smith PetscViewer viewer; 45642a359c20SBarry Smith PetscBool flg; 45652a359c20SBarry Smith static PetscBool incall = PETSC_FALSE; 45662a359c20SBarry Smith PetscViewerFormat format; 4567c4421ceaSFande Kong PetscInt i; 45682a359c20SBarry Smith 45692a359c20SBarry Smith PetscFunctionBegin; 45703ba16761SJacob Faibussowitsch if (incall) PetscFunctionReturn(PETSC_SUCCESS); 45712a359c20SBarry Smith incall = PETSC_TRUE; 4572c4421ceaSFande Kong 4573c4421ceaSFande Kong /* All user-provided viewers are called first, if they exist. */ 457448a46eb9SPierre Jolivet for (i = 0; i < snes->numberreasonviews; i++) PetscCall((*snes->reasonview[i])(snes, snes->reasonviewcontext[i])); 4575c4421ceaSFande Kong 4576c4421ceaSFande Kong /* Call PETSc default routine if users ask for it */ 45779566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_converged_reason", &viewer, &format, &flg)); 45782a359c20SBarry Smith if (flg) { 45799566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(viewer, format)); 45809566063dSJacob Faibussowitsch PetscCall(SNESConvergedReasonView(snes, viewer)); 45819566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer)); 4582cd791dc2SBarry Smith PetscCall(PetscOptionsRestoreViewer(&viewer)); 45832a359c20SBarry Smith } 45842a359c20SBarry Smith incall = PETSC_FALSE; 45853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 45862a359c20SBarry Smith } 45872a359c20SBarry Smith 4588487a658cSBarry Smith /*@ 4589f69a0ea3SMatthew Knepley SNESSolve - Solves a nonlinear system F(x) = b. 45909b94acceSBarry Smith 4591c3339decSBarry Smith Collective 4592c7afd0dbSLois Curfman McInnes 4593b2002411SLois Curfman McInnes Input Parameters: 4594f6dfbefdSBarry Smith + snes - the `SNES` context 4595dc4c0fb0SBarry Smith . b - the constant part of the equation F(x) = b, or `NULL` to use zero. 459685385478SLisandro Dalcin - x - the solution vector. 45979b94acceSBarry Smith 4598dc4c0fb0SBarry Smith Level: beginner 4599dc4c0fb0SBarry Smith 4600f6dfbefdSBarry Smith Note: 4601420bcc1bSBarry Smith The user should initialize the vector, `x`, with the initial guess 4602420bcc1bSBarry Smith for the nonlinear solve prior to calling `SNESSolve()` or use `SNESSetInitialSolution()`. In particular, 46038ddd3da0SLois Curfman McInnes to employ an initial guess of zero, the user should explicitly set 4604f6dfbefdSBarry Smith this vector to zero by calling `VecSet()`. 46058ddd3da0SLois Curfman McInnes 46061cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESSetFunction()`, `SNESSetJacobian()`, `SNESSetGridSequence()`, `SNESGetSolution()`, 4607db781477SPatrick Sanan `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRGetPreCheck()`, `SNESNewtonTRSetPostCheck()`, `SNESNewtonTRGetPostCheck()`, 4608420bcc1bSBarry Smith `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`, `SNESSetInitialSolution()` 46099b94acceSBarry Smith @*/ 4610d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSolve(SNES snes, Vec b, Vec x) 4611d71ae5a4SJacob Faibussowitsch { 4612ace3abfcSBarry Smith PetscBool flg; 4613efd51863SBarry Smith PetscInt grid; 46140298fd71SBarry Smith Vec xcreated = NULL; 4615caa4e7f2SJed Brown DM dm; 4616052efed2SBarry Smith 46173a40ed3dSBarry Smith PetscFunctionBegin; 46180700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4619a69afd8bSBarry Smith if (x) PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4620a69afd8bSBarry Smith if (x) PetscCheckSameComm(snes, 1, x, 3); 46210700a824SBarry Smith if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 462285385478SLisandro Dalcin if (b) PetscCheckSameComm(snes, 1, b, 2); 462385385478SLisandro Dalcin 462434b4d3a8SMatthew G. Knepley /* High level operations using the nonlinear solver */ 462506fc46c8SMatthew G. Knepley { 462606fc46c8SMatthew G. Knepley PetscViewer viewer; 462706fc46c8SMatthew G. Knepley PetscViewerFormat format; 46287c88af5aSMatthew G. Knepley PetscInt num; 462906fc46c8SMatthew G. Knepley PetscBool flg; 463006fc46c8SMatthew G. Knepley static PetscBool incall = PETSC_FALSE; 463106fc46c8SMatthew G. Knepley 463206fc46c8SMatthew G. Knepley if (!incall) { 463334b4d3a8SMatthew G. Knepley /* Estimate the convergence rate of the discretization */ 46349566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg)); 463506fc46c8SMatthew G. Knepley if (flg) { 463606fc46c8SMatthew G. Knepley PetscConvEst conv; 463746079b62SMatthew G. Knepley DM dm; 463846079b62SMatthew G. Knepley PetscReal *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */ 463946079b62SMatthew G. Knepley PetscInt Nf; 464006fc46c8SMatthew G. Knepley 464106fc46c8SMatthew G. Knepley incall = PETSC_TRUE; 46429566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 46439566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 46449566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(Nf, &alpha)); 46459566063dSJacob Faibussowitsch PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)snes), &conv)); 46469566063dSJacob Faibussowitsch PetscCall(PetscConvEstSetSolver(conv, (PetscObject)snes)); 46479566063dSJacob Faibussowitsch PetscCall(PetscConvEstSetFromOptions(conv)); 46489566063dSJacob Faibussowitsch PetscCall(PetscConvEstSetUp(conv)); 46499566063dSJacob Faibussowitsch PetscCall(PetscConvEstGetConvRate(conv, alpha)); 46509566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(viewer, format)); 46519566063dSJacob Faibussowitsch PetscCall(PetscConvEstRateView(conv, alpha, viewer)); 46529566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer)); 4653cd791dc2SBarry Smith PetscCall(PetscOptionsRestoreViewer(&viewer)); 46549566063dSJacob Faibussowitsch PetscCall(PetscConvEstDestroy(&conv)); 46559566063dSJacob Faibussowitsch PetscCall(PetscFree(alpha)); 465606fc46c8SMatthew G. Knepley incall = PETSC_FALSE; 465706fc46c8SMatthew G. Knepley } 465834b4d3a8SMatthew G. Knepley /* Adaptively refine the initial grid */ 4659b2588ea6SMatthew G. Knepley num = 1; 46609566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_initial", &num, &flg)); 466134b4d3a8SMatthew G. Knepley if (flg) { 466234b4d3a8SMatthew G. Knepley DMAdaptor adaptor; 466334b4d3a8SMatthew G. Knepley 466434b4d3a8SMatthew G. Knepley incall = PETSC_TRUE; 46659566063dSJacob Faibussowitsch PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor)); 46669566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSolver(adaptor, snes)); 46679566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSequenceLength(adaptor, num)); 46689566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetFromOptions(adaptor)); 46699566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetUp(adaptor)); 46709566063dSJacob Faibussowitsch PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x)); 46719566063dSJacob Faibussowitsch PetscCall(DMAdaptorDestroy(&adaptor)); 467234b4d3a8SMatthew G. Knepley incall = PETSC_FALSE; 467334b4d3a8SMatthew G. Knepley } 46747c88af5aSMatthew G. Knepley /* Use grid sequencing to adapt */ 46757c88af5aSMatthew G. Knepley num = 0; 46769566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_sequence", &num, NULL)); 46777c88af5aSMatthew G. Knepley if (num) { 46787c88af5aSMatthew G. Knepley DMAdaptor adaptor; 46797c88af5aSMatthew G. Knepley 46807c88af5aSMatthew G. Knepley incall = PETSC_TRUE; 46819566063dSJacob Faibussowitsch PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor)); 46829566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSolver(adaptor, snes)); 46839566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSequenceLength(adaptor, num)); 46849566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetFromOptions(adaptor)); 46859566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetUp(adaptor)); 46869566063dSJacob Faibussowitsch PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x)); 46879566063dSJacob Faibussowitsch PetscCall(DMAdaptorDestroy(&adaptor)); 46887c88af5aSMatthew G. Knepley incall = PETSC_FALSE; 46897c88af5aSMatthew G. Knepley } 469006fc46c8SMatthew G. Knepley } 469106fc46c8SMatthew G. Knepley } 4692ad540459SPierre Jolivet if (!x) x = snes->vec_sol; 4693caa4e7f2SJed Brown if (!x) { 46949566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 46959566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dm, &xcreated)); 4696a69afd8bSBarry Smith x = xcreated; 4697a69afd8bSBarry Smith } 46989566063dSJacob Faibussowitsch PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view_pre")); 4699f05ece33SBarry Smith 47009566063dSJacob Faibussowitsch for (grid = 0; grid < snes->gridsequence; grid++) PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)))); 4701efd51863SBarry Smith for (grid = 0; grid < snes->gridsequence + 1; grid++) { 470285385478SLisandro Dalcin /* set solution vector */ 47039566063dSJacob Faibussowitsch if (!grid) PetscCall(PetscObjectReference((PetscObject)x)); 47049566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol)); 470585385478SLisandro Dalcin snes->vec_sol = x; 47069566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 4707caa4e7f2SJed Brown 4708caa4e7f2SJed Brown /* set affine vector if provided */ 47099566063dSJacob Faibussowitsch if (b) PetscCall(PetscObjectReference((PetscObject)b)); 47109566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_rhs)); 471185385478SLisandro Dalcin snes->vec_rhs = b; 471285385478SLisandro Dalcin 47135f80ce2aSJacob 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"); 47145f80ce2aSJacob Faibussowitsch PetscCheck(snes->vec_func != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be function vector"); 47155f80ce2aSJacob Faibussowitsch PetscCheck(snes->vec_rhs != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be right hand side vector"); 4716aa624791SPierre Jolivet if (!snes->vec_sol_update /* && snes->vec_sol */) PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_sol_update)); 47179566063dSJacob Faibussowitsch PetscCall(DMShellSetGlobalVector(dm, snes->vec_sol)); 47189566063dSJacob Faibussowitsch PetscCall(SNESSetUp(snes)); 47193f149594SLisandro Dalcin 47207eee914bSBarry Smith if (!grid) { 47219927e4dfSBarry Smith if (snes->ops->computeinitialguess) PetscCallBack("SNES callback compute initial guess", (*snes->ops->computeinitialguess)(snes, snes->vec_sol, snes->initialguessP)); 4722dd568438SSatish Balay } 4723d25893d9SBarry Smith 4724abc0a331SBarry Smith if (snes->conv_hist_reset) snes->conv_hist_len = 0; 47259371c9d4SSatish Balay if (snes->counters_reset) { 47269371c9d4SSatish Balay snes->nfuncs = 0; 47279371c9d4SSatish Balay snes->linear_its = 0; 47289371c9d4SSatish Balay snes->numFailures = 0; 47299371c9d4SSatish Balay } 4730d5e45103SBarry Smith 47312d157150SStefano Zampini snes->reason = SNES_CONVERGED_ITERATING; 47329566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_Solve, snes, 0, 0, 0)); 4733dbbe0bcdSBarry Smith PetscUseTypeMethod(snes, solve); 47349566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_Solve, snes, 0, 0, 0)); 47352d157150SStefano Zampini PetscCheck(snes->reason, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error, solver %s returned without setting converged reason", ((PetscObject)snes)->type_name); 4736422a814eSBarry Smith snes->domainerror = PETSC_FALSE; /* clear the flag if it has been set */ 47373f149594SLisandro Dalcin 473837ec4e1aSPeter Brune if (snes->lagjac_persist) snes->jac_iter += snes->iter; 473937ec4e1aSPeter Brune if (snes->lagpre_persist) snes->pre_iter += snes->iter; 474037ec4e1aSPeter Brune 47419566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_test_local_min", NULL, NULL, &flg)); 47429566063dSJacob Faibussowitsch if (flg && !PetscPreLoadingOn) PetscCall(SNESTestLocalMin(snes)); 4743c4421ceaSFande Kong /* Call converged reason views. This may involve user-provided viewers as well */ 47449566063dSJacob Faibussowitsch PetscCall(SNESConvergedReasonViewFromOptions(snes)); 47455968eb51SBarry Smith 47465f80ce2aSJacob Faibussowitsch if (snes->errorifnotconverged) PetscCheck(snes->reason >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_NOT_CONVERGED, "SNESSolve has not converged"); 47479c8e83a9SBarry Smith if (snes->reason < 0) break; 4748efd51863SBarry Smith if (grid < snes->gridsequence) { 4749efd51863SBarry Smith DM fine; 4750efd51863SBarry Smith Vec xnew; 4751efd51863SBarry Smith Mat interp; 4752efd51863SBarry Smith 47539566063dSJacob Faibussowitsch PetscCall(DMRefine(snes->dm, PetscObjectComm((PetscObject)snes), &fine)); 47545f80ce2aSJacob Faibussowitsch PetscCheck(fine, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_INCOMP, "DMRefine() did not perform any refinement, cannot continue grid sequencing"); 47559566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(snes->dm, fine, &interp, NULL)); 47569566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(fine, &xnew)); 47579566063dSJacob Faibussowitsch PetscCall(MatInterpolate(interp, x, xnew)); 47589566063dSJacob Faibussowitsch PetscCall(DMInterpolate(snes->dm, interp, fine)); 47599566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interp)); 4760efd51863SBarry Smith x = xnew; 4761efd51863SBarry Smith 47629566063dSJacob Faibussowitsch PetscCall(SNESReset(snes)); 47639566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes, fine)); 47649566063dSJacob Faibussowitsch PetscCall(SNESResetFromOptions(snes)); 47659566063dSJacob Faibussowitsch PetscCall(DMDestroy(&fine)); 47669566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)))); 4767efd51863SBarry Smith } 4768efd51863SBarry Smith } 47699566063dSJacob Faibussowitsch PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view")); 47709566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(snes->vec_sol, (PetscObject)snes, "-snes_view_solution")); 47719566063dSJacob Faibussowitsch PetscCall(DMMonitor(snes->dm)); 47729566063dSJacob Faibussowitsch PetscCall(SNESMonitorPauseFinal_Internal(snes)); 47733f7e2da0SPeter Brune 47749566063dSJacob Faibussowitsch PetscCall(VecDestroy(&xcreated)); 47759566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsBlock((PetscObject)snes)); 47763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 47779b94acceSBarry Smith } 47789b94acceSBarry Smith 47799b94acceSBarry Smith /* --------- Internal routines for SNES Package --------- */ 47809b94acceSBarry Smith 478182bf6240SBarry Smith /*@C 47824b0e389bSBarry Smith SNESSetType - Sets the method for the nonlinear solver. 47839b94acceSBarry Smith 4784c3339decSBarry Smith Collective 4785fee21e36SBarry Smith 4786c7afd0dbSLois Curfman McInnes Input Parameters: 4787f6dfbefdSBarry Smith + snes - the `SNES` context 4788454a90a3SBarry Smith - type - a known method 4789c7afd0dbSLois Curfman McInnes 4790c7afd0dbSLois Curfman McInnes Options Database Key: 4791454a90a3SBarry Smith . -snes_type <type> - Sets the method; use -help for a list 479204d7464bSBarry Smith of available methods (for instance, newtonls or newtontr) 4793ae12b187SLois Curfman McInnes 4794dc4c0fb0SBarry Smith Level: intermediate 4795dc4c0fb0SBarry Smith 47969b94acceSBarry Smith Notes: 4797e090d566SSatish Balay See "petsc/include/petscsnes.h" for available methods (for instance) 4798f6dfbefdSBarry Smith + `SNESNEWTONLS` - Newton's method with line search 4799c7afd0dbSLois Curfman McInnes (systems of nonlinear equations) 48004a221d59SStefano Zampini - `SNESNEWTONTR` - Newton's method with trust region 4801c7afd0dbSLois Curfman McInnes (systems of nonlinear equations) 48029b94acceSBarry Smith 4803f6dfbefdSBarry Smith Normally, it is best to use the `SNESSetFromOptions()` command and then 4804f6dfbefdSBarry Smith set the `SNES` solver type from the options database rather than by using 4805ae12b187SLois Curfman McInnes this routine. Using the options database provides the user with 4806ae12b187SLois Curfman McInnes maximum flexibility in evaluating the many nonlinear solvers. 4807f6dfbefdSBarry Smith The `SNESSetType()` routine is provided for those situations where it 4808ae12b187SLois Curfman McInnes is necessary to set the nonlinear solver independently of the command 4809ae12b187SLois Curfman McInnes line or options database. This might be the case, for example, when 4810ae12b187SLois Curfman McInnes the choice of solver changes during the execution of the program, 4811ae12b187SLois Curfman McInnes and the user's application is taking responsibility for choosing the 4812b0a32e0cSBarry Smith appropriate method. 481336851e7fSLois Curfman McInnes 4814420bcc1bSBarry Smith Developer Note: 4815f6dfbefdSBarry Smith `SNESRegister()` adds a constructor for a new `SNESType` to `SNESList`, `SNESSetType()` locates 4816f6dfbefdSBarry Smith the constructor in that list and calls it to create the specific object. 48178f6c3df8SBarry Smith 48181cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESType`, `SNESCreate()`, `SNESDestroy()`, `SNESGetType()`, `SNESSetFromOptions()` 48199b94acceSBarry Smith @*/ 4820d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetType(SNES snes, SNESType type) 4821d71ae5a4SJacob Faibussowitsch { 4822ace3abfcSBarry Smith PetscBool match; 48235f80ce2aSJacob Faibussowitsch PetscErrorCode (*r)(SNES); 48243a40ed3dSBarry Smith 48253a40ed3dSBarry Smith PetscFunctionBegin; 48260700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 48274f572ea9SToby Isaac PetscAssertPointer(type, 2); 482882bf6240SBarry Smith 48299566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes, type, &match)); 48303ba16761SJacob Faibussowitsch if (match) PetscFunctionReturn(PETSC_SUCCESS); 483192ff6ae8SBarry Smith 48329566063dSJacob Faibussowitsch PetscCall(PetscFunctionListFind(SNESList, type, &r)); 48336adde796SStefano Zampini PetscCheck(r, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested SNES type %s", type); 483475396ef9SLisandro Dalcin /* Destroy the previous private SNES context */ 4835dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, destroy); 483675396ef9SLisandro Dalcin /* Reinitialize function pointers in SNESOps structure */ 48379e5d0892SLisandro Dalcin snes->ops->setup = NULL; 48389e5d0892SLisandro Dalcin snes->ops->solve = NULL; 48399e5d0892SLisandro Dalcin snes->ops->view = NULL; 48409e5d0892SLisandro Dalcin snes->ops->setfromoptions = NULL; 48419e5d0892SLisandro Dalcin snes->ops->destroy = NULL; 48427fe760d5SStefano Zampini 48437fe760d5SStefano Zampini /* It may happen the user has customized the line search before calling SNESSetType */ 48449566063dSJacob Faibussowitsch if (((PetscObject)snes)->type_name) PetscCall(SNESLineSearchDestroy(&snes->linesearch)); 48457fe760d5SStefano Zampini 484675396ef9SLisandro Dalcin /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */ 484775396ef9SLisandro Dalcin snes->setupcalled = PETSC_FALSE; 4848f5af7f23SKarl Rupp 48499566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)snes, type)); 48509566063dSJacob Faibussowitsch PetscCall((*r)(snes)); 48513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 48529b94acceSBarry Smith } 48539b94acceSBarry Smith 48549b94acceSBarry Smith /*@C 4855f6dfbefdSBarry Smith SNESGetType - Gets the `SNES` method type and name (as a string). 48569b94acceSBarry Smith 4857c7afd0dbSLois Curfman McInnes Not Collective 4858c7afd0dbSLois Curfman McInnes 48599b94acceSBarry Smith Input Parameter: 48604b0e389bSBarry Smith . snes - nonlinear solver context 48619b94acceSBarry Smith 48629b94acceSBarry Smith Output Parameter: 4863f6dfbefdSBarry Smith . type - `SNES` method (a character string) 48649b94acceSBarry Smith 486536851e7fSLois Curfman McInnes Level: intermediate 486636851e7fSLois Curfman McInnes 48671cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetType()`, `SNESType`, `SNESSetFromOptions()`, `SNES` 48689b94acceSBarry Smith @*/ 4869d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetType(SNES snes, SNESType *type) 4870d71ae5a4SJacob Faibussowitsch { 48713a40ed3dSBarry Smith PetscFunctionBegin; 48720700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 48734f572ea9SToby Isaac PetscAssertPointer(type, 2); 48747adad957SLisandro Dalcin *type = ((PetscObject)snes)->type_name; 48753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 48769b94acceSBarry Smith } 48779b94acceSBarry Smith 48783cd8a7caSMatthew G. Knepley /*@ 4879f6dfbefdSBarry Smith SNESSetSolution - Sets the solution vector for use by the `SNES` routines. 48803cd8a7caSMatthew G. Knepley 4881c3339decSBarry Smith Logically Collective 48823cd8a7caSMatthew G. Knepley 48833cd8a7caSMatthew G. Knepley Input Parameters: 4884f6dfbefdSBarry Smith + snes - the `SNES` context obtained from `SNESCreate()` 48853cd8a7caSMatthew G. Knepley - u - the solution vector 48863cd8a7caSMatthew G. Knepley 48873cd8a7caSMatthew G. Knepley Level: beginner 48883cd8a7caSMatthew G. Knepley 48891cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetSolution()`, `Vec` 48903cd8a7caSMatthew G. Knepley @*/ 4891d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetSolution(SNES snes, Vec u) 4892d71ae5a4SJacob Faibussowitsch { 48933cd8a7caSMatthew G. Knepley DM dm; 48943cd8a7caSMatthew G. Knepley 48953cd8a7caSMatthew G. Knepley PetscFunctionBegin; 48963cd8a7caSMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 48973cd8a7caSMatthew G. Knepley PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 48989566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)u)); 48999566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol)); 49003cd8a7caSMatthew G. Knepley 49013cd8a7caSMatthew G. Knepley snes->vec_sol = u; 49023cd8a7caSMatthew G. Knepley 49039566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 49049566063dSJacob Faibussowitsch PetscCall(DMShellSetGlobalVector(dm, u)); 49053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49063cd8a7caSMatthew G. Knepley } 49073cd8a7caSMatthew G. Knepley 490852baeb72SSatish Balay /*@ 49099b94acceSBarry Smith SNESGetSolution - Returns the vector where the approximate solution is 4910f6dfbefdSBarry Smith stored. This is the fine grid solution when using `SNESSetGridSequence()`. 49119b94acceSBarry Smith 4912420bcc1bSBarry Smith Not Collective, but `x` is parallel if `snes` is parallel 4913c7afd0dbSLois Curfman McInnes 49149b94acceSBarry Smith Input Parameter: 4915f6dfbefdSBarry Smith . snes - the `SNES` context 49169b94acceSBarry Smith 49179b94acceSBarry Smith Output Parameter: 49189b94acceSBarry Smith . x - the solution 49199b94acceSBarry Smith 492070e92668SMatthew Knepley Level: intermediate 492136851e7fSLois Curfman McInnes 49221cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetSolution()`, `SNESSolve()`, `SNES`, `SNESGetSolutionUpdate()`, `SNESGetFunction()` 49239b94acceSBarry Smith @*/ 4924d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolution(SNES snes, Vec *x) 4925d71ae5a4SJacob Faibussowitsch { 49263a40ed3dSBarry Smith PetscFunctionBegin; 49270700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 49284f572ea9SToby Isaac PetscAssertPointer(x, 2); 492985385478SLisandro Dalcin *x = snes->vec_sol; 49303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 493170e92668SMatthew Knepley } 493270e92668SMatthew Knepley 493352baeb72SSatish Balay /*@ 49349b94acceSBarry Smith SNESGetSolutionUpdate - Returns the vector where the solution update is 49359b94acceSBarry Smith stored. 49369b94acceSBarry Smith 4937420bcc1bSBarry Smith Not Collective, but `x` is parallel if `snes` is parallel 4938c7afd0dbSLois Curfman McInnes 49399b94acceSBarry Smith Input Parameter: 4940f6dfbefdSBarry Smith . snes - the `SNES` context 49419b94acceSBarry Smith 49429b94acceSBarry Smith Output Parameter: 49439b94acceSBarry Smith . x - the solution update 49449b94acceSBarry Smith 494536851e7fSLois Curfman McInnes Level: advanced 494636851e7fSLois Curfman McInnes 49471cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()` 49489b94acceSBarry Smith @*/ 4949d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionUpdate(SNES snes, Vec *x) 4950d71ae5a4SJacob Faibussowitsch { 49513a40ed3dSBarry Smith PetscFunctionBegin; 49520700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 49534f572ea9SToby Isaac PetscAssertPointer(x, 2); 495485385478SLisandro Dalcin *x = snes->vec_sol_update; 49553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49569b94acceSBarry Smith } 49579b94acceSBarry Smith 49589b94acceSBarry Smith /*@C 4959f6dfbefdSBarry Smith SNESGetFunction - Returns the function that defines the nonlinear system set with `SNESSetFunction()` 49609b94acceSBarry Smith 4961420bcc1bSBarry Smith Not Collective, but `r` is parallel if `snes` is parallel. Collective if `r` is requested, but has not been created yet. 4962c7afd0dbSLois Curfman McInnes 49639b94acceSBarry Smith Input Parameter: 4964f6dfbefdSBarry Smith . snes - the `SNES` context 49659b94acceSBarry Smith 4966d8d19677SJose E. Roman Output Parameters: 4967dc4c0fb0SBarry Smith + r - the vector that is used to store residuals (or `NULL` if you don't want it) 49688434afd1SBarry Smith . f - the function (or `NULL` if you don't want it); for calling sequence see `SNESFunctionFn` 4969dc4c0fb0SBarry Smith - ctx - the function context (or `NULL` if you don't want it) 49709b94acceSBarry Smith 497136851e7fSLois Curfman McInnes Level: advanced 497236851e7fSLois Curfman McInnes 4973f6dfbefdSBarry Smith Note: 4974dc4c0fb0SBarry Smith The vector `r` DOES NOT, in general, contain the current value of the `SNES` nonlinear function 497504edfde5SBarry Smith 49768434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetSolution()`, `SNESFunctionFn` 49779b94acceSBarry Smith @*/ 49788434afd1SBarry Smith PetscErrorCode SNESGetFunction(SNES snes, Vec *r, SNESFunctionFn **f, void **ctx) 4979d71ae5a4SJacob Faibussowitsch { 49806cab3a1bSJed Brown DM dm; 4981a63bb30eSJed Brown 49823a40ed3dSBarry Smith PetscFunctionBegin; 49830700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4984a63bb30eSJed Brown if (r) { 4985a63bb30eSJed Brown if (!snes->vec_func) { 4986a63bb30eSJed Brown if (snes->vec_rhs) { 49879566063dSJacob Faibussowitsch PetscCall(VecDuplicate(snes->vec_rhs, &snes->vec_func)); 4988a63bb30eSJed Brown } else if (snes->vec_sol) { 49899566063dSJacob Faibussowitsch PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_func)); 4990a63bb30eSJed Brown } else if (snes->dm) { 49919566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(snes->dm, &snes->vec_func)); 4992a63bb30eSJed Brown } 4993a63bb30eSJed Brown } 4994a63bb30eSJed Brown *r = snes->vec_func; 4995a63bb30eSJed Brown } 49969566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 49979566063dSJacob Faibussowitsch PetscCall(DMSNESGetFunction(dm, f, ctx)); 49983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49999b94acceSBarry Smith } 50009b94acceSBarry Smith 5001c79ef259SPeter Brune /*@C 500237fdd005SBarry Smith SNESGetNGS - Returns the function and context set with `SNESSetNGS()` 5003c79ef259SPeter Brune 5004c79ef259SPeter Brune Input Parameter: 5005f6dfbefdSBarry Smith . snes - the `SNES` context 5006c79ef259SPeter Brune 5007d8d19677SJose E. Roman Output Parameters: 50088434afd1SBarry Smith + f - the function (or `NULL`) see `SNESNGSFn` for calling sequence 5009dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`) 5010c79ef259SPeter Brune 5011c79ef259SPeter Brune Level: advanced 5012c79ef259SPeter Brune 50138434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetNGS()`, `SNESGetFunction()`, `SNESNGSFn` 5014c79ef259SPeter Brune @*/ 50158434afd1SBarry Smith PetscErrorCode SNESGetNGS(SNES snes, SNESNGSFn **f, void **ctx) 5016d71ae5a4SJacob Faibussowitsch { 50176cab3a1bSJed Brown DM dm; 50186cab3a1bSJed Brown 5019646217ecSPeter Brune PetscFunctionBegin; 5020646217ecSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 50219566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 50229566063dSJacob Faibussowitsch PetscCall(DMSNESGetNGS(dm, f, ctx)); 50233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5024646217ecSPeter Brune } 5025646217ecSPeter Brune 50263c7409f5SSatish Balay /*@C 50273c7409f5SSatish Balay SNESSetOptionsPrefix - Sets the prefix used for searching for all 5028f6dfbefdSBarry Smith `SNES` options in the database. 50293c7409f5SSatish Balay 5030c3339decSBarry Smith Logically Collective 5031fee21e36SBarry Smith 5032d8d19677SJose E. Roman Input Parameters: 5033f6dfbefdSBarry Smith + snes - the `SNES` context 5034c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names 5035c7afd0dbSLois Curfman McInnes 5036dc4c0fb0SBarry Smith Level: advanced 5037dc4c0fb0SBarry Smith 5038f6dfbefdSBarry Smith Note: 5039a83b1b31SSatish Balay A hyphen (-) must NOT be given at the beginning of the prefix name. 5040c7afd0dbSLois Curfman McInnes The first character of all runtime options is AUTOMATICALLY the hyphen. 5041d850072dSLois Curfman McInnes 50421cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESAppendOptionsPrefix()` 50433c7409f5SSatish Balay @*/ 5044d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetOptionsPrefix(SNES snes, const char prefix[]) 5045d71ae5a4SJacob Faibussowitsch { 50463a40ed3dSBarry Smith PetscFunctionBegin; 50470700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 50489566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes, prefix)); 50499566063dSJacob Faibussowitsch if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 505035f5d045SPeter Brune if (snes->linesearch) { 50519566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 50529566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch, prefix)); 505335f5d045SPeter Brune } 50549566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(snes->ksp, prefix)); 50553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50563c7409f5SSatish Balay } 50573c7409f5SSatish Balay 50583c7409f5SSatish Balay /*@C 5059f525115eSLois Curfman McInnes SNESAppendOptionsPrefix - Appends to the prefix used for searching for all 5060f6dfbefdSBarry Smith `SNES` options in the database. 50613c7409f5SSatish Balay 5062c3339decSBarry Smith Logically Collective 5063fee21e36SBarry Smith 5064c7afd0dbSLois Curfman McInnes Input Parameters: 5065f6dfbefdSBarry Smith + snes - the `SNES` context 5066c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names 5067c7afd0dbSLois Curfman McInnes 5068dc4c0fb0SBarry Smith Level: advanced 5069dc4c0fb0SBarry Smith 5070f6dfbefdSBarry Smith Note: 5071a83b1b31SSatish Balay A hyphen (-) must NOT be given at the beginning of the prefix name. 5072c7afd0dbSLois Curfman McInnes The first character of all runtime options is AUTOMATICALLY the hyphen. 5073d850072dSLois Curfman McInnes 50741cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetOptionsPrefix()`, `SNESSetOptionsPrefix()` 50753c7409f5SSatish Balay @*/ 5076d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESAppendOptionsPrefix(SNES snes, const char prefix[]) 5077d71ae5a4SJacob Faibussowitsch { 50783a40ed3dSBarry Smith PetscFunctionBegin; 50790700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 50809566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes, prefix)); 50819566063dSJacob Faibussowitsch if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 508235f5d045SPeter Brune if (snes->linesearch) { 50839566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 50849566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch, prefix)); 508535f5d045SPeter Brune } 50869566063dSJacob Faibussowitsch PetscCall(KSPAppendOptionsPrefix(snes->ksp, prefix)); 50873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50883c7409f5SSatish Balay } 50893c7409f5SSatish Balay 50909ab63eb5SSatish Balay /*@C 5091f6dfbefdSBarry Smith SNESGetOptionsPrefix - Gets the prefix used for searching for all 5092f6dfbefdSBarry Smith `SNES` options in the database. 50933c7409f5SSatish Balay 5094c7afd0dbSLois Curfman McInnes Not Collective 5095c7afd0dbSLois Curfman McInnes 50963c7409f5SSatish Balay Input Parameter: 5097f6dfbefdSBarry Smith . snes - the `SNES` context 50983c7409f5SSatish Balay 50993c7409f5SSatish Balay Output Parameter: 51003c7409f5SSatish Balay . prefix - pointer to the prefix string used 51013c7409f5SSatish Balay 510236851e7fSLois Curfman McInnes Level: advanced 510336851e7fSLois Curfman McInnes 5104420bcc1bSBarry Smith Fortran Note: 5105dc4c0fb0SBarry Smith The user should pass in a string 'prefix' of 5106dc4c0fb0SBarry Smith sufficient length to hold the prefix. 5107dc4c0fb0SBarry Smith 51081cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetOptionsPrefix()`, `SNESAppendOptionsPrefix()` 51093c7409f5SSatish Balay @*/ 5110d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetOptionsPrefix(SNES snes, const char *prefix[]) 5111d71ae5a4SJacob Faibussowitsch { 51123a40ed3dSBarry Smith PetscFunctionBegin; 51130700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 51149566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)snes, prefix)); 51153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 51163c7409f5SSatish Balay } 51173c7409f5SSatish Balay 51183cea93caSBarry Smith /*@C 51191c84c290SBarry Smith SNESRegister - Adds a method to the nonlinear solver package. 51201c84c290SBarry Smith 512120f4b53cSBarry Smith Not Collective 51221c84c290SBarry Smith 51231c84c290SBarry Smith Input Parameters: 512420f4b53cSBarry Smith + sname - name of a new user-defined solver 512520f4b53cSBarry Smith - function - routine to create method context 51261c84c290SBarry Smith 5127dc4c0fb0SBarry Smith Level: advanced 5128dc4c0fb0SBarry Smith 5129f6dfbefdSBarry Smith Note: 5130f6dfbefdSBarry Smith `SNESRegister()` may be called multiple times to add several user-defined solvers. 51311c84c290SBarry Smith 5132e4094ef1SJacob Faibussowitsch Example Usage: 51331c84c290SBarry Smith .vb 5134bdf89e91SBarry Smith SNESRegister("my_solver", MySolverCreate); 51351c84c290SBarry Smith .ve 51361c84c290SBarry Smith 51371c84c290SBarry Smith Then, your solver can be chosen with the procedural interface via 51381c84c290SBarry Smith $ SNESSetType(snes, "my_solver") 51391c84c290SBarry Smith or at runtime via the option 51401c84c290SBarry Smith $ -snes_type my_solver 51411c84c290SBarry Smith 51421cc06b55SBarry Smith .seealso: [](ch_snes), `SNESRegisterAll()`, `SNESRegisterDestroy()` 51433cea93caSBarry Smith @*/ 5144d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESRegister(const char sname[], PetscErrorCode (*function)(SNES)) 5145d71ae5a4SJacob Faibussowitsch { 5146b2002411SLois Curfman McInnes PetscFunctionBegin; 51479566063dSJacob Faibussowitsch PetscCall(SNESInitializePackage()); 51489566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&SNESList, sname, function)); 51493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5150b2002411SLois Curfman McInnes } 5151da9b6338SBarry Smith 5152d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestLocalMin(SNES snes) 5153d71ae5a4SJacob Faibussowitsch { 515477431f27SBarry Smith PetscInt N, i, j; 5155da9b6338SBarry Smith Vec u, uh, fh; 5156da9b6338SBarry Smith PetscScalar value; 5157da9b6338SBarry Smith PetscReal norm; 5158da9b6338SBarry Smith 5159da9b6338SBarry Smith PetscFunctionBegin; 51609566063dSJacob Faibussowitsch PetscCall(SNESGetSolution(snes, &u)); 51619566063dSJacob Faibussowitsch PetscCall(VecDuplicate(u, &uh)); 51629566063dSJacob Faibussowitsch PetscCall(VecDuplicate(u, &fh)); 5163da9b6338SBarry Smith 5164da9b6338SBarry Smith /* currently only works for sequential */ 51659566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Testing FormFunction() for local min\n")); 51669566063dSJacob Faibussowitsch PetscCall(VecGetSize(u, &N)); 5167da9b6338SBarry Smith for (i = 0; i < N; i++) { 51689566063dSJacob Faibussowitsch PetscCall(VecCopy(u, uh)); 516963a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "i = %" PetscInt_FMT "\n", i)); 5170da9b6338SBarry Smith for (j = -10; j < 11; j++) { 51718b49ba18SBarry Smith value = PetscSign(j) * PetscExpReal(PetscAbs(j) - 10.0); 51729566063dSJacob Faibussowitsch PetscCall(VecSetValue(uh, i, value, ADD_VALUES)); 51739566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, uh, fh)); 51749566063dSJacob Faibussowitsch PetscCall(VecNorm(fh, NORM_2, &norm)); 517563a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), " j norm %" PetscInt_FMT " %18.16e\n", j, (double)norm)); 5176da9b6338SBarry Smith value = -value; 51779566063dSJacob Faibussowitsch PetscCall(VecSetValue(uh, i, value, ADD_VALUES)); 5178da9b6338SBarry Smith } 5179da9b6338SBarry Smith } 51809566063dSJacob Faibussowitsch PetscCall(VecDestroy(&uh)); 51819566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fh)); 51823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5183da9b6338SBarry Smith } 518471f87433Sdalcinl 518571f87433Sdalcinl /*@ 5186f6dfbefdSBarry Smith SNESKSPSetUseEW - Sets `SNES` to the use Eisenstat-Walker method for 518771f87433Sdalcinl computing relative tolerance for linear solvers within an inexact 518871f87433Sdalcinl Newton method. 518971f87433Sdalcinl 5190c3339decSBarry Smith Logically Collective 519171f87433Sdalcinl 519271f87433Sdalcinl Input Parameters: 5193f6dfbefdSBarry Smith + snes - `SNES` context 5194f6dfbefdSBarry Smith - flag - `PETSC_TRUE` or `PETSC_FALSE` 519571f87433Sdalcinl 5196f6dfbefdSBarry Smith Options Database Keys: 519764ba62caSBarry Smith + -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence 519864ba62caSBarry Smith . -snes_ksp_ew_version ver - version of Eisenstat-Walker method 519964ba62caSBarry Smith . -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0 520064ba62caSBarry Smith . -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax 520164ba62caSBarry Smith . -snes_ksp_ew_gamma <gamma> - Sets gamma 520264ba62caSBarry Smith . -snes_ksp_ew_alpha <alpha> - Sets alpha 520364ba62caSBarry Smith . -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2 520464ba62caSBarry Smith - -snes_ksp_ew_threshold <threshold> - Sets threshold 520564ba62caSBarry Smith 5206dc4c0fb0SBarry Smith Level: advanced 5207dc4c0fb0SBarry Smith 5208f6dfbefdSBarry Smith Note: 5209f6dfbefdSBarry Smith The default is to use a constant relative tolerance for 521071f87433Sdalcinl the inner linear solvers. Alternatively, one can use the 52111d27aa22SBarry Smith Eisenstat-Walker method {cite}`ew96`, where the relative convergence tolerance 521271f87433Sdalcinl is reset at each Newton iteration according progress of the nonlinear 521371f87433Sdalcinl solver. 521471f87433Sdalcinl 52151cc06b55SBarry Smith .seealso: [](ch_snes), `KSP`, `SNES`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()` 521671f87433Sdalcinl @*/ 5217d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetUseEW(SNES snes, PetscBool flag) 5218d71ae5a4SJacob Faibussowitsch { 521971f87433Sdalcinl PetscFunctionBegin; 52200700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5221acfcf0e5SJed Brown PetscValidLogicalCollectiveBool(snes, flag, 2); 522271f87433Sdalcinl snes->ksp_ewconv = flag; 52233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 522471f87433Sdalcinl } 522571f87433Sdalcinl 522671f87433Sdalcinl /*@ 5227f6dfbefdSBarry Smith SNESKSPGetUseEW - Gets if `SNES` is using Eisenstat-Walker method 522871f87433Sdalcinl for computing relative tolerance for linear solvers within an 522971f87433Sdalcinl inexact Newton method. 523071f87433Sdalcinl 523171f87433Sdalcinl Not Collective 523271f87433Sdalcinl 523371f87433Sdalcinl Input Parameter: 5234f6dfbefdSBarry Smith . snes - `SNES` context 523571f87433Sdalcinl 523671f87433Sdalcinl Output Parameter: 5237f6dfbefdSBarry Smith . flag - `PETSC_TRUE` or `PETSC_FALSE` 523871f87433Sdalcinl 523971f87433Sdalcinl Level: advanced 524071f87433Sdalcinl 52411cc06b55SBarry Smith .seealso: [](ch_snes), `SNESKSPSetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()` 524271f87433Sdalcinl @*/ 5243d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag) 5244d71ae5a4SJacob Faibussowitsch { 524571f87433Sdalcinl PetscFunctionBegin; 52460700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 52474f572ea9SToby Isaac PetscAssertPointer(flag, 2); 524871f87433Sdalcinl *flag = snes->ksp_ewconv; 52493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 525071f87433Sdalcinl } 525171f87433Sdalcinl 525271f87433Sdalcinl /*@ 5253fa9f3622SBarry Smith SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker 525471f87433Sdalcinl convergence criteria for the linear solvers within an inexact 525571f87433Sdalcinl Newton method. 525671f87433Sdalcinl 5257c3339decSBarry Smith Logically Collective 525871f87433Sdalcinl 525971f87433Sdalcinl Input Parameters: 5260f6dfbefdSBarry Smith + snes - `SNES` context 52610f0abf79SStefano Zampini . version - version 1, 2 (default is 2), 3 or 4 526271f87433Sdalcinl . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 526371f87433Sdalcinl . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 526471f87433Sdalcinl . gamma - multiplicative factor for version 2 rtol computation 526571f87433Sdalcinl (0 <= gamma2 <= 1) 526671f87433Sdalcinl . alpha - power for version 2 rtol computation (1 < alpha <= 2) 526771f87433Sdalcinl . alpha2 - power for safeguard 526871f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1) 526971f87433Sdalcinl 5270dc4c0fb0SBarry Smith Level: advanced 5271dc4c0fb0SBarry Smith 5272f6dfbefdSBarry Smith Notes: 527371f87433Sdalcinl Version 3 was contributed by Luis Chacon, June 2006. 527471f87433Sdalcinl 5275f6dfbefdSBarry Smith Use `PETSC_DEFAULT` to retain the default for any of the parameters. 527671f87433Sdalcinl 52771cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()` 527871f87433Sdalcinl @*/ 5279d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetParametersEW(SNES snes, PetscInt version, PetscReal rtol_0, PetscReal rtol_max, PetscReal gamma, PetscReal alpha, PetscReal alpha2, PetscReal threshold) 5280d71ae5a4SJacob Faibussowitsch { 5281fa9f3622SBarry Smith SNESKSPEW *kctx; 52825fd66863SKarl Rupp 528371f87433Sdalcinl PetscFunctionBegin; 52840700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5285fa9f3622SBarry Smith kctx = (SNESKSPEW *)snes->kspconvctx; 52865f80ce2aSJacob Faibussowitsch PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing"); 5287c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, version, 2); 5288c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, rtol_0, 3); 5289c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, rtol_max, 4); 5290c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, gamma, 5); 5291c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, alpha, 6); 5292c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, alpha2, 7); 5293c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, threshold, 8); 529471f87433Sdalcinl 529571f87433Sdalcinl if (version != PETSC_DEFAULT) kctx->version = version; 529613bcc0bdSJacob Faibussowitsch if (rtol_0 != (PetscReal)PETSC_DEFAULT) kctx->rtol_0 = rtol_0; 529713bcc0bdSJacob Faibussowitsch if (rtol_max != (PetscReal)PETSC_DEFAULT) kctx->rtol_max = rtol_max; 529813bcc0bdSJacob Faibussowitsch if (gamma != (PetscReal)PETSC_DEFAULT) kctx->gamma = gamma; 529913bcc0bdSJacob Faibussowitsch if (alpha != (PetscReal)PETSC_DEFAULT) kctx->alpha = alpha; 530013bcc0bdSJacob Faibussowitsch if (alpha2 != (PetscReal)PETSC_DEFAULT) kctx->alpha2 = alpha2; 530113bcc0bdSJacob Faibussowitsch if (threshold != (PetscReal)PETSC_DEFAULT) kctx->threshold = threshold; 530271f87433Sdalcinl 53030f0abf79SStefano 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); 53040b121fc5SBarry 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); 53050b121fc5SBarry 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); 53060b121fc5SBarry 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); 53070b121fc5SBarry 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); 53080b121fc5SBarry 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); 53093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 531071f87433Sdalcinl } 531171f87433Sdalcinl 531271f87433Sdalcinl /*@ 5313fa9f3622SBarry Smith SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker 531471f87433Sdalcinl convergence criteria for the linear solvers within an inexact 531571f87433Sdalcinl Newton method. 531671f87433Sdalcinl 531771f87433Sdalcinl Not Collective 531871f87433Sdalcinl 531997bb3fdcSJose E. Roman Input Parameter: 5320f6dfbefdSBarry Smith . snes - `SNES` context 532171f87433Sdalcinl 532271f87433Sdalcinl Output Parameters: 53230f0abf79SStefano Zampini + version - version 1, 2 (default is 2), 3 or 4 532471f87433Sdalcinl . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 532571f87433Sdalcinl . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 5326bf388a1fSBarry Smith . gamma - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1) 532771f87433Sdalcinl . alpha - power for version 2 rtol computation (1 < alpha <= 2) 532871f87433Sdalcinl . alpha2 - power for safeguard 532971f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1) 533071f87433Sdalcinl 533171f87433Sdalcinl Level: advanced 533271f87433Sdalcinl 53331cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPSetParametersEW()` 533471f87433Sdalcinl @*/ 5335d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetParametersEW(SNES snes, PetscInt *version, PetscReal *rtol_0, PetscReal *rtol_max, PetscReal *gamma, PetscReal *alpha, PetscReal *alpha2, PetscReal *threshold) 5336d71ae5a4SJacob Faibussowitsch { 5337fa9f3622SBarry Smith SNESKSPEW *kctx; 53385fd66863SKarl Rupp 533971f87433Sdalcinl PetscFunctionBegin; 53400700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5341fa9f3622SBarry Smith kctx = (SNESKSPEW *)snes->kspconvctx; 53425f80ce2aSJacob Faibussowitsch PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing"); 534371f87433Sdalcinl if (version) *version = kctx->version; 534471f87433Sdalcinl if (rtol_0) *rtol_0 = kctx->rtol_0; 534571f87433Sdalcinl if (rtol_max) *rtol_max = kctx->rtol_max; 534671f87433Sdalcinl if (gamma) *gamma = kctx->gamma; 534771f87433Sdalcinl if (alpha) *alpha = kctx->alpha; 534871f87433Sdalcinl if (alpha2) *alpha2 = kctx->alpha2; 534971f87433Sdalcinl if (threshold) *threshold = kctx->threshold; 53503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 535171f87433Sdalcinl } 535271f87433Sdalcinl 53535c0db29aSPierre Jolivet PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx) 5354d71ae5a4SJacob Faibussowitsch { 53555c0db29aSPierre Jolivet SNES snes = (SNES)ctx; 5356fa9f3622SBarry Smith SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx; 535771f87433Sdalcinl PetscReal rtol = PETSC_DEFAULT, stol; 535871f87433Sdalcinl 535971f87433Sdalcinl PetscFunctionBegin; 53603ba16761SJacob Faibussowitsch if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS); 536130058271SDmitry Karpeev if (!snes->iter) { 536230058271SDmitry Karpeev rtol = kctx->rtol_0; /* first time in, so use the original user rtol */ 53639566063dSJacob Faibussowitsch PetscCall(VecNorm(snes->vec_func, NORM_2, &kctx->norm_first)); 53640f0abf79SStefano Zampini } else { 53650fdf79fbSJacob 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); 536671f87433Sdalcinl if (kctx->version == 1) { 53670f0abf79SStefano Zampini rtol = PetscAbsReal(snes->norm - kctx->lresid_last) / kctx->norm_last; 536885ec1a3cSBarry Smith stol = PetscPowReal(kctx->rtol_last, kctx->alpha2); 536971f87433Sdalcinl if (stol > kctx->threshold) rtol = PetscMax(rtol, stol); 537071f87433Sdalcinl } else if (kctx->version == 2) { 537185ec1a3cSBarry Smith rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha); 537285ec1a3cSBarry Smith stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha); 537371f87433Sdalcinl if (stol > kctx->threshold) rtol = PetscMax(rtol, stol); 537471f87433Sdalcinl } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */ 537585ec1a3cSBarry Smith rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha); 537671f87433Sdalcinl /* safeguard: avoid sharp decrease of rtol */ 537785ec1a3cSBarry Smith stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha); 537871f87433Sdalcinl stol = PetscMax(rtol, stol); 537971f87433Sdalcinl rtol = PetscMin(kctx->rtol_0, stol); 538071f87433Sdalcinl /* safeguard: avoid oversolving */ 538130058271SDmitry Karpeev stol = kctx->gamma * (kctx->norm_first * snes->rtol) / snes->norm; 538271f87433Sdalcinl stol = PetscMax(rtol, stol); 538371f87433Sdalcinl rtol = PetscMin(kctx->rtol_0, stol); 53840fdf79fbSJacob Faibussowitsch } else /* if (kctx->version == 4) */ { 53850fdf79fbSJacob Faibussowitsch /* H.-B. An et al. Journal of Computational and Applied Mathematics 200 (2007) 47-60 */ 53860f0abf79SStefano Zampini PetscReal ared = PetscAbsReal(kctx->norm_last - snes->norm); 53870f0abf79SStefano Zampini PetscReal pred = PetscAbsReal(kctx->norm_last - kctx->lresid_last); 53880f0abf79SStefano Zampini PetscReal rk = ared / pred; 53890f0abf79SStefano Zampini if (rk < kctx->v4_p1) rtol = 1. - 2. * kctx->v4_p1; 53900f0abf79SStefano Zampini else if (rk < kctx->v4_p2) rtol = kctx->rtol_last; 53910f0abf79SStefano Zampini else if (rk < kctx->v4_p3) rtol = kctx->v4_m1 * kctx->rtol_last; 53920f0abf79SStefano Zampini else rtol = kctx->v4_m2 * kctx->rtol_last; 53930f0abf79SStefano Zampini 5394a4598233SStefano 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; 53950f0abf79SStefano Zampini kctx->rtol_last_2 = kctx->rtol_last; 53960f0abf79SStefano Zampini kctx->rk_last_2 = kctx->rk_last; 53970f0abf79SStefano Zampini kctx->rk_last = rk; 53980fdf79fbSJacob Faibussowitsch } 53990f0abf79SStefano Zampini } 54000f0abf79SStefano Zampini /* safeguard: avoid rtol greater than rtol_max */ 540171f87433Sdalcinl rtol = PetscMin(rtol, kctx->rtol_max); 54029566063dSJacob Faibussowitsch PetscCall(KSPSetTolerances(ksp, rtol, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT)); 540363a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "iter %" PetscInt_FMT ", Eisenstat-Walker (version %" PetscInt_FMT ") KSP rtol=%g\n", snes->iter, kctx->version, (double)rtol)); 54043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 540571f87433Sdalcinl } 540671f87433Sdalcinl 54075c0db29aSPierre Jolivet PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx) 5408d71ae5a4SJacob Faibussowitsch { 54095c0db29aSPierre Jolivet SNES snes = (SNES)ctx; 5410fa9f3622SBarry Smith SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx; 541171f87433Sdalcinl PCSide pcside; 541271f87433Sdalcinl Vec lres; 541371f87433Sdalcinl 541471f87433Sdalcinl PetscFunctionBegin; 54153ba16761SJacob Faibussowitsch if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS); 54169566063dSJacob Faibussowitsch PetscCall(KSPGetTolerances(ksp, &kctx->rtol_last, NULL, NULL, NULL)); 541771dbe336SPeter Brune kctx->norm_last = snes->norm; 54180f0abf79SStefano Zampini if (kctx->version == 1 || kctx->version == 4) { 54194f00ce20SMatthew G. Knepley PC pc; 54200f0abf79SStefano Zampini PetscBool getRes; 54214f00ce20SMatthew G. Knepley 54229566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksp, &pc)); 54230f0abf79SStefano Zampini PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &getRes)); 54240f0abf79SStefano Zampini if (!getRes) { 54250f0abf79SStefano Zampini KSPNormType normtype; 54260f0abf79SStefano Zampini 54270f0abf79SStefano Zampini PetscCall(KSPGetNormType(ksp, &normtype)); 54280f0abf79SStefano Zampini getRes = (PetscBool)(normtype == KSP_NORM_UNPRECONDITIONED); 54290f0abf79SStefano Zampini } 54309566063dSJacob Faibussowitsch PetscCall(KSPGetPCSide(ksp, &pcside)); 54310f0abf79SStefano Zampini if (pcside == PC_RIGHT || getRes) { /* KSP residual is true linear residual */ 54329566063dSJacob Faibussowitsch PetscCall(KSPGetResidualNorm(ksp, &kctx->lresid_last)); 543371f87433Sdalcinl } else { 543471f87433Sdalcinl /* KSP residual is preconditioned residual */ 543571f87433Sdalcinl /* compute true linear residual norm */ 54360f0abf79SStefano Zampini Mat J; 54370f0abf79SStefano Zampini PetscCall(KSPGetOperators(ksp, &J, NULL)); 54389566063dSJacob Faibussowitsch PetscCall(VecDuplicate(b, &lres)); 54390f0abf79SStefano Zampini PetscCall(MatMult(J, x, lres)); 54409566063dSJacob Faibussowitsch PetscCall(VecAYPX(lres, -1.0, b)); 54419566063dSJacob Faibussowitsch PetscCall(VecNorm(lres, NORM_2, &kctx->lresid_last)); 54429566063dSJacob Faibussowitsch PetscCall(VecDestroy(&lres)); 544371f87433Sdalcinl } 544471f87433Sdalcinl } 54453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 544671f87433Sdalcinl } 544771f87433Sdalcinl 5448d4211eb9SBarry Smith /*@ 5449f6dfbefdSBarry Smith SNESGetKSP - Returns the `KSP` context for a `SNES` solver. 5450d4211eb9SBarry Smith 5451420bcc1bSBarry Smith Not Collective, but if `snes` is parallel, then `ksp` is parallel 5452d4211eb9SBarry Smith 5453d4211eb9SBarry Smith Input Parameter: 5454f6dfbefdSBarry Smith . snes - the `SNES` context 5455d4211eb9SBarry Smith 5456d4211eb9SBarry Smith Output Parameter: 5457f6dfbefdSBarry Smith . ksp - the `KSP` context 5458d4211eb9SBarry Smith 5459dc4c0fb0SBarry Smith Level: beginner 5460dc4c0fb0SBarry Smith 5461d4211eb9SBarry Smith Notes: 5462f6dfbefdSBarry Smith The user can then directly manipulate the `KSP` context to set various 5463d4211eb9SBarry Smith options, etc. Likewise, the user can then extract and manipulate the 5464f6dfbefdSBarry Smith `PC` contexts as well. 5465f6dfbefdSBarry Smith 5466f6dfbefdSBarry Smith Some `SNESType`s do not use a `KSP` but a `KSP` is still returned by this function 5467d4211eb9SBarry Smith 54681cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSP`, `PC`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()` 5469d4211eb9SBarry Smith @*/ 5470d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetKSP(SNES snes, KSP *ksp) 5471d71ae5a4SJacob Faibussowitsch { 547271f87433Sdalcinl PetscFunctionBegin; 5473d4211eb9SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 54744f572ea9SToby Isaac PetscAssertPointer(ksp, 2); 5475d4211eb9SBarry Smith 5476d4211eb9SBarry Smith if (!snes->ksp) { 54779566063dSJacob Faibussowitsch PetscCall(KSPCreate(PetscObjectComm((PetscObject)snes), &snes->ksp)); 54789566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->ksp, (PetscObject)snes, 1)); 5479d4211eb9SBarry Smith 54805c0db29aSPierre Jolivet PetscCall(KSPSetPreSolve(snes->ksp, KSPPreSolve_SNESEW, snes)); 54815c0db29aSPierre Jolivet PetscCall(KSPSetPostSolve(snes->ksp, KSPPostSolve_SNESEW, snes)); 5482a5c2985bSBarry Smith 54839566063dSJacob Faibussowitsch PetscCall(KSPMonitorSetFromOptions(snes->ksp, "-snes_monitor_ksp", "snes_preconditioned_residual", snes)); 54849566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptions((PetscObject)snes->ksp, ((PetscObject)snes)->options)); 5485d4211eb9SBarry Smith } 5486d4211eb9SBarry Smith *ksp = snes->ksp; 54873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 548871f87433Sdalcinl } 54896c699258SBarry Smith 5490af0996ceSBarry Smith #include <petsc/private/dmimpl.h> 54916c699258SBarry Smith /*@ 5492f6dfbefdSBarry Smith SNESSetDM - Sets the `DM` that may be used by some nonlinear solvers or their underlying preconditioners 54936c699258SBarry Smith 5494c3339decSBarry Smith Logically Collective 54956c699258SBarry Smith 54966c699258SBarry Smith Input Parameters: 54972a808120SBarry Smith + snes - the nonlinear solver context 5498420bcc1bSBarry Smith - dm - the `DM`, cannot be `NULL` 5499dc4c0fb0SBarry Smith 5500dc4c0fb0SBarry Smith Level: intermediate 55016c699258SBarry Smith 5502f6dfbefdSBarry Smith Note: 5503f6dfbefdSBarry Smith A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`, 5504f6dfbefdSBarry Smith even when not using interfaces like `DMSNESSetFunction()`. Use `DMClone()` to get a distinct `DM` when solving different 5505e03a659cSJed Brown problems using the same function space. 5506e03a659cSJed Brown 5507420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()` 55086c699258SBarry Smith @*/ 5509d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDM(SNES snes, DM dm) 5510d71ae5a4SJacob Faibussowitsch { 5511345fed2cSBarry Smith KSP ksp; 5512942e3340SBarry Smith DMSNES sdm; 55136c699258SBarry Smith 55146c699258SBarry Smith PetscFunctionBegin; 55150700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 55162a808120SBarry Smith PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 55179566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 5518942e3340SBarry Smith if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */ 551951f4b3c7SToby Isaac if (snes->dm->dmsnes && !dm->dmsnes) { 55209566063dSJacob Faibussowitsch PetscCall(DMCopyDMSNES(snes->dm, dm)); 55219566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(snes->dm, &sdm)); 5522f5af7f23SKarl Rupp if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */ 55236cab3a1bSJed Brown } 55249566063dSJacob Faibussowitsch PetscCall(DMCoarsenHookRemove(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes)); 55259566063dSJacob Faibussowitsch PetscCall(DMDestroy(&snes->dm)); 55266cab3a1bSJed Brown } 55276c699258SBarry Smith snes->dm = dm; 5528116d1032SJed Brown snes->dmAuto = PETSC_FALSE; 5529f5af7f23SKarl Rupp 55309566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 55319566063dSJacob Faibussowitsch PetscCall(KSPSetDM(ksp, dm)); 55329566063dSJacob Faibussowitsch PetscCall(KSPSetDMActive(ksp, PETSC_FALSE)); 5533efd4aadfSBarry Smith if (snes->npc) { 55349566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes->npc, snes->dm)); 55359566063dSJacob Faibussowitsch PetscCall(SNESSetNPCSide(snes, snes->npcside)); 55362c155ee1SBarry Smith } 55373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 55386c699258SBarry Smith } 55396c699258SBarry Smith 55406c699258SBarry Smith /*@ 5541420bcc1bSBarry Smith SNESGetDM - Gets the `DM` that may be used by some solvers/preconditioners 55426c699258SBarry Smith 5543f6dfbefdSBarry Smith Not Collective but dm obtained is parallel on snes 55446c699258SBarry Smith 55456c699258SBarry Smith Input Parameter: 5546420bcc1bSBarry Smith . snes - the `SNES` context 55476c699258SBarry Smith 55486c699258SBarry Smith Output Parameter: 5549420bcc1bSBarry Smith . dm - the `DM` 55506c699258SBarry Smith 55516c699258SBarry Smith Level: intermediate 55526c699258SBarry Smith 5553420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESSetDM()`, `KSPSetDM()`, `KSPGetDM()` 55546c699258SBarry Smith @*/ 5555d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDM(SNES snes, DM *dm) 5556d71ae5a4SJacob Faibussowitsch { 55576c699258SBarry Smith PetscFunctionBegin; 55580700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 55596cab3a1bSJed Brown if (!snes->dm) { 55609566063dSJacob Faibussowitsch PetscCall(DMShellCreate(PetscObjectComm((PetscObject)snes), &snes->dm)); 5561116d1032SJed Brown snes->dmAuto = PETSC_TRUE; 55626cab3a1bSJed Brown } 55636c699258SBarry Smith *dm = snes->dm; 55643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 55656c699258SBarry Smith } 55660807856dSBarry Smith 556731823bd8SMatthew G Knepley /*@ 5568be95d8f1SBarry Smith SNESSetNPC - Sets the nonlinear preconditioner to be used. 556931823bd8SMatthew G Knepley 5570c3339decSBarry Smith Collective 557131823bd8SMatthew G Knepley 557231823bd8SMatthew G Knepley Input Parameters: 5573f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 5574420bcc1bSBarry Smith - npc - the nonlinear preconditioner object 557531823bd8SMatthew G Knepley 5576dc4c0fb0SBarry Smith Level: developer 5577dc4c0fb0SBarry Smith 557831823bd8SMatthew G Knepley Notes: 5579f6dfbefdSBarry Smith Use `SNESGetNPC()` to retrieve the preconditioner context (for example, 558031823bd8SMatthew G Knepley to configure it using the API). 558131823bd8SMatthew G Knepley 5582f6dfbefdSBarry Smith Only some `SNESType` can use a nonlinear preconditioner 5583f6dfbefdSBarry Smith 5584420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNGS`, `SNESFAS`, `SNESGetNPC()`, `SNESHasNPC()` 558531823bd8SMatthew G Knepley @*/ 5586d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPC(SNES snes, SNES npc) 5587d71ae5a4SJacob Faibussowitsch { 558831823bd8SMatthew G Knepley PetscFunctionBegin; 558931823bd8SMatthew G Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5590f6dfbefdSBarry Smith PetscValidHeaderSpecific(npc, SNES_CLASSID, 2); 5591f6dfbefdSBarry Smith PetscCheckSameComm(snes, 1, npc, 2); 5592f6dfbefdSBarry Smith PetscCall(PetscObjectReference((PetscObject)npc)); 55939566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&snes->npc)); 5594f6dfbefdSBarry Smith snes->npc = npc; 55953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 559631823bd8SMatthew G Knepley } 559731823bd8SMatthew G Knepley 559831823bd8SMatthew G Knepley /*@ 5599f6dfbefdSBarry Smith SNESGetNPC - Gets a nonlinear preconditioning solver SNES` to be used to precondition the original nonlinear solver. 560031823bd8SMatthew G Knepley 5601f6dfbefdSBarry Smith Not Collective; but any changes to the obtained the npc object must be applied collectively 560231823bd8SMatthew G Knepley 560331823bd8SMatthew G Knepley Input Parameter: 5604f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 560531823bd8SMatthew G Knepley 560631823bd8SMatthew G Knepley Output Parameter: 5607e4094ef1SJacob Faibussowitsch . pc - preconditioner context 560831823bd8SMatthew G Knepley 5609f6dfbefdSBarry Smith Options Database Key: 5610f6dfbefdSBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner 5611b5badacbSBarry Smith 5612dc4c0fb0SBarry Smith Level: developer 5613dc4c0fb0SBarry Smith 561495452b02SPatrick Sanan Notes: 5615f6dfbefdSBarry Smith If a `SNES` was previously set with `SNESSetNPC()` then that value is returned, otherwise a new `SNES` object is created. 5616be95d8f1SBarry Smith 5617f6dfbefdSBarry Smith The (preconditioner) `SNES` returned automatically inherits the same nonlinear function and Jacobian supplied to the original 5618f6dfbefdSBarry Smith `SNES` 5619951fe5abSBarry Smith 56201cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESHasNPC()`, `SNES`, `SNESCreate()` 562131823bd8SMatthew G Knepley @*/ 5622d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPC(SNES snes, SNES *pc) 5623d71ae5a4SJacob Faibussowitsch { 5624a64e098fSPeter Brune const char *optionsprefix; 562531823bd8SMatthew G Knepley 562631823bd8SMatthew G Knepley PetscFunctionBegin; 562731823bd8SMatthew G Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 56284f572ea9SToby Isaac PetscAssertPointer(pc, 2); 5629efd4aadfSBarry Smith if (!snes->npc) { 5630ec785e5bSStefano Zampini void *ctx; 5631ec785e5bSStefano Zampini 56329566063dSJacob Faibussowitsch PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &snes->npc)); 56339566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->npc, (PetscObject)snes, 1)); 56349566063dSJacob Faibussowitsch PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 56359566063dSJacob Faibussowitsch PetscCall(SNESSetOptionsPrefix(snes->npc, optionsprefix)); 56369566063dSJacob Faibussowitsch PetscCall(SNESAppendOptionsPrefix(snes->npc, "npc_")); 5637fb87a551SStefano Zampini if (snes->ops->usercompute) { 5638fb87a551SStefano Zampini PetscCall(SNESSetComputeApplicationContext(snes, snes->ops->usercompute, snes->ops->userdestroy)); 5639fb87a551SStefano Zampini } else { 5640ec785e5bSStefano Zampini PetscCall(SNESGetApplicationContext(snes, &ctx)); 5641ec785e5bSStefano Zampini PetscCall(SNESSetApplicationContext(snes->npc, ctx)); 5642fb87a551SStefano Zampini } 56439566063dSJacob Faibussowitsch PetscCall(SNESSetCountersReset(snes->npc, PETSC_FALSE)); 564431823bd8SMatthew G Knepley } 5645efd4aadfSBarry Smith *pc = snes->npc; 56463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 564731823bd8SMatthew G Knepley } 564831823bd8SMatthew G Knepley 56493ad1a0b9SPatrick Farrell /*@ 56503ad1a0b9SPatrick Farrell SNESHasNPC - Returns whether a nonlinear preconditioner exists 56513ad1a0b9SPatrick Farrell 56523ad1a0b9SPatrick Farrell Not Collective 56533ad1a0b9SPatrick Farrell 56543ad1a0b9SPatrick Farrell Input Parameter: 5655f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 56563ad1a0b9SPatrick Farrell 56573ad1a0b9SPatrick Farrell Output Parameter: 5658420bcc1bSBarry Smith . has_npc - whether the `SNES` has a nonlinear preconditioner or not 56593ad1a0b9SPatrick Farrell 56603ad1a0b9SPatrick Farrell Level: developer 56613ad1a0b9SPatrick Farrell 56621cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESGetNPC()` 56633ad1a0b9SPatrick Farrell @*/ 5664d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc) 5665d71ae5a4SJacob Faibussowitsch { 56663ad1a0b9SPatrick Farrell PetscFunctionBegin; 56673ad1a0b9SPatrick Farrell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5668efd4aadfSBarry Smith *has_npc = (PetscBool)(snes->npc ? PETSC_TRUE : PETSC_FALSE); 56693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 56703ad1a0b9SPatrick Farrell } 56713ad1a0b9SPatrick Farrell 5672c40d0f55SPeter Brune /*@ 5673420bcc1bSBarry Smith SNESSetNPCSide - Sets the nonlinear preconditioning side. 5674c40d0f55SPeter Brune 5675c3339decSBarry Smith Logically Collective 5676c40d0f55SPeter Brune 5677c40d0f55SPeter Brune Input Parameter: 5678f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 5679c40d0f55SPeter Brune 5680c40d0f55SPeter Brune Output Parameter: 5681c40d0f55SPeter Brune . side - the preconditioning side, where side is one of 5682c40d0f55SPeter Brune .vb 56832d547940SBarry Smith PC_LEFT - left preconditioning 56842d547940SBarry Smith PC_RIGHT - right preconditioning (default for most nonlinear solvers) 5685c40d0f55SPeter Brune .ve 5686c40d0f55SPeter Brune 5687f6dfbefdSBarry Smith Options Database Key: 568867b8a455SSatish Balay . -snes_npc_side <right,left> - nonlinear preconditioner side 5689c40d0f55SPeter Brune 5690dc4c0fb0SBarry Smith Level: intermediate 5691dc4c0fb0SBarry Smith 5692f6dfbefdSBarry Smith Note: 5693f6dfbefdSBarry Smith `SNESNRICHARDSON` and `SNESNCG` only support left preconditioning. 56942d547940SBarry Smith 5695420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNRICHARDSON`, `SNESNCG`, `SNESType`, `SNESGetNPCSide()`, `KSPSetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide` 5696c40d0f55SPeter Brune @*/ 5697d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPCSide(SNES snes, PCSide side) 5698d71ae5a4SJacob Faibussowitsch { 5699c40d0f55SPeter Brune PetscFunctionBegin; 5700c40d0f55SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5701c40d0f55SPeter Brune PetscValidLogicalCollectiveEnum(snes, side, 2); 5702b552625fSStefano Zampini if (side == PC_SIDE_DEFAULT) side = PC_RIGHT; 570354c59aa7SJacob Faibussowitsch PetscCheck((side == PC_LEFT) || (side == PC_RIGHT), PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Only PC_LEFT and PC_RIGHT are supported"); 5704efd4aadfSBarry Smith snes->npcside = side; 57053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5706c40d0f55SPeter Brune } 5707c40d0f55SPeter Brune 5708c40d0f55SPeter Brune /*@ 5709be95d8f1SBarry Smith SNESGetNPCSide - Gets the preconditioning side. 5710c40d0f55SPeter Brune 5711c40d0f55SPeter Brune Not Collective 5712c40d0f55SPeter Brune 5713c40d0f55SPeter Brune Input Parameter: 5714f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 5715c40d0f55SPeter Brune 5716c40d0f55SPeter Brune Output Parameter: 5717c40d0f55SPeter Brune . side - the preconditioning side, where side is one of 5718c40d0f55SPeter Brune .vb 5719f6dfbefdSBarry Smith `PC_LEFT` - left preconditioning 5720f6dfbefdSBarry Smith `PC_RIGHT` - right preconditioning (default for most nonlinear solvers) 5721c40d0f55SPeter Brune .ve 5722c40d0f55SPeter Brune 5723c40d0f55SPeter Brune Level: intermediate 5724c40d0f55SPeter Brune 5725420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNPCSide()`, `KSPGetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide` 5726c40d0f55SPeter Brune @*/ 5727d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPCSide(SNES snes, PCSide *side) 5728d71ae5a4SJacob Faibussowitsch { 5729c40d0f55SPeter Brune PetscFunctionBegin; 5730c40d0f55SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 57314f572ea9SToby Isaac PetscAssertPointer(side, 2); 5732efd4aadfSBarry Smith *side = snes->npcside; 57333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5734c40d0f55SPeter Brune } 5735c40d0f55SPeter Brune 57369e764e56SPeter Brune /*@ 5737420bcc1bSBarry Smith SNESSetLineSearch - Sets the linesearch to be used for `SNES` 57389e764e56SPeter Brune 5739c3339decSBarry Smith Collective 57409e764e56SPeter Brune 57419e764e56SPeter Brune Input Parameters: 5742f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 57439e764e56SPeter Brune - linesearch - the linesearch object 57449e764e56SPeter Brune 5745dc4c0fb0SBarry Smith Level: developer 5746dc4c0fb0SBarry Smith 5747f6dfbefdSBarry Smith Note: 5748420bcc1bSBarry Smith This is almost never used, rather one uses `SNESGetLineSearch()` to retrieve the line search and set options on it 57499e764e56SPeter Brune to configure it using the API). 57509e764e56SPeter Brune 5751420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()` 57529e764e56SPeter Brune @*/ 5753d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch) 5754d71ae5a4SJacob Faibussowitsch { 57559e764e56SPeter Brune PetscFunctionBegin; 57569e764e56SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5757f1c6b773SPeter Brune PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 2); 57589e764e56SPeter Brune PetscCheckSameComm(snes, 1, linesearch, 2); 57599566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)linesearch)); 57609566063dSJacob Faibussowitsch PetscCall(SNESLineSearchDestroy(&snes->linesearch)); 5761f5af7f23SKarl Rupp 57629e764e56SPeter Brune snes->linesearch = linesearch; 57633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 57649e764e56SPeter Brune } 57659e764e56SPeter Brune 5766a34ceb2aSJed Brown /*@ 5767420bcc1bSBarry Smith SNESGetLineSearch - Returns the line search context possibly set with `SNESSetLineSearch()` 5768f6dfbefdSBarry Smith or creates a default line search instance associated with the `SNES` and returns it. 57699e764e56SPeter Brune 57709e764e56SPeter Brune Not Collective 57719e764e56SPeter Brune 57729e764e56SPeter Brune Input Parameter: 5773f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 57749e764e56SPeter Brune 57759e764e56SPeter Brune Output Parameter: 57769e764e56SPeter Brune . linesearch - linesearch context 57779e764e56SPeter Brune 5778162e0bf5SPeter Brune Level: beginner 57799e764e56SPeter Brune 57801cc06b55SBarry Smith .seealso: [](ch_snes), `SNESLineSearch`, `SNESSetLineSearch()`, `SNESLineSearchCreate()` 57819e764e56SPeter Brune @*/ 5782d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch) 5783d71ae5a4SJacob Faibussowitsch { 57849e764e56SPeter Brune const char *optionsprefix; 57859e764e56SPeter Brune 57869e764e56SPeter Brune PetscFunctionBegin; 57879e764e56SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 57884f572ea9SToby Isaac PetscAssertPointer(linesearch, 2); 57899e764e56SPeter Brune if (!snes->linesearch) { 57909566063dSJacob Faibussowitsch PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 57919566063dSJacob Faibussowitsch PetscCall(SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch)); 57929566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetSNES(snes->linesearch, snes)); 57939566063dSJacob Faibussowitsch PetscCall(SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix)); 57949566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->linesearch, (PetscObject)snes, 1)); 57959e764e56SPeter Brune } 57969e764e56SPeter Brune *linesearch = snes->linesearch; 57973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 57989e764e56SPeter Brune } 5799