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 1351cc06b55SBarry Smith .seealso: [](ch_snes), `SNESCreate()`, `SNESSetFunction()`, `SNESFunction`, `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 1651cc06b55SBarry Smith .seealso: [](ch_snes), `SNESCreate()`, `SNESSetFunction()`, `SNESFunction()`, `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 1921cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESCreate()`, `SNESSetFunction()`, `SNESFunction()`, `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 2151cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSetFunction()`, `SNESFunction()`, `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; 4088404b7f3SBarry Smith PetscErrorCode (*cJ)(SNES, Vec, Mat, Mat, void *); 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; 68725ce1634SJed Brown PetscErrorCode (*jac)(SNES, Vec, Mat, Mat, void *) = 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 183688f0584fSBarry Smith /*MC 1837f6dfbefdSBarry Smith SNESFunction - Functional form used to convey the nonlinear function to `SNES` in `SNESSetFunction()` 183888f0584fSBarry Smith 183988f0584fSBarry Smith Synopsis: 1840411c0326SBarry Smith #include "petscsnes.h" 1841411c0326SBarry Smith PetscErrorCode SNESFunction(SNES snes,Vec x,Vec f,void *ctx); 184288f0584fSBarry Smith 1843c3339decSBarry Smith Collective 18441843f636SBarry Smith 184588f0584fSBarry Smith Input Parameters: 1846f6dfbefdSBarry Smith + snes - the `SNES` context 184788f0584fSBarry Smith . x - state at which to evaluate residual 1848f6dfbefdSBarry Smith - ctx - optional user-defined function context, passed in with `SNESSetFunction()` 184988f0584fSBarry Smith 185088f0584fSBarry Smith Output Parameter: 185188f0584fSBarry Smith . f - vector to put residual (function value) 185288f0584fSBarry Smith 1853878cb397SSatish Balay Level: intermediate 1854878cb397SSatish Balay 18551cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetFunction()`, `SNESGetFunction()` 185688f0584fSBarry Smith M*/ 185788f0584fSBarry Smith 18589b94acceSBarry Smith /*@C 18599b94acceSBarry Smith SNESSetFunction - Sets the function evaluation routine and function 1860f6dfbefdSBarry Smith vector for use by the `SNES` routines in solving systems of nonlinear 18619b94acceSBarry Smith equations. 18629b94acceSBarry Smith 1863c3339decSBarry Smith Logically Collective 1864fee21e36SBarry Smith 1865c7afd0dbSLois Curfman McInnes Input Parameters: 1866f6dfbefdSBarry Smith + snes - the `SNES` context 1867dc4c0fb0SBarry Smith . r - vector to store function values, may be `NULL` 186820f4b53cSBarry Smith . f - function evaluation routine; for calling sequence see `SNESFunction` 1869c7afd0dbSLois Curfman McInnes - ctx - [optional] user-defined context for private data for the 1870dc4c0fb0SBarry Smith function evaluation routine (may be `NULL`) 18719b94acceSBarry Smith 187236851e7fSLois Curfman McInnes Level: beginner 187336851e7fSLois Curfman McInnes 18741cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetPicard()`, `SNESFunction` 18759b94acceSBarry Smith @*/ 1876d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunction(SNES snes, Vec r, PetscErrorCode (*f)(SNES, Vec, Vec, void *), void *ctx) 1877d71ae5a4SJacob Faibussowitsch { 18786cab3a1bSJed Brown DM dm; 18796cab3a1bSJed Brown 18803a40ed3dSBarry Smith PetscFunctionBegin; 18810700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1882d2a683ecSLisandro Dalcin if (r) { 1883d2a683ecSLisandro Dalcin PetscValidHeaderSpecific(r, VEC_CLASSID, 2); 1884d2a683ecSLisandro Dalcin PetscCheckSameComm(snes, 1, r, 2); 18859566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)r)); 18869566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_func)); 188785385478SLisandro Dalcin snes->vec_func = r; 1888d2a683ecSLisandro Dalcin } 18899566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 18909566063dSJacob Faibussowitsch PetscCall(DMSNESSetFunction(dm, f, ctx)); 189148a46eb9SPierre Jolivet if (f == SNESPicardComputeFunction) PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx)); 18923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18939b94acceSBarry Smith } 18949b94acceSBarry Smith 1895e4ed7901SPeter Brune /*@C 18960b4db180SJacob Faibussowitsch SNESSetInitialFunction - Set an already computed function evaluation at the initial guess to be reused by `SNESSolve()`. 1897e4ed7901SPeter Brune 1898c3339decSBarry Smith Logically Collective 1899e4ed7901SPeter Brune 1900e4ed7901SPeter Brune Input Parameters: 1901f6dfbefdSBarry Smith + snes - the `SNES` context 1902e4ed7901SPeter Brune - f - vector to store function value 1903e4ed7901SPeter Brune 1904dc4c0fb0SBarry Smith Level: developer 1905dc4c0fb0SBarry Smith 1906e4ed7901SPeter Brune Notes: 1907e4ed7901SPeter Brune This should not be modified during the solution procedure. 1908e4ed7901SPeter Brune 1909f6dfbefdSBarry Smith This is used extensively in the `SNESFAS` hierarchy and in nonlinear preconditioning. 1910e4ed7901SPeter Brune 19111cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetInitialFunctionNorm()` 1912e4ed7901SPeter Brune @*/ 1913d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetInitialFunction(SNES snes, Vec f) 1914d71ae5a4SJacob Faibussowitsch { 1915e4ed7901SPeter Brune Vec vec_func; 1916e4ed7901SPeter Brune 1917e4ed7901SPeter Brune PetscFunctionBegin; 1918e4ed7901SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1919e4ed7901SPeter Brune PetscValidHeaderSpecific(f, VEC_CLASSID, 2); 1920e4ed7901SPeter Brune PetscCheckSameComm(snes, 1, f, 2); 1921efd4aadfSBarry Smith if (snes->npcside == PC_LEFT && snes->functype == SNES_FUNCTION_PRECONDITIONED) { 1922902f982fSPeter Brune snes->vec_func_init_set = PETSC_FALSE; 19233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1924902f982fSPeter Brune } 19259566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &vec_func, NULL, NULL)); 19269566063dSJacob Faibussowitsch PetscCall(VecCopy(f, vec_func)); 1927f5af7f23SKarl Rupp 1928217b9c2eSPeter Brune snes->vec_func_init_set = PETSC_TRUE; 19293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1930e4ed7901SPeter Brune } 1931e4ed7901SPeter Brune 1932534ebe21SPeter Brune /*@ 1933f6dfbefdSBarry Smith SNESSetNormSchedule - Sets the `SNESNormSchedule` used in convergence and monitoring 1934f6dfbefdSBarry Smith of the `SNES` method, when norms are computed in the solving process 1935534ebe21SPeter Brune 1936c3339decSBarry Smith Logically Collective 1937534ebe21SPeter Brune 1938534ebe21SPeter Brune Input Parameters: 1939f6dfbefdSBarry Smith + snes - the `SNES` context 1940365a6726SPeter Brune - normschedule - the frequency of norm computation 1941534ebe21SPeter Brune 1942517f1916SMatthew G. Knepley Options Database Key: 194367b8a455SSatish Balay . -snes_norm_schedule <none, always, initialonly, finalonly, initialfinalonly> - set the schedule 1944517f1916SMatthew G. Knepley 1945dc4c0fb0SBarry Smith Level: advanced 1946dc4c0fb0SBarry Smith 1947534ebe21SPeter Brune Notes: 1948f6dfbefdSBarry Smith Only certain `SNES` methods support certain `SNESNormSchedules`. Most require evaluation 1949534ebe21SPeter Brune of the nonlinear function and the taking of its norm at every iteration to 1950534ebe21SPeter Brune even ensure convergence at all. However, methods such as custom Gauss-Seidel methods 1951f6dfbefdSBarry Smith `SNESNGS` and the like do not require the norm of the function to be computed, and therefore 1952534ebe21SPeter Brune may either be monitored for convergence or not. As these are often used as nonlinear 1953534ebe21SPeter Brune preconditioners, monitoring the norm of their error is not a useful enterprise within 1954534ebe21SPeter Brune their solution. 1955534ebe21SPeter Brune 1956e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNESNormSchedule`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()` 1957534ebe21SPeter Brune @*/ 1958d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNormSchedule(SNES snes, SNESNormSchedule normschedule) 1959d71ae5a4SJacob Faibussowitsch { 1960534ebe21SPeter Brune PetscFunctionBegin; 1961534ebe21SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1962365a6726SPeter Brune snes->normschedule = normschedule; 19633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1964534ebe21SPeter Brune } 1965534ebe21SPeter Brune 1966534ebe21SPeter Brune /*@ 1967f6dfbefdSBarry Smith SNESGetNormSchedule - Gets the `SNESNormSchedule` used in convergence and monitoring 1968f6dfbefdSBarry Smith of the `SNES` method. 1969534ebe21SPeter Brune 1970c3339decSBarry Smith Logically Collective 1971534ebe21SPeter Brune 1972534ebe21SPeter Brune Input Parameters: 1973f6dfbefdSBarry Smith + snes - the `SNES` context 1974365a6726SPeter Brune - normschedule - the type of the norm used 1975534ebe21SPeter Brune 1976534ebe21SPeter Brune Level: advanced 1977534ebe21SPeter Brune 19781cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 1979534ebe21SPeter Brune @*/ 1980d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNormSchedule(SNES snes, SNESNormSchedule *normschedule) 1981d71ae5a4SJacob Faibussowitsch { 1982534ebe21SPeter Brune PetscFunctionBegin; 1983534ebe21SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1984365a6726SPeter Brune *normschedule = snes->normschedule; 19853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1986534ebe21SPeter Brune } 1987534ebe21SPeter Brune 1988c5ce4427SMatthew G. Knepley /*@ 1989c5ce4427SMatthew G. Knepley SNESSetFunctionNorm - Sets the last computed residual norm. 1990c5ce4427SMatthew G. Knepley 1991c3339decSBarry Smith Logically Collective 1992c5ce4427SMatthew G. Knepley 1993c5ce4427SMatthew G. Knepley Input Parameters: 1994f6dfbefdSBarry Smith + snes - the `SNES` context 1995f6dfbefdSBarry Smith - norm - the value of the norm 1996c5ce4427SMatthew G. Knepley 1997c5ce4427SMatthew G. Knepley Level: developer 1998c5ce4427SMatthew G. Knepley 19991cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 2000c5ce4427SMatthew G. Knepley @*/ 2001d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionNorm(SNES snes, PetscReal norm) 2002d71ae5a4SJacob Faibussowitsch { 2003c5ce4427SMatthew G. Knepley PetscFunctionBegin; 2004c5ce4427SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2005c5ce4427SMatthew G. Knepley snes->norm = norm; 20063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2007c5ce4427SMatthew G. Knepley } 2008c5ce4427SMatthew G. Knepley 2009c5ce4427SMatthew G. Knepley /*@ 2010c5ce4427SMatthew G. Knepley SNESGetFunctionNorm - Gets the last computed norm of the residual 2011c5ce4427SMatthew G. Knepley 2012c5ce4427SMatthew G. Knepley Not Collective 2013c5ce4427SMatthew G. Knepley 2014c5ce4427SMatthew G. Knepley Input Parameter: 2015f6dfbefdSBarry Smith . snes - the `SNES` context 2016c5ce4427SMatthew G. Knepley 2017c5ce4427SMatthew G. Knepley Output Parameter: 2018c5ce4427SMatthew G. Knepley . norm - the last computed residual norm 2019c5ce4427SMatthew G. Knepley 2020c5ce4427SMatthew G. Knepley Level: developer 2021c5ce4427SMatthew G. Knepley 20221cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 2023c5ce4427SMatthew G. Knepley @*/ 2024d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionNorm(SNES snes, PetscReal *norm) 2025d71ae5a4SJacob Faibussowitsch { 2026c5ce4427SMatthew G. Knepley PetscFunctionBegin; 2027c5ce4427SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 20284f572ea9SToby Isaac PetscAssertPointer(norm, 2); 2029c5ce4427SMatthew G. Knepley *norm = snes->norm; 20303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2031c5ce4427SMatthew G. Knepley } 2032c5ce4427SMatthew G. Knepley 2033c1e67a49SFande Kong /*@ 2034f6dfbefdSBarry Smith SNESGetUpdateNorm - Gets the last computed norm of the solution update 2035c1e67a49SFande Kong 2036c1e67a49SFande Kong Not Collective 2037c1e67a49SFande Kong 2038c1e67a49SFande Kong Input Parameter: 2039f6dfbefdSBarry Smith . snes - the `SNES` context 2040c1e67a49SFande Kong 2041c1e67a49SFande Kong Output Parameter: 2042c1e67a49SFande Kong . ynorm - the last computed update norm 2043c1e67a49SFande Kong 2044c1e67a49SFande Kong Level: developer 2045c1e67a49SFande Kong 2046f6dfbefdSBarry Smith Note: 2047f6dfbefdSBarry Smith The new solution is the current solution plus the update, so this norm is an indication of the size of the update 2048f6dfbefdSBarry Smith 20491cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()` 2050c1e67a49SFande Kong @*/ 2051d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUpdateNorm(SNES snes, PetscReal *ynorm) 2052d71ae5a4SJacob Faibussowitsch { 2053c1e67a49SFande Kong PetscFunctionBegin; 2054c1e67a49SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 20554f572ea9SToby Isaac PetscAssertPointer(ynorm, 2); 2056c1e67a49SFande Kong *ynorm = snes->ynorm; 20573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2058c1e67a49SFande Kong } 2059c1e67a49SFande Kong 2060c1e67a49SFande Kong /*@ 20614591eaf2SFande Kong SNESGetSolutionNorm - Gets the last computed norm of the solution 2062c1e67a49SFande Kong 2063c1e67a49SFande Kong Not Collective 2064c1e67a49SFande Kong 2065c1e67a49SFande Kong Input Parameter: 2066f6dfbefdSBarry Smith . snes - the `SNES` context 2067c1e67a49SFande Kong 2068c1e67a49SFande Kong Output Parameter: 2069c1e67a49SFande Kong . xnorm - the last computed solution norm 2070c1e67a49SFande Kong 2071c1e67a49SFande Kong Level: developer 2072c1e67a49SFande Kong 20731cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`, `SNESGetUpdateNorm()` 2074c1e67a49SFande Kong @*/ 2075d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionNorm(SNES snes, PetscReal *xnorm) 2076d71ae5a4SJacob Faibussowitsch { 2077c1e67a49SFande Kong PetscFunctionBegin; 2078c1e67a49SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 20794f572ea9SToby Isaac PetscAssertPointer(xnorm, 2); 2080c1e67a49SFande Kong *xnorm = snes->xnorm; 20813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2082c1e67a49SFande Kong } 2083c1e67a49SFande Kong 208447073ea2SPeter Brune /*@C 2085f6dfbefdSBarry Smith SNESSetFunctionType - Sets the `SNESFunctionType` 2086f6dfbefdSBarry Smith of the `SNES` method. 208747073ea2SPeter Brune 2088c3339decSBarry Smith Logically Collective 208947073ea2SPeter Brune 209047073ea2SPeter Brune Input Parameters: 2091f6dfbefdSBarry Smith + snes - the `SNES` context 2092f6dfbefdSBarry Smith - type - the function type 209347073ea2SPeter Brune 209447073ea2SPeter Brune Level: developer 209547073ea2SPeter Brune 2096420bcc1bSBarry Smith Values of the function type\: 2097f6dfbefdSBarry Smith + `SNES_FUNCTION_DEFAULT` - the default for the given `SNESType` 2098f6dfbefdSBarry Smith . `SNES_FUNCTION_UNPRECONDITIONED` - an unpreconditioned function evaluation (this is the function provided with `SNESSetFunction()` 2099f6dfbefdSBarry Smith - `SNES_FUNCTION_PRECONDITIONED` - a transformation of the function provided with `SNESSetFunction()` 2100f6dfbefdSBarry Smith 2101420bcc1bSBarry Smith Note: 2102f6dfbefdSBarry Smith Different `SNESType`s use this value in different ways 2103f6dfbefdSBarry Smith 21041cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFunctionType`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 210547073ea2SPeter Brune @*/ 2106d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionType(SNES snes, SNESFunctionType type) 2107d71ae5a4SJacob Faibussowitsch { 210847073ea2SPeter Brune PetscFunctionBegin; 210947073ea2SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 211047073ea2SPeter Brune snes->functype = type; 21113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 211247073ea2SPeter Brune } 211347073ea2SPeter Brune 211447073ea2SPeter Brune /*@C 2115f6dfbefdSBarry Smith SNESGetFunctionType - Gets the `SNESFunctionType` used in convergence and monitoring set with `SNESSetFunctionType()` 211647073ea2SPeter Brune of the SNES method. 211747073ea2SPeter Brune 2118c3339decSBarry Smith Logically Collective 211947073ea2SPeter Brune 212047073ea2SPeter Brune Input Parameters: 2121f6dfbefdSBarry Smith + snes - the `SNES` context 2122f6dfbefdSBarry Smith - type - the type of the function evaluation, see `SNESSetFunctionType()` 212347073ea2SPeter Brune 212447073ea2SPeter Brune Level: advanced 212547073ea2SPeter Brune 21261cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetFunctionType()`, `SNESFunctionType`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 212747073ea2SPeter Brune @*/ 2128d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionType(SNES snes, SNESFunctionType *type) 2129d71ae5a4SJacob Faibussowitsch { 213047073ea2SPeter Brune PetscFunctionBegin; 213147073ea2SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 213247073ea2SPeter Brune *type = snes->functype; 21333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2134534ebe21SPeter Brune } 2135534ebe21SPeter Brune 2136c79ef259SPeter Brune /*@C 2137be95d8f1SBarry Smith SNESSetNGS - Sets the user nonlinear Gauss-Seidel routine for 2138c79ef259SPeter Brune use with composed nonlinear solvers. 2139c79ef259SPeter Brune 2140c79ef259SPeter Brune Input Parameters: 2141dc4c0fb0SBarry Smith + snes - the `SNES` context 214237fdd005SBarry Smith . f - function evaluation routine to apply Gauss-Seidel 2143c79ef259SPeter Brune - ctx - [optional] user-defined context for private data for the 2144dc4c0fb0SBarry Smith smoother evaluation routine (may be `NULL`) 2145c79ef259SPeter Brune 214620f4b53cSBarry Smith Calling sequence of `f`: 2147f6dfbefdSBarry Smith + snes - the `SNES` context 2148f6dfbefdSBarry Smith . X - the current solution 2149dc4c0fb0SBarry Smith . B - the right hand side vector (which may be `NULL`) 2150f6dfbefdSBarry Smith - ctx - a user provided context 2151f6dfbefdSBarry Smith 2152dc4c0fb0SBarry Smith Level: intermediate 2153dc4c0fb0SBarry Smith 2154f6dfbefdSBarry Smith Note: 2155f6dfbefdSBarry Smith The `SNESNGS` routines are used by the composed nonlinear solver to generate 2156f6dfbefdSBarry Smith a problem appropriate update to the solution, particularly `SNESFAS`. 2157c79ef259SPeter Brune 21581cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetNGS()`, `SNESNCG`, `SNESGetFunction()`, `SNESComputeNGS()` 2159c79ef259SPeter Brune @*/ 21600b4db180SJacob Faibussowitsch PetscErrorCode SNESSetNGS(SNES snes, PetscErrorCode (*f)(SNES snes, Vec X, Vec B, void *ctx), void *ctx) 2161d71ae5a4SJacob Faibussowitsch { 21626cab3a1bSJed Brown DM dm; 21636cab3a1bSJed Brown 2164646217ecSPeter Brune PetscFunctionBegin; 21656cab3a1bSJed Brown PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 21669566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 21679566063dSJacob Faibussowitsch PetscCall(DMSNESSetNGS(dm, f, ctx)); 21683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2169646217ecSPeter Brune } 2170646217ecSPeter Brune 2171bbc1464cSBarry Smith /* 2172bbc1464cSBarry Smith This is used for -snes_mf_operator; it uses a duplicate of snes->jacobian_pre because snes->jacobian_pre cannot be 2173bbc1464cSBarry Smith changed during the KSPSolve() 2174bbc1464cSBarry Smith */ 2175d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeMFFunction(SNES snes, Vec x, Vec f, void *ctx) 2176d71ae5a4SJacob Faibussowitsch { 2177bbc1464cSBarry Smith DM dm; 2178bbc1464cSBarry Smith DMSNES sdm; 2179bbc1464cSBarry Smith 2180bbc1464cSBarry Smith PetscFunctionBegin; 21819566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 21829566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 2183bbc1464cSBarry Smith /* A(x)*x - b(x) */ 2184bbc1464cSBarry Smith if (sdm->ops->computepfunction) { 2185792fecdfSBarry Smith PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx)); 21869566063dSJacob Faibussowitsch PetscCall(VecScale(f, -1.0)); 21870df40c35SBarry Smith /* Cannot share nonzero pattern because of the possible use of SNESComputeJacobianDefault() */ 2188ef1023bdSBarry Smith if (!snes->picard) PetscCall(MatDuplicate(snes->jacobian_pre, MAT_DO_NOT_COPY_VALUES, &snes->picard)); 2189792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx)); 21909566063dSJacob Faibussowitsch PetscCall(MatMultAdd(snes->picard, x, f, f)); 2191bbc1464cSBarry Smith } else { 2192792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx)); 21939566063dSJacob Faibussowitsch PetscCall(MatMult(snes->picard, x, f)); 2194bbc1464cSBarry Smith } 21953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2196bbc1464cSBarry Smith } 2197bbc1464cSBarry Smith 2198d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeFunction(SNES snes, Vec x, Vec f, void *ctx) 2199d71ae5a4SJacob Faibussowitsch { 2200e03ab78fSPeter Brune DM dm; 2201942e3340SBarry Smith DMSNES sdm; 22026cab3a1bSJed Brown 22038b0a5094SBarry Smith PetscFunctionBegin; 22049566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 22059566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 22068b0a5094SBarry Smith /* A(x)*x - b(x) */ 2207bbc1464cSBarry Smith if (sdm->ops->computepfunction) { 2208792fecdfSBarry Smith PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx)); 22099566063dSJacob Faibussowitsch PetscCall(VecScale(f, -1.0)); 2210792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx)); 22119566063dSJacob Faibussowitsch PetscCall(MatMultAdd(snes->jacobian_pre, x, f, f)); 2212bbc1464cSBarry Smith } else { 2213792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx)); 22149566063dSJacob Faibussowitsch PetscCall(MatMult(snes->jacobian_pre, x, f)); 2215bbc1464cSBarry Smith } 22163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22178b0a5094SBarry Smith } 22188b0a5094SBarry Smith 2219d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeJacobian(SNES snes, Vec x1, Mat J, Mat B, void *ctx) 2220d71ae5a4SJacob Faibussowitsch { 22218b0a5094SBarry Smith PetscFunctionBegin; 2222e03ab78fSPeter Brune /* the jacobian matrix should be pre-filled in SNESPicardComputeFunction */ 2223bbc1464cSBarry Smith /* must assembly if matrix-free to get the last SNES solution */ 22249566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 22259566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 22263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22278b0a5094SBarry Smith } 22288b0a5094SBarry Smith 22298b0a5094SBarry Smith /*@C 2230f6dfbefdSBarry Smith SNESSetPicard - Use `SNES` to solve the system A(x) x = bp(x) + b via a Picard type iteration (Picard linearization) 22318b0a5094SBarry Smith 2232c3339decSBarry Smith Logically Collective 22338b0a5094SBarry Smith 22348b0a5094SBarry Smith Input Parameters: 2235f6dfbefdSBarry Smith + snes - the `SNES` context 2236dc4c0fb0SBarry Smith . r - vector to store function values, may be `NULL` 2237420bcc1bSBarry Smith . bp - function evaluation routine, may be `NULL`, for the calling sequence see `SNESJacobianFunction` 22386b7fb656SBarry Smith . Amat - matrix with which A(x) x - bp(x) - b is to be computed 2239dc4c0fb0SBarry Smith . Pmat - matrix from which preconditioner is computed (usually the same as `Amat`) 2240420bcc1bSBarry Smith . J - function to compute matrix values, for the calling sequence see `SNESJacobianFunction` 2241dc4c0fb0SBarry Smith - ctx - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`) 2242dc4c0fb0SBarry Smith 2243dc4c0fb0SBarry Smith Level: intermediate 22448b0a5094SBarry Smith 22458b0a5094SBarry Smith Notes: 22466b7fb656SBarry Smith It is often better to provide the nonlinear function F() and some approximation to its Jacobian directly and use 2247f450aa47SBarry 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. 2248f450aa47SBarry Smith 2249f6dfbefdSBarry Smith One can call `SNESSetPicard()` or `SNESSetFunction()` (and possibly `SNESSetJacobian()`) but cannot call both 22508b0a5094SBarry Smith 2251dc4c0fb0SBarry 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}. 2252dc4c0fb0SBarry Smith When an exact solver is used this corresponds to the "classic" Picard A(x^{n}) x^{n+1} = bp(x^{n}) + b iteration. 22538b0a5094SBarry Smith 2254dc4c0fb0SBarry Smith Run with `-snes_mf_operator` to solve the system with Newton's method using A(x^{n}) to construct the preconditioner. 22558b0a5094SBarry Smith 22560d04baf8SBarry Smith We implement the defect correction form of the Picard iteration because it converges much more generally when inexact linear solvers are used then 22576b7fb656SBarry Smith the direct Picard iteration A(x^n) x^{n+1} = bp(x^n) + b 22588b0a5094SBarry Smith 22598b0a5094SBarry 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 22608b0a5094SBarry 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 22618b0a5094SBarry Smith different please contact us at petsc-dev@mcs.anl.gov and we'll have an entirely new argument :-). 22628b0a5094SBarry Smith 2263dc4c0fb0SBarry 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 2264f6dfbefdSBarry Smith A(x^{n}) is used to build the preconditioner 22656b7fb656SBarry Smith 2266dc4c0fb0SBarry Smith When used with `-snes_fd` this will compute the true Jacobian (very slowly one column at at time) and thus represent Newton's method. 22676b7fb656SBarry Smith 2268dc4c0fb0SBarry 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 22696b7fb656SBarry 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 2270f6dfbefdSBarry 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`. 2271aaa8cc7dSPierre Jolivet See the comment in src/snes/tutorials/ex15.c. 2272bbc1464cSBarry Smith 22731cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESGetPicard()`, `SNESLineSearchPreCheckPicard()`, `SNESJacobianFunction` 22748b0a5094SBarry Smith @*/ 2275d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetPicard(SNES snes, Vec r, PetscErrorCode (*bp)(SNES, Vec, Vec, void *), Mat Amat, Mat Pmat, PetscErrorCode (*J)(SNES, Vec, Mat, Mat, void *), void *ctx) 2276d71ae5a4SJacob Faibussowitsch { 2277e03ab78fSPeter Brune DM dm; 2278e03ab78fSPeter Brune 22798b0a5094SBarry Smith PetscFunctionBegin; 22808b0a5094SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 22819566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 22829566063dSJacob Faibussowitsch PetscCall(DMSNESSetPicard(dm, bp, J, ctx)); 22839566063dSJacob Faibussowitsch PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx)); 22849566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes, r, SNESPicardComputeFunction, ctx)); 22859566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESPicardComputeJacobian, ctx)); 22863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22878b0a5094SBarry Smith } 22888b0a5094SBarry Smith 22897971a8bfSPeter Brune /*@C 22907971a8bfSPeter Brune SNESGetPicard - Returns the context for the Picard iteration 22917971a8bfSPeter Brune 2292f6dfbefdSBarry Smith Not Collective, but `Vec` is parallel if `SNES` is parallel. Collective if `Vec` is requested, but has not been created yet. 22937971a8bfSPeter Brune 22947971a8bfSPeter Brune Input Parameter: 2295f6dfbefdSBarry Smith . snes - the `SNES` context 22967971a8bfSPeter Brune 2297d8d19677SJose E. Roman Output Parameters: 2298dc4c0fb0SBarry Smith + r - the function (or `NULL`) 229920f4b53cSBarry Smith . f - the function (or `NULL`); for calling sequence see `SNESFunction` 2300dc4c0fb0SBarry Smith . Amat - the matrix used to defined the operation A(x) x - b(x) (or `NULL`) 2301dc4c0fb0SBarry Smith . Pmat - the matrix from which the preconditioner will be constructed (or `NULL`) 230220f4b53cSBarry Smith . J - the function for matrix evaluation (or `NULL`); for calling sequence see `SNESJacobianFunction` 2303dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`) 23047971a8bfSPeter Brune 23057971a8bfSPeter Brune Level: advanced 23067971a8bfSPeter Brune 23071cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetFunction()`, `SNESSetPicard()`, `SNESGetFunction()`, `SNESGetJacobian()`, `SNESGetDM()`, `SNESFunction`, `SNESJacobianFunction` 23087971a8bfSPeter Brune @*/ 2309d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetPicard(SNES snes, Vec *r, PetscErrorCode (**f)(SNES, Vec, Vec, void *), Mat *Amat, Mat *Pmat, PetscErrorCode (**J)(SNES, Vec, Mat, Mat, void *), void **ctx) 2310d71ae5a4SJacob Faibussowitsch { 23117971a8bfSPeter Brune DM dm; 23127971a8bfSPeter Brune 23137971a8bfSPeter Brune PetscFunctionBegin; 23147971a8bfSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 23159566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, r, NULL, NULL)); 23169566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL)); 23179566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 23189566063dSJacob Faibussowitsch PetscCall(DMSNESGetPicard(dm, f, J, ctx)); 23193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23207971a8bfSPeter Brune } 23217971a8bfSPeter Brune 2322d25893d9SBarry Smith /*@C 2323dc4c0fb0SBarry Smith SNESSetComputeInitialGuess - Sets a routine used to compute an initial guess for the nonlinear problem 2324d25893d9SBarry Smith 2325c3339decSBarry Smith Logically Collective 2326d25893d9SBarry Smith 2327d25893d9SBarry Smith Input Parameters: 2328f6dfbefdSBarry Smith + snes - the `SNES` context 2329d25893d9SBarry Smith . func - function evaluation routine 2330d25893d9SBarry Smith - ctx - [optional] user-defined context for private data for the 2331dc4c0fb0SBarry Smith function evaluation routine (may be `NULL`) 2332d25893d9SBarry Smith 233320f4b53cSBarry Smith Calling sequence of `func`: 233420f4b53cSBarry Smith + snes - the `SNES` solver 233520f4b53cSBarry Smith . x - vector to put initial guess 2336d25893d9SBarry Smith - ctx - optional user-defined function context 2337d25893d9SBarry Smith 2338d25893d9SBarry Smith Level: intermediate 2339d25893d9SBarry Smith 2340420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()` 2341d25893d9SBarry Smith @*/ 23420b4db180SJacob Faibussowitsch PetscErrorCode SNESSetComputeInitialGuess(SNES snes, PetscErrorCode (*func)(SNES snes, Vec x, void *ctx), void *ctx) 2343d71ae5a4SJacob Faibussowitsch { 2344d25893d9SBarry Smith PetscFunctionBegin; 2345d25893d9SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2346d25893d9SBarry Smith if (func) snes->ops->computeinitialguess = func; 2347d25893d9SBarry Smith if (ctx) snes->initialguessP = ctx; 23483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2349d25893d9SBarry Smith } 2350d25893d9SBarry Smith 23511096aae1SMatthew Knepley /*@C 2352dc4c0fb0SBarry Smith SNESGetRhs - Gets the vector for solving F(x) = `rhs`. If `rhs` is not set 23531096aae1SMatthew Knepley it assumes a zero right hand side. 23541096aae1SMatthew Knepley 2355c3339decSBarry Smith Logically Collective 23561096aae1SMatthew Knepley 23571096aae1SMatthew Knepley Input Parameter: 2358f6dfbefdSBarry Smith . snes - the `SNES` context 23591096aae1SMatthew Knepley 23601096aae1SMatthew Knepley Output Parameter: 2361420bcc1bSBarry Smith . rhs - the right hand side vector or `NULL` if there is no right-hand side vector 23621096aae1SMatthew Knepley 23631096aae1SMatthew Knepley Level: intermediate 23641096aae1SMatthew Knepley 23651cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetFunction()` 23661096aae1SMatthew Knepley @*/ 2367d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetRhs(SNES snes, Vec *rhs) 2368d71ae5a4SJacob Faibussowitsch { 23691096aae1SMatthew Knepley PetscFunctionBegin; 23700700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 23714f572ea9SToby Isaac PetscAssertPointer(rhs, 2); 237285385478SLisandro Dalcin *rhs = snes->vec_rhs; 23733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23741096aae1SMatthew Knepley } 23751096aae1SMatthew Knepley 23769b94acceSBarry Smith /*@ 2377f6dfbefdSBarry Smith SNESComputeFunction - Calls the function that has been set with `SNESSetFunction()`. 23789b94acceSBarry Smith 2379c3339decSBarry Smith Collective 2380c7afd0dbSLois Curfman McInnes 23819b94acceSBarry Smith Input Parameters: 2382f6dfbefdSBarry Smith + snes - the `SNES` context 2383c7afd0dbSLois Curfman McInnes - x - input vector 23849b94acceSBarry Smith 23859b94acceSBarry Smith Output Parameter: 2386f6dfbefdSBarry Smith . y - function vector, as set by `SNESSetFunction()` 23879b94acceSBarry Smith 2388dc4c0fb0SBarry Smith Level: developer 2389dc4c0fb0SBarry Smith 239000677de2SStefano Zampini Notes: 2391f6dfbefdSBarry Smith `SNESComputeFunction()` is typically used within nonlinear solvers 2392bbc1464cSBarry Smith implementations, so users would not generally call this routine themselves. 239336851e7fSLois Curfman McInnes 239400677de2SStefano Zampini When solving for $F(x) = b$, this routine computes $y = F(x) - b$. 239500677de2SStefano Zampini 23961cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeMFFunction()` 23979b94acceSBarry Smith @*/ 2398d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeFunction(SNES snes, Vec x, Vec y) 2399d71ae5a4SJacob Faibussowitsch { 24006cab3a1bSJed Brown DM dm; 2401942e3340SBarry Smith DMSNES sdm; 24029b94acceSBarry Smith 24033a40ed3dSBarry Smith PetscFunctionBegin; 24040700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 24050700a824SBarry Smith PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 24060700a824SBarry Smith PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2407c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, x, 2); 2408c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, y, 3); 2409e0f629ddSJacob Faibussowitsch PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2410184914b5SBarry Smith 24119566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 24129566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 24130fdf79fbSJacob 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()."); 241432f3f7c2SPeter Brune if (sdm->ops->computefunction) { 241548a46eb9SPierre Jolivet if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0)); 24169566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(x)); 24178ddeebeaSSteve Benbow /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */ 24188ddeebeaSSteve Benbow snes->domainerror = PETSC_FALSE; 2419800f99ffSJeremy L Thompson { 2420800f99ffSJeremy L Thompson void *ctx; 2421800f99ffSJeremy L Thompson PetscErrorCode (*computefunction)(SNES, Vec, Vec, void *); 2422800f99ffSJeremy L Thompson PetscCall(DMSNESGetFunction(dm, &computefunction, &ctx)); 2423800f99ffSJeremy L Thompson PetscCallBack("SNES callback function", (*computefunction)(snes, x, y, ctx)); 2424800f99ffSJeremy L Thompson } 24259566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(x)); 242648a46eb9SPierre Jolivet if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0)); 24270fdf79fbSJacob Faibussowitsch } else /* if (snes->vec_rhs) */ { 24289566063dSJacob Faibussowitsch PetscCall(MatMult(snes->jacobian, x, y)); 24290fdf79fbSJacob Faibussowitsch } 24301baa6e33SBarry Smith if (snes->vec_rhs) PetscCall(VecAXPY(y, -1.0, snes->vec_rhs)); 2431ae3c334cSLois Curfman McInnes snes->nfuncs++; 2432422a814eSBarry Smith /* 2433422a814eSBarry Smith domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will 2434422a814eSBarry Smith propagate the value to all processes 2435422a814eSBarry Smith */ 24361baa6e33SBarry Smith if (snes->domainerror) PetscCall(VecSetInf(y)); 24373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24389b94acceSBarry Smith } 24399b94acceSBarry Smith 2440c79ef259SPeter Brune /*@ 2441f6dfbefdSBarry Smith SNESComputeMFFunction - Calls the function that has been set with `SNESSetMFFunction()`. 2442bbc1464cSBarry Smith 2443c3339decSBarry Smith Collective 2444bbc1464cSBarry Smith 2445bbc1464cSBarry Smith Input Parameters: 2446f6dfbefdSBarry Smith + snes - the `SNES` context 2447bbc1464cSBarry Smith - x - input vector 2448bbc1464cSBarry Smith 2449bbc1464cSBarry Smith Output Parameter: 2450f6dfbefdSBarry Smith . y - function vector, as set by `SNESSetMFFunction()` 2451bbc1464cSBarry Smith 2452dc4c0fb0SBarry Smith Level: developer 2453dc4c0fb0SBarry Smith 2454bbc1464cSBarry Smith Notes: 2455420bcc1bSBarry Smith `SNESComputeMFFunction()` is used within the matrix-vector products called by the matrix created with `MatCreateSNESMF()` 2456bbc1464cSBarry Smith so users would not generally call this routine themselves. 2457bbc1464cSBarry Smith 2458f6dfbefdSBarry Smith Since this function is intended for use with finite differencing it does not subtract the right hand side vector provided with `SNESSolve()` 2459f6dfbefdSBarry Smith while `SNESComputeFunction()` does. As such, this routine cannot be used with `MatMFFDSetBase()` with a provided F function value even if it applies the 2460f6dfbefdSBarry 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. 2461bbc1464cSBarry Smith 24621cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `MatCreateSNESMF` 2463bbc1464cSBarry Smith @*/ 2464d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeMFFunction(SNES snes, Vec x, Vec y) 2465d71ae5a4SJacob Faibussowitsch { 2466bbc1464cSBarry Smith DM dm; 2467bbc1464cSBarry Smith DMSNES sdm; 2468bbc1464cSBarry Smith 2469bbc1464cSBarry Smith PetscFunctionBegin; 2470bbc1464cSBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2471bbc1464cSBarry Smith PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2472bbc1464cSBarry Smith PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2473bbc1464cSBarry Smith PetscCheckSameComm(snes, 1, x, 2); 2474bbc1464cSBarry Smith PetscCheckSameComm(snes, 1, y, 3); 2475e0f629ddSJacob Faibussowitsch PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2476bbc1464cSBarry Smith 24779566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 24789566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 24799566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0)); 24809566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(x)); 2481bbc1464cSBarry Smith /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */ 2482bbc1464cSBarry Smith snes->domainerror = PETSC_FALSE; 2483792fecdfSBarry Smith PetscCallBack("SNES callback function", (*sdm->ops->computemffunction)(snes, x, y, sdm->mffunctionctx)); 24849566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(x)); 24859566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0)); 2486bbc1464cSBarry Smith snes->nfuncs++; 2487bbc1464cSBarry Smith /* 2488bbc1464cSBarry Smith domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will 2489bbc1464cSBarry Smith propagate the value to all processes 2490bbc1464cSBarry Smith */ 24911baa6e33SBarry Smith if (snes->domainerror) PetscCall(VecSetInf(y)); 24923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2493bbc1464cSBarry Smith } 2494bbc1464cSBarry Smith 2495bbc1464cSBarry Smith /*@ 2496f6dfbefdSBarry Smith SNESComputeNGS - Calls the Gauss-Seidel function that has been set with `SNESSetNGS()`. 2497c79ef259SPeter Brune 2498c3339decSBarry Smith Collective 2499c79ef259SPeter Brune 2500c79ef259SPeter Brune Input Parameters: 2501f6dfbefdSBarry Smith + snes - the `SNES` context 2502c79ef259SPeter Brune . x - input vector 2503c79ef259SPeter Brune - b - rhs vector 2504c79ef259SPeter Brune 2505c79ef259SPeter Brune Output Parameter: 2506c79ef259SPeter Brune . x - new solution vector 2507c79ef259SPeter Brune 2508dc4c0fb0SBarry Smith Level: developer 2509dc4c0fb0SBarry Smith 2510f6dfbefdSBarry Smith Note: 2511f6dfbefdSBarry Smith `SNESComputeNGS()` is typically used within composed nonlinear solver 2512c79ef259SPeter Brune implementations, so most users would not generally call this routine 2513c79ef259SPeter Brune themselves. 2514c79ef259SPeter Brune 25151cc06b55SBarry Smith .seealso: [](ch_snes), `SNESNGS`, `SNESSetNGS()`, `SNESComputeFunction()` 2516c79ef259SPeter Brune @*/ 2517d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeNGS(SNES snes, Vec b, Vec x) 2518d71ae5a4SJacob Faibussowitsch { 25196cab3a1bSJed Brown DM dm; 2520942e3340SBarry Smith DMSNES sdm; 2521646217ecSPeter Brune 2522646217ecSPeter Brune PetscFunctionBegin; 2523646217ecSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2524064a246eSJacob Faibussowitsch PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 2525064a246eSJacob Faibussowitsch if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 2526064a246eSJacob Faibussowitsch PetscCheckSameComm(snes, 1, x, 3); 2527064a246eSJacob Faibussowitsch if (b) PetscCheckSameComm(snes, 1, b, 2); 2528e0f629ddSJacob Faibussowitsch if (b) PetscCall(VecValidValues_Internal(b, 2, PETSC_TRUE)); 25299566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_NGSEval, snes, x, b, 0)); 25309566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 25319566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 25320fdf79fbSJacob Faibussowitsch PetscCheck(sdm->ops->computegs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetNGS() before SNESComputeNGS(), likely called from SNESSolve()."); 25339566063dSJacob Faibussowitsch if (b) PetscCall(VecLockReadPush(b)); 2534792fecdfSBarry Smith PetscCallBack("SNES callback NGS", (*sdm->ops->computegs)(snes, x, b, sdm->gsctx)); 25359566063dSJacob Faibussowitsch if (b) PetscCall(VecLockReadPop(b)); 25369566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_NGSEval, snes, x, b, 0)); 25373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2538646217ecSPeter Brune } 2539646217ecSPeter Brune 2540*494a190aSStefano Zampini static PetscErrorCode SNESComputeFunction_FD(SNES snes, Vec Xin, Vec G) 2541*494a190aSStefano Zampini { 2542*494a190aSStefano Zampini Vec X; 2543*494a190aSStefano Zampini PetscScalar *g; 2544*494a190aSStefano Zampini PetscReal f, f2; 2545*494a190aSStefano Zampini PetscInt low, high, N, i; 2546*494a190aSStefano Zampini PetscBool flg; 2547*494a190aSStefano Zampini PetscReal h = .5 * PETSC_SQRT_MACHINE_EPSILON; 2548*494a190aSStefano Zampini 2549*494a190aSStefano Zampini PetscFunctionBegin; 2550*494a190aSStefano Zampini PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_fd_delta", &h, &flg)); 2551*494a190aSStefano Zampini PetscCall(VecDuplicate(Xin, &X)); 2552*494a190aSStefano Zampini PetscCall(VecCopy(Xin, X)); 2553*494a190aSStefano Zampini PetscCall(VecGetSize(X, &N)); 2554*494a190aSStefano Zampini PetscCall(VecGetOwnershipRange(X, &low, &high)); 2555*494a190aSStefano Zampini PetscCall(VecSetOption(X, VEC_IGNORE_OFF_PROC_ENTRIES, PETSC_TRUE)); 2556*494a190aSStefano Zampini PetscCall(VecGetArray(G, &g)); 2557*494a190aSStefano Zampini for (i = 0; i < N; i++) { 2558*494a190aSStefano Zampini PetscCall(VecSetValue(X, i, -h, ADD_VALUES)); 2559*494a190aSStefano Zampini PetscCall(VecAssemblyBegin(X)); 2560*494a190aSStefano Zampini PetscCall(VecAssemblyEnd(X)); 2561*494a190aSStefano Zampini PetscCall(SNESComputeObjective(snes, X, &f)); 2562*494a190aSStefano Zampini PetscCall(VecSetValue(X, i, 2.0 * h, ADD_VALUES)); 2563*494a190aSStefano Zampini PetscCall(VecAssemblyBegin(X)); 2564*494a190aSStefano Zampini PetscCall(VecAssemblyEnd(X)); 2565*494a190aSStefano Zampini PetscCall(SNESComputeObjective(snes, X, &f2)); 2566*494a190aSStefano Zampini PetscCall(VecSetValue(X, i, -h, ADD_VALUES)); 2567*494a190aSStefano Zampini PetscCall(VecAssemblyBegin(X)); 2568*494a190aSStefano Zampini PetscCall(VecAssemblyEnd(X)); 2569*494a190aSStefano Zampini if (i >= low && i < high) g[i - low] = (f2 - f) / (2.0 * h); 2570*494a190aSStefano Zampini } 2571*494a190aSStefano Zampini PetscCall(VecRestoreArray(G, &g)); 2572*494a190aSStefano Zampini PetscCall(VecDestroy(&X)); 2573*494a190aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2574*494a190aSStefano Zampini } 2575*494a190aSStefano Zampini 2576*494a190aSStefano Zampini PetscErrorCode SNESTestFunction(SNES snes) 2577*494a190aSStefano Zampini { 2578*494a190aSStefano Zampini Vec x, g1, g2, g3; 2579*494a190aSStefano Zampini PetscBool complete_print = PETSC_FALSE, test = PETSC_FALSE; 2580*494a190aSStefano Zampini PetscReal hcnorm, fdnorm, hcmax, fdmax, diffmax, diffnorm; 2581*494a190aSStefano Zampini PetscScalar dot; 2582*494a190aSStefano Zampini MPI_Comm comm; 2583*494a190aSStefano Zampini PetscViewer viewer, mviewer; 2584*494a190aSStefano Zampini PetscViewerFormat format; 2585*494a190aSStefano Zampini PetscInt tabs; 2586*494a190aSStefano Zampini static PetscBool directionsprinted = PETSC_FALSE; 2587*494a190aSStefano Zampini PetscErrorCode (*objective)(SNES, Vec, PetscReal *, void *); 2588*494a190aSStefano Zampini 2589*494a190aSStefano Zampini PetscFunctionBegin; 2590*494a190aSStefano Zampini PetscCall(SNESGetObjective(snes, &objective, NULL)); 2591*494a190aSStefano Zampini if (!objective) PetscFunctionReturn(PETSC_SUCCESS); 2592*494a190aSStefano Zampini 2593*494a190aSStefano Zampini PetscObjectOptionsBegin((PetscObject)snes); 2594*494a190aSStefano Zampini PetscCall(PetscOptionsName("-snes_test_function", "Compare hand-coded and finite difference function", "None", &test)); 2595*494a190aSStefano Zampini PetscCall(PetscOptionsViewer("-snes_test_function_view", "View difference between hand-coded and finite difference function element entries", "None", &mviewer, &format, &complete_print)); 2596*494a190aSStefano Zampini PetscOptionsEnd(); 2597*494a190aSStefano Zampini if (!test) { 2598*494a190aSStefano Zampini if (complete_print) PetscCall(PetscViewerDestroy(&mviewer)); 2599*494a190aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2600*494a190aSStefano Zampini } 2601*494a190aSStefano Zampini 2602*494a190aSStefano Zampini PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 2603*494a190aSStefano Zampini PetscCall(PetscViewerASCIIGetStdout(comm, &viewer)); 2604*494a190aSStefano Zampini PetscCall(PetscViewerASCIIGetTab(viewer, &tabs)); 2605*494a190aSStefano Zampini PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel)); 2606*494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Function -------------\n")); 2607*494a190aSStefano Zampini if (!complete_print && !directionsprinted) { 2608*494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Run with -snes_test_function_view and optionally -snes_test_function <threshold> to show difference\n")); 2609*494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " of hand-coded and finite difference function entries greater than <threshold>.\n")); 2610*494a190aSStefano Zampini } 2611*494a190aSStefano Zampini if (!directionsprinted) { 2612*494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Testing hand-coded Function, if (for double precision runs) ||F - Ffd||/||F|| is\n")); 2613*494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " O(1.e-8), the hand-coded Function is probably correct.\n")); 2614*494a190aSStefano Zampini directionsprinted = PETSC_TRUE; 2615*494a190aSStefano Zampini } 2616*494a190aSStefano Zampini if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format)); 2617*494a190aSStefano Zampini 2618*494a190aSStefano Zampini PetscCall(SNESGetSolution(snes, &x)); 2619*494a190aSStefano Zampini PetscCall(VecDuplicate(x, &g1)); 2620*494a190aSStefano Zampini PetscCall(VecDuplicate(x, &g2)); 2621*494a190aSStefano Zampini PetscCall(VecDuplicate(x, &g3)); 2622*494a190aSStefano Zampini PetscCall(SNESComputeFunction(snes, x, g1)); 2623*494a190aSStefano Zampini PetscCall(SNESComputeFunction_FD(snes, x, g2)); 2624*494a190aSStefano Zampini 2625*494a190aSStefano Zampini PetscCall(VecNorm(g2, NORM_2, &fdnorm)); 2626*494a190aSStefano Zampini PetscCall(VecNorm(g1, NORM_2, &hcnorm)); 2627*494a190aSStefano Zampini PetscCall(VecNorm(g2, NORM_INFINITY, &fdmax)); 2628*494a190aSStefano Zampini PetscCall(VecNorm(g1, NORM_INFINITY, &hcmax)); 2629*494a190aSStefano Zampini PetscCall(VecDot(g1, g2, &dot)); 2630*494a190aSStefano Zampini PetscCall(VecCopy(g1, g3)); 2631*494a190aSStefano Zampini PetscCall(VecAXPY(g3, -1.0, g2)); 2632*494a190aSStefano Zampini PetscCall(VecNorm(g3, NORM_2, &diffnorm)); 2633*494a190aSStefano Zampini PetscCall(VecNorm(g3, NORM_INFINITY, &diffmax)); 2634*494a190aSStefano 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)))); 2635*494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " 2-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffnorm / PetscMax(hcnorm, fdnorm)), (double)diffnorm)); 2636*494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " max-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffmax / PetscMax(hcmax, fdmax)), (double)diffmax)); 2637*494a190aSStefano Zampini 2638*494a190aSStefano Zampini if (complete_print) { 2639*494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded function ----------\n")); 2640*494a190aSStefano Zampini PetscCall(VecView(g1, mviewer)); 2641*494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Finite difference function ----------\n")); 2642*494a190aSStefano Zampini PetscCall(VecView(g2, mviewer)); 2643*494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded minus finite-difference function ----------\n")); 2644*494a190aSStefano Zampini PetscCall(VecView(g3, mviewer)); 2645*494a190aSStefano Zampini } 2646*494a190aSStefano Zampini PetscCall(VecDestroy(&g1)); 2647*494a190aSStefano Zampini PetscCall(VecDestroy(&g2)); 2648*494a190aSStefano Zampini PetscCall(VecDestroy(&g3)); 2649*494a190aSStefano Zampini 2650*494a190aSStefano Zampini if (complete_print) { 2651*494a190aSStefano Zampini PetscCall(PetscViewerPopFormat(mviewer)); 2652*494a190aSStefano Zampini PetscCall(PetscViewerDestroy(&mviewer)); 2653*494a190aSStefano Zampini } 2654*494a190aSStefano Zampini PetscCall(PetscViewerASCIISetTab(viewer, tabs)); 2655*494a190aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2656*494a190aSStefano Zampini } 2657*494a190aSStefano Zampini 2658d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestJacobian(SNES snes) 2659d71ae5a4SJacob Faibussowitsch { 266012837594SBarry Smith Mat A, B, C, D, jacobian; 2661e885f1abSBarry Smith Vec x = snes->vec_sol, f = snes->vec_func; 2662e885f1abSBarry Smith PetscReal nrm, gnorm; 266381e7118cSBarry Smith PetscReal threshold = 1.e-5; 26640e276705SLisandro Dalcin MatType mattype; 2665e885f1abSBarry Smith PetscInt m, n, M, N; 2666e885f1abSBarry Smith void *functx; 26672cd624f9SStefano Zampini PetscBool complete_print = PETSC_FALSE, threshold_print = PETSC_FALSE, test = PETSC_FALSE, flg, istranspose; 26683325ff46SBarry Smith PetscViewer viewer, mviewer; 2669e885f1abSBarry Smith MPI_Comm comm; 2670e885f1abSBarry Smith PetscInt tabs; 267112837594SBarry Smith static PetscBool directionsprinted = PETSC_FALSE; 26723325ff46SBarry Smith PetscViewerFormat format; 2673e885f1abSBarry Smith 2674e885f1abSBarry Smith PetscFunctionBegin; 2675d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)snes); 26769566063dSJacob Faibussowitsch PetscCall(PetscOptionsName("-snes_test_jacobian", "Compare hand-coded and finite difference Jacobians", "None", &test)); 26779566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-snes_test_jacobian", "Threshold for element difference between hand-coded and finite difference being meaningful", "None", threshold, &threshold, NULL)); 26789566063dSJacob Faibussowitsch PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display", "-snes_test_jacobian_view", "3.13", NULL)); 26794ead3382SBarry Smith PetscCall(PetscOptionsViewer("-snes_test_jacobian_view", "View difference between hand-coded and finite difference Jacobians element entries", "None", &mviewer, &format, &complete_print)); 26809566063dSJacob Faibussowitsch PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display_threshold", "-snes_test_jacobian", "3.13", "-snes_test_jacobian accepts an optional threshold (since v3.10)")); 26819566063dSJacob 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)); 2682d0609cedSBarry Smith PetscOptionsEnd(); 26833ba16761SJacob Faibussowitsch if (!test) PetscFunctionReturn(PETSC_SUCCESS); 2684e885f1abSBarry Smith 26859566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 26869566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(comm, &viewer)); 26879566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetTab(viewer, &tabs)); 26889566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel)); 26899566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Jacobian -------------\n")); 269012837594SBarry Smith if (!complete_print && !directionsprinted) { 26919566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Run with -snes_test_jacobian_view and optionally -snes_test_jacobian <threshold> to show difference\n")); 26929566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " of hand-coded and finite difference Jacobian entries greater than <threshold>.\n")); 269312837594SBarry Smith } 269412837594SBarry Smith if (!directionsprinted) { 26959566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Testing hand-coded Jacobian, if (for double precision runs) ||J - Jfd||_F/||J||_F is\n")); 26969566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " O(1.e-8), the hand-coded Jacobian is probably correct.\n")); 269712837594SBarry Smith directionsprinted = PETSC_TRUE; 2698e885f1abSBarry Smith } 26991baa6e33SBarry Smith if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format)); 2700e885f1abSBarry Smith 27019566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes->jacobian, MATMFFD, &flg)); 270212837594SBarry Smith if (!flg) jacobian = snes->jacobian; 270312837594SBarry Smith else jacobian = snes->jacobian_pre; 270412837594SBarry Smith 2705a82339d0SMatthew G. Knepley if (!x) { 27069566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(jacobian, &x, NULL)); 2707a82339d0SMatthew G. Knepley } else { 27089566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)x)); 2709a82339d0SMatthew G. Knepley } 2710a82339d0SMatthew G. Knepley if (!f) { 27119566063dSJacob Faibussowitsch PetscCall(VecDuplicate(x, &f)); 2712a82339d0SMatthew G. Knepley } else { 27139566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)f)); 2714a82339d0SMatthew G. Knepley } 2715a82339d0SMatthew G. Knepley /* evaluate the function at this point because SNESComputeJacobianDefault() assumes that the function has been evaluated and put into snes->vec_func */ 27169566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, x, f)); 27179566063dSJacob Faibussowitsch PetscCall(VecDestroy(&f)); 27189566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESKSPTRANSPOSEONLY, &istranspose)); 271912837594SBarry Smith while (jacobian) { 27202cd624f9SStefano Zampini Mat JT = NULL, Jsave = NULL; 27212cd624f9SStefano Zampini 27222cd624f9SStefano Zampini if (istranspose) { 27239566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(jacobian, &JT)); 27242cd624f9SStefano Zampini Jsave = jacobian; 27252cd624f9SStefano Zampini jacobian = JT; 27262cd624f9SStefano Zampini } 27279566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)jacobian, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, "")); 272812837594SBarry Smith if (flg) { 272912837594SBarry Smith A = jacobian; 27309566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 273112837594SBarry Smith } else { 27329566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(jacobian, MATAIJ, &A)); 273312837594SBarry Smith } 2734e885f1abSBarry Smith 27359566063dSJacob Faibussowitsch PetscCall(MatGetType(A, &mattype)); 27369566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &M, &N)); 27379566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &m, &n)); 27389566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B)); 27399566063dSJacob Faibussowitsch PetscCall(MatSetType(B, mattype)); 27409566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, m, n, M, N)); 27419566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(B, A, A)); 27429566063dSJacob Faibussowitsch PetscCall(MatSetUp(B)); 27439566063dSJacob Faibussowitsch PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 2744e885f1abSBarry Smith 27459566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, NULL, &functx)); 27469566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobianDefault(snes, x, B, B, functx)); 274712837594SBarry Smith 27489566063dSJacob Faibussowitsch PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &D)); 27499566063dSJacob Faibussowitsch PetscCall(MatAYPX(D, -1.0, A, DIFFERENT_NONZERO_PATTERN)); 27509566063dSJacob Faibussowitsch PetscCall(MatNorm(D, NORM_FROBENIUS, &nrm)); 27519566063dSJacob Faibussowitsch PetscCall(MatNorm(A, NORM_FROBENIUS, &gnorm)); 27529566063dSJacob Faibussowitsch PetscCall(MatDestroy(&D)); 275312837594SBarry Smith if (!gnorm) gnorm = 1; /* just in case */ 27549566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " ||J - Jfd||_F/||J||_F = %g, ||J - Jfd||_F = %g\n", (double)(nrm / gnorm), (double)nrm)); 275512837594SBarry Smith 2756e885f1abSBarry Smith if (complete_print) { 27579566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded Jacobian ----------\n")); 27589566063dSJacob Faibussowitsch PetscCall(MatView(A, mviewer)); 27599566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Finite difference Jacobian ----------\n")); 27609566063dSJacob Faibussowitsch PetscCall(MatView(B, mviewer)); 2761e885f1abSBarry Smith } 2762e885f1abSBarry Smith 2763df10fb39SFande Kong if (threshold_print || complete_print) { 2764e885f1abSBarry Smith PetscInt Istart, Iend, *ccols, bncols, cncols, j, row; 2765e885f1abSBarry Smith PetscScalar *cvals; 2766e885f1abSBarry Smith const PetscInt *bcols; 2767e885f1abSBarry Smith const PetscScalar *bvals; 2768e885f1abSBarry Smith 27699566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C)); 27709566063dSJacob Faibussowitsch PetscCall(MatSetType(C, mattype)); 27719566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, m, n, M, N)); 27729566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(C, A, A)); 27739566063dSJacob Faibussowitsch PetscCall(MatSetUp(C)); 27749566063dSJacob Faibussowitsch PetscCall(MatSetOption(C, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 27750e276705SLisandro Dalcin 27769566063dSJacob Faibussowitsch PetscCall(MatAYPX(B, -1.0, A, DIFFERENT_NONZERO_PATTERN)); 27779566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(B, &Istart, &Iend)); 2778e885f1abSBarry Smith 2779e885f1abSBarry Smith for (row = Istart; row < Iend; row++) { 27809566063dSJacob Faibussowitsch PetscCall(MatGetRow(B, row, &bncols, &bcols, &bvals)); 27819566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(bncols, &ccols, bncols, &cvals)); 2782e885f1abSBarry Smith for (j = 0, cncols = 0; j < bncols; j++) { 278323a52b1dSBarry Smith if (PetscAbsScalar(bvals[j]) > threshold) { 2784e885f1abSBarry Smith ccols[cncols] = bcols[j]; 2785e885f1abSBarry Smith cvals[cncols] = bvals[j]; 2786e885f1abSBarry Smith cncols += 1; 2787e885f1abSBarry Smith } 2788e885f1abSBarry Smith } 278948a46eb9SPierre Jolivet if (cncols) PetscCall(MatSetValues(C, 1, &row, cncols, ccols, cvals, INSERT_VALUES)); 27909566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(B, row, &bncols, &bcols, &bvals)); 27919566063dSJacob Faibussowitsch PetscCall(PetscFree2(ccols, cvals)); 2792e885f1abSBarry Smith } 27939566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 27949566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 27959566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded minus finite-difference Jacobian with tolerance %g ----------\n", (double)threshold)); 27969566063dSJacob Faibussowitsch PetscCall(MatView(C, complete_print ? mviewer : viewer)); 27979566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C)); 2798e885f1abSBarry Smith } 27999566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A)); 28009566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 28019566063dSJacob Faibussowitsch PetscCall(MatDestroy(&JT)); 28022cd624f9SStefano Zampini if (Jsave) jacobian = Jsave; 280312837594SBarry Smith if (jacobian != snes->jacobian_pre) { 280412837594SBarry Smith jacobian = snes->jacobian_pre; 28059566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Jacobian for preconditioner -------------\n")); 28069371c9d4SSatish Balay } else jacobian = NULL; 280712837594SBarry Smith } 28089566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); 28091baa6e33SBarry Smith if (complete_print) PetscCall(PetscViewerPopFormat(mviewer)); 2810cd791dc2SBarry Smith if (mviewer) PetscCall(PetscOptionsRestoreViewer(&mviewer)); 28119566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISetTab(viewer, tabs)); 28123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2813e885f1abSBarry Smith } 2814e885f1abSBarry Smith 281562fef451SLois Curfman McInnes /*@ 2816f6dfbefdSBarry Smith SNESComputeJacobian - Computes the Jacobian matrix that has been set with `SNESSetJacobian()`. 281762fef451SLois Curfman McInnes 2818c3339decSBarry Smith Collective 2819c7afd0dbSLois Curfman McInnes 282062fef451SLois Curfman McInnes Input Parameters: 2821f6dfbefdSBarry Smith + snes - the `SNES` context 2822e4094ef1SJacob Faibussowitsch - X - input vector 282362fef451SLois Curfman McInnes 282462fef451SLois Curfman McInnes Output Parameters: 2825c7afd0dbSLois Curfman McInnes + A - Jacobian matrix 2826420bcc1bSBarry Smith - B - optional matrix for building the preconditioner, usually the same as `A` 2827fee21e36SBarry Smith 2828e35cf81dSBarry Smith Options Database Keys: 282967b8a455SSatish Balay + -snes_lag_preconditioner <lag> - how often to rebuild preconditioner 283067b8a455SSatish Balay . -snes_lag_jacobian <lag> - how often to rebuild Jacobian 2831455a5933SJed 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. 2832455a5933SJed 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 2833693365a8SJed Brown . -snes_compare_explicit - Compare the computed Jacobian to the finite difference Jacobian and output the differences 2834693365a8SJed Brown . -snes_compare_explicit_draw - Compare the computed Jacobian to the finite difference Jacobian and draw the result 2835693365a8SJed Brown . -snes_compare_explicit_contour - Compare the computed Jacobian to the finite difference Jacobian and draw a contour plot with the result 28364c30e9fbSJed Brown . -snes_compare_operator - Make the comparison options above use the operator instead of the preconditioning matrix 283794d6a431SBarry Smith . -snes_compare_coloring - Compute the finite difference Jacobian using coloring and display norms of difference 2838a5b23f4aSJose E. Roman . -snes_compare_coloring_display - Compute the finite difference Jacobian using coloring and display verbose differences 2839c01495d3SJed Brown . -snes_compare_coloring_threshold - Display only those matrix entries that differ by more than a given threshold 2840dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_atol - Absolute tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold` 2841dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_rtol - Relative tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold` 2842a5b23f4aSJose E. Roman . -snes_compare_coloring_draw - Compute the finite difference Jacobian using coloring and draw differences 2843a5b23f4aSJose E. Roman - -snes_compare_coloring_draw_contour - Compute the finite difference Jacobian using coloring and show contours of matrices and differences 2844c01495d3SJed Brown 2845dc4c0fb0SBarry Smith Level: developer 2846dc4c0fb0SBarry Smith 2847f6dfbefdSBarry Smith Note: 284862fef451SLois Curfman McInnes Most users should not need to explicitly call this routine, as it 284962fef451SLois Curfman McInnes is used internally within the nonlinear solvers. 285062fef451SLois Curfman McInnes 2851420bcc1bSBarry Smith Developer Note: 2852dc4c0fb0SBarry 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 2853420bcc1bSBarry Smith with the `SNESType` of test that has been removed. 2854e885f1abSBarry Smith 28551cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetJacobian()`, `KSPSetOperators()`, `MatStructure`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()` 285662fef451SLois Curfman McInnes @*/ 2857d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeJacobian(SNES snes, Vec X, Mat A, Mat B) 2858d71ae5a4SJacob Faibussowitsch { 2859ace3abfcSBarry Smith PetscBool flag; 28606cab3a1bSJed Brown DM dm; 2861942e3340SBarry Smith DMSNES sdm; 2862e0e3a89bSBarry Smith KSP ksp; 28633a40ed3dSBarry Smith 28643a40ed3dSBarry Smith PetscFunctionBegin; 28650700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 28660700a824SBarry Smith PetscValidHeaderSpecific(X, VEC_CLASSID, 2); 2867c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, X, 2); 2868e0f629ddSJacob Faibussowitsch PetscCall(VecValidValues_Internal(X, 2, PETSC_TRUE)); 28699566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 28709566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 28713232da50SPeter Brune 287201c1178eSBarry Smith /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix-free */ 2873fe3ffe1eSBarry Smith if (snes->lagjacobian == -2) { 2874fe3ffe1eSBarry Smith snes->lagjacobian = -1; 2875f5af7f23SKarl Rupp 28769566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n")); 2877fe3ffe1eSBarry Smith } else if (snes->lagjacobian == -1) { 28789566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is -1\n")); 28799566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag)); 2880ebd3b9afSBarry Smith if (flag) { 28819566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 28829566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 2883ebd3b9afSBarry Smith } 28843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 288537ec4e1aSPeter Brune } else if (snes->lagjacobian > 1 && (snes->iter + snes->jac_iter) % snes->lagjacobian) { 288663a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagjacobian, snes->iter)); 28879566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag)); 2888ebd3b9afSBarry Smith if (flag) { 28899566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 28909566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 2891ebd3b9afSBarry Smith } 28923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2893e35cf81dSBarry Smith } 2894efd4aadfSBarry Smith if (snes->npc && snes->npcside == PC_LEFT) { 28959566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 28969566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 28973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2898d728fb7dSPeter Brune } 2899e35cf81dSBarry Smith 29009566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_JacobianEval, snes, X, A, B)); 29019566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(X)); 2902800f99ffSJeremy L Thompson { 2903800f99ffSJeremy L Thompson void *ctx; 2904800f99ffSJeremy L Thompson PetscErrorCode (*J)(SNES, Vec, Mat, Mat, void *); 2905800f99ffSJeremy L Thompson PetscCall(DMSNESGetJacobian(dm, &J, &ctx)); 2906800f99ffSJeremy L Thompson PetscCallBack("SNES callback Jacobian", (*J)(snes, X, A, B, ctx)); 2907800f99ffSJeremy L Thompson } 29089566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(X)); 29099566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_JacobianEval, snes, X, A, B)); 291028d58a37SPierre Jolivet 291128d58a37SPierre Jolivet /* attach latest linearization point to the preconditioning matrix */ 29129566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)B, "__SNES_latest_X", (PetscObject)X)); 2913a8054027SBarry Smith 2914e0e3a89bSBarry Smith /* the next line ensures that snes->ksp exists */ 29159566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 29163b4f5425SBarry Smith if (snes->lagpreconditioner == -2) { 29179566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Rebuilding preconditioner exactly once since lag is -2\n")); 29189566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE)); 29193b4f5425SBarry Smith snes->lagpreconditioner = -1; 29203b4f5425SBarry Smith } else if (snes->lagpreconditioner == -1) { 29219566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is -1\n")); 29229566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE)); 292337ec4e1aSPeter Brune } else if (snes->lagpreconditioner > 1 && (snes->iter + snes->pre_iter) % snes->lagpreconditioner) { 292463a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagpreconditioner, snes->iter)); 29259566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE)); 2926d1e9a80fSBarry Smith } else { 29279566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Rebuilding preconditioner\n")); 29289566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE)); 2929a8054027SBarry Smith } 2930a8054027SBarry Smith 2931*494a190aSStefano Zampini PetscCall(SNESTestFunction(snes)); 29329566063dSJacob Faibussowitsch PetscCall(SNESTestJacobian(snes)); 2933*494a190aSStefano Zampini 29346d84be18SBarry Smith /* make sure user returned a correct Jacobian and preconditioner */ 293594ab13aaSBarry Smith /* PetscValidHeaderSpecific(A,MAT_CLASSID,3); 293694ab13aaSBarry Smith PetscValidHeaderSpecific(B,MAT_CLASSID,4); */ 2937693365a8SJed Brown { 2938693365a8SJed Brown PetscBool flag = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_operator = PETSC_FALSE; 29399566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit", NULL, NULL, &flag)); 29409566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw", NULL, NULL, &flag_draw)); 29419566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw_contour", NULL, NULL, &flag_contour)); 29429566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_operator", NULL, NULL, &flag_operator)); 2943693365a8SJed Brown if (flag || flag_draw || flag_contour) { 29440298fd71SBarry Smith Mat Bexp_mine = NULL, Bexp, FDexp; 2945693365a8SJed Brown PetscViewer vdraw, vstdout; 29466b3a5b13SJed Brown PetscBool flg; 2947693365a8SJed Brown if (flag_operator) { 29489566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(A, MATAIJ, &Bexp_mine)); 2949693365a8SJed Brown Bexp = Bexp_mine; 2950693365a8SJed Brown } else { 2951693365a8SJed Brown /* See if the preconditioning matrix can be viewed and added directly */ 29529566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)B, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPIBAIJ, "")); 295394ab13aaSBarry Smith if (flg) Bexp = B; 2954693365a8SJed Brown else { 2955693365a8SJed Brown /* If the "preconditioning" matrix is itself MATSHELL or some other type without direct support */ 29569566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(B, MATAIJ, &Bexp_mine)); 2957693365a8SJed Brown Bexp = Bexp_mine; 2958693365a8SJed Brown } 2959693365a8SJed Brown } 29609566063dSJacob Faibussowitsch PetscCall(MatConvert(Bexp, MATSAME, MAT_INITIAL_MATRIX, &FDexp)); 29619566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobianDefault(snes, X, FDexp, FDexp, NULL)); 29629566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout)); 2963693365a8SJed Brown if (flag_draw || flag_contour) { 29649566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Explicit Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw)); 29659566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 29660298fd71SBarry Smith } else vdraw = NULL; 29679566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit %s\n", flag_operator ? "Jacobian" : "preconditioning Jacobian")); 29689566063dSJacob Faibussowitsch if (flag) PetscCall(MatView(Bexp, vstdout)); 29699566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(Bexp, vdraw)); 29709566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Finite difference Jacobian\n")); 29719566063dSJacob Faibussowitsch if (flag) PetscCall(MatView(FDexp, vstdout)); 29729566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(FDexp, vdraw)); 29739566063dSJacob Faibussowitsch PetscCall(MatAYPX(FDexp, -1.0, Bexp, SAME_NONZERO_PATTERN)); 29749566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian\n")); 29759566063dSJacob Faibussowitsch if (flag) PetscCall(MatView(FDexp, vstdout)); 2976693365a8SJed Brown if (vdraw) { /* Always use contour for the difference */ 29779566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 29789566063dSJacob Faibussowitsch PetscCall(MatView(FDexp, vdraw)); 29799566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(vdraw)); 2980693365a8SJed Brown } 29819566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw)); 29829566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&vdraw)); 29839566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bexp_mine)); 29849566063dSJacob Faibussowitsch PetscCall(MatDestroy(&FDexp)); 2985693365a8SJed Brown } 2986693365a8SJed Brown } 29874c30e9fbSJed Brown { 29886719d8e4SJed Brown PetscBool flag = PETSC_FALSE, flag_display = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_threshold = PETSC_FALSE; 29896719d8e4SJed Brown PetscReal threshold_atol = PETSC_SQRT_MACHINE_EPSILON, threshold_rtol = 10 * PETSC_SQRT_MACHINE_EPSILON; 29909566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring", NULL, NULL, &flag)); 29919566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_display", NULL, NULL, &flag_display)); 29929566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw", NULL, NULL, &flag_draw)); 29939566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw_contour", NULL, NULL, &flag_contour)); 29949566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold", NULL, NULL, &flag_threshold)); 299527b0f280SBarry Smith if (flag_threshold) { 29969566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_rtol", &threshold_rtol, NULL)); 29979566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_atol", &threshold_atol, NULL)); 299827b0f280SBarry Smith } 29996719d8e4SJed Brown if (flag || flag_display || flag_draw || flag_contour || flag_threshold) { 30004c30e9fbSJed Brown Mat Bfd; 30014c30e9fbSJed Brown PetscViewer vdraw, vstdout; 3002335efc43SPeter Brune MatColoring coloring; 30034c30e9fbSJed Brown ISColoring iscoloring; 30044c30e9fbSJed Brown MatFDColoring matfdcoloring; 30054c30e9fbSJed Brown PetscErrorCode (*func)(SNES, Vec, Vec, void *); 30064c30e9fbSJed Brown void *funcctx; 30076719d8e4SJed Brown PetscReal norm1, norm2, normmax; 30084c30e9fbSJed Brown 30099566063dSJacob Faibussowitsch PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &Bfd)); 30109566063dSJacob Faibussowitsch PetscCall(MatColoringCreate(Bfd, &coloring)); 30119566063dSJacob Faibussowitsch PetscCall(MatColoringSetType(coloring, MATCOLORINGSL)); 30129566063dSJacob Faibussowitsch PetscCall(MatColoringSetFromOptions(coloring)); 30139566063dSJacob Faibussowitsch PetscCall(MatColoringApply(coloring, &iscoloring)); 30149566063dSJacob Faibussowitsch PetscCall(MatColoringDestroy(&coloring)); 30159566063dSJacob Faibussowitsch PetscCall(MatFDColoringCreate(Bfd, iscoloring, &matfdcoloring)); 30169566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFromOptions(matfdcoloring)); 30179566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetUp(Bfd, iscoloring, matfdcoloring)); 30189566063dSJacob Faibussowitsch PetscCall(ISColoringDestroy(&iscoloring)); 30194c30e9fbSJed Brown 30204c30e9fbSJed Brown /* This method of getting the function is currently unreliable since it doesn't work for DM local functions. */ 30219566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, &func, &funcctx)); 30229566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFunction(matfdcoloring, (PetscErrorCode(*)(void))func, funcctx)); 30239566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)matfdcoloring, ((PetscObject)snes)->prefix)); 30249566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)matfdcoloring, "coloring_")); 30259566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFromOptions(matfdcoloring)); 30269566063dSJacob Faibussowitsch PetscCall(MatFDColoringApply(Bfd, matfdcoloring, X, snes)); 30279566063dSJacob Faibussowitsch PetscCall(MatFDColoringDestroy(&matfdcoloring)); 30284c30e9fbSJed Brown 30299566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout)); 30304c30e9fbSJed Brown if (flag_draw || flag_contour) { 30319566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Colored Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw)); 30329566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 30330298fd71SBarry Smith } else vdraw = NULL; 30349566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit preconditioning Jacobian\n")); 30359566063dSJacob Faibussowitsch if (flag_display) PetscCall(MatView(B, vstdout)); 30369566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(B, vdraw)); 30379566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Colored Finite difference Jacobian\n")); 30389566063dSJacob Faibussowitsch if (flag_display) PetscCall(MatView(Bfd, vstdout)); 30399566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(Bfd, vdraw)); 30409566063dSJacob Faibussowitsch PetscCall(MatAYPX(Bfd, -1.0, B, SAME_NONZERO_PATTERN)); 30419566063dSJacob Faibussowitsch PetscCall(MatNorm(Bfd, NORM_1, &norm1)); 30429566063dSJacob Faibussowitsch PetscCall(MatNorm(Bfd, NORM_FROBENIUS, &norm2)); 30439566063dSJacob Faibussowitsch PetscCall(MatNorm(Bfd, NORM_MAX, &normmax)); 30449566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian, norm1=%g normFrob=%g normmax=%g\n", (double)norm1, (double)norm2, (double)normmax)); 30459566063dSJacob Faibussowitsch if (flag_display) PetscCall(MatView(Bfd, vstdout)); 30464c30e9fbSJed Brown if (vdraw) { /* Always use contour for the difference */ 30479566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 30489566063dSJacob Faibussowitsch PetscCall(MatView(Bfd, vdraw)); 30499566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(vdraw)); 30504c30e9fbSJed Brown } 30519566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw)); 30526719d8e4SJed Brown 30536719d8e4SJed Brown if (flag_threshold) { 30546719d8e4SJed Brown PetscInt bs, rstart, rend, i; 30559566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(B, &bs)); 30569566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(B, &rstart, &rend)); 30576719d8e4SJed Brown for (i = rstart; i < rend; i++) { 30586719d8e4SJed Brown const PetscScalar *ba, *ca; 30596719d8e4SJed Brown const PetscInt *bj, *cj; 30606719d8e4SJed Brown PetscInt bn, cn, j, maxentrycol = -1, maxdiffcol = -1, maxrdiffcol = -1; 30616719d8e4SJed Brown PetscReal maxentry = 0, maxdiff = 0, maxrdiff = 0; 30629566063dSJacob Faibussowitsch PetscCall(MatGetRow(B, i, &bn, &bj, &ba)); 30639566063dSJacob Faibussowitsch PetscCall(MatGetRow(Bfd, i, &cn, &cj, &ca)); 30645f80ce2aSJacob Faibussowitsch PetscCheck(bn == cn, ((PetscObject)A)->comm, PETSC_ERR_PLIB, "Unexpected different nonzero pattern in -snes_compare_coloring_threshold"); 30656719d8e4SJed Brown for (j = 0; j < bn; j++) { 30666719d8e4SJed Brown PetscReal rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j])); 30676719d8e4SJed Brown if (PetscAbsScalar(ba[j]) > PetscAbs(maxentry)) { 30686719d8e4SJed Brown maxentrycol = bj[j]; 30696719d8e4SJed Brown maxentry = PetscRealPart(ba[j]); 30706719d8e4SJed Brown } 30716719d8e4SJed Brown if (PetscAbsScalar(ca[j]) > PetscAbs(maxdiff)) { 30726719d8e4SJed Brown maxdiffcol = bj[j]; 30736719d8e4SJed Brown maxdiff = PetscRealPart(ca[j]); 30746719d8e4SJed Brown } 30756719d8e4SJed Brown if (rdiff > maxrdiff) { 30766719d8e4SJed Brown maxrdiffcol = bj[j]; 30776719d8e4SJed Brown maxrdiff = rdiff; 30786719d8e4SJed Brown } 30796719d8e4SJed Brown } 30806719d8e4SJed Brown if (maxrdiff > 1) { 308163a3b9bcSJacob 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)); 30826719d8e4SJed Brown for (j = 0; j < bn; j++) { 30836719d8e4SJed Brown PetscReal rdiff; 30846719d8e4SJed Brown rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j])); 308548a46eb9SPierre Jolivet if (rdiff > 1) PetscCall(PetscViewerASCIIPrintf(vstdout, " (%" PetscInt_FMT ",%g:%g)", bj[j], (double)PetscRealPart(ba[j]), (double)PetscRealPart(ca[j]))); 30866719d8e4SJed Brown } 308763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "\n")); 30886719d8e4SJed Brown } 30899566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(B, i, &bn, &bj, &ba)); 30909566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(Bfd, i, &cn, &cj, &ca)); 30916719d8e4SJed Brown } 30926719d8e4SJed Brown } 30939566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&vdraw)); 30949566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bfd)); 30954c30e9fbSJed Brown } 30964c30e9fbSJed Brown } 30973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30989b94acceSBarry Smith } 30999b94acceSBarry Smith 3100bf388a1fSBarry Smith /*MC 3101420bcc1bSBarry Smith SNESJacobianFunction - Functional form used by `SNES` to compute the nonlinear Jacobian of the function to be solved by `SNES` 3102bf388a1fSBarry Smith 3103bf388a1fSBarry Smith Synopsis: 3104411c0326SBarry Smith #include "petscsnes.h" 3105411c0326SBarry Smith PetscErrorCode SNESJacobianFunction(SNES snes,Vec x,Mat Amat,Mat Pmat,void *ctx); 3106bf388a1fSBarry Smith 3107c3339decSBarry Smith Collective 31081843f636SBarry Smith 31091843f636SBarry Smith Input Parameters: 31101843f636SBarry Smith + x - input vector, the Jacobian is to be computed at this value 3111bf388a1fSBarry Smith - ctx - [optional] user-defined Jacobian context 3112bf388a1fSBarry Smith 31131843f636SBarry Smith Output Parameters: 31141843f636SBarry Smith + Amat - the matrix that defines the (approximate) Jacobian 3115dc4c0fb0SBarry Smith - Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`. 31161843f636SBarry Smith 3117878cb397SSatish Balay Level: intermediate 3118878cb397SSatish Balay 31191cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESSetJacobian()`, `SNESGetJacobian()` 3120bf388a1fSBarry Smith M*/ 3121bf388a1fSBarry Smith 31229b94acceSBarry Smith /*@C 31239b94acceSBarry Smith SNESSetJacobian - Sets the function to compute Jacobian as well as the 3124044dda88SLois Curfman McInnes location to store the matrix. 31259b94acceSBarry Smith 3126c3339decSBarry Smith Logically Collective 3127c7afd0dbSLois Curfman McInnes 31289b94acceSBarry Smith Input Parameters: 3129f6dfbefdSBarry Smith + snes - the `SNES` context 3130e5d3d808SBarry Smith . Amat - the matrix that defines the (approximate) Jacobian 3131dc4c0fb0SBarry Smith . Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`. 3132dc4c0fb0SBarry Smith . J - Jacobian evaluation routine (if `NULL` then `SNES` retains any previously set value), see `SNESJacobianFunction` for details 3133c7afd0dbSLois Curfman McInnes - ctx - [optional] user-defined context for private data for the 3134dc4c0fb0SBarry Smith Jacobian evaluation routine (may be `NULL`) (if `NULL` then `SNES` retains any previously set value) 3135dc4c0fb0SBarry Smith 3136dc4c0fb0SBarry Smith Level: beginner 31379b94acceSBarry Smith 31389b94acceSBarry Smith Notes: 3139dc4c0fb0SBarry Smith If the `Amat` matrix and `Pmat` matrix are different you must call `MatAssemblyBegin()`/`MatAssemblyEnd()` on 314016913363SBarry Smith each matrix. 314116913363SBarry Smith 3142dc4c0fb0SBarry Smith If you know the operator `Amat` has a null space you can use `MatSetNullSpace()` and `MatSetTransposeNullSpace()` to supply the null 3143dc4c0fb0SBarry Smith space to `Amat` and the `KSP` solvers will automatically use that null space as needed during the solution process. 3144895c21f2SBarry Smith 3145dc4c0fb0SBarry Smith If using `SNESComputeJacobianDefaultColor()` to assemble a Jacobian, the `ctx` argument 3146f6dfbefdSBarry Smith must be a `MatFDColoring`. 3147a8a26c1eSJed Brown 3148c3cc8fd1SJed Brown Other defect-correction schemes can be used by computing a different matrix in place of the Jacobian. One common 3149f6dfbefdSBarry Smith example is to use the "Picard linearization" which only differentiates through the highest order parts of each term using `SNESSetPicard()` 3150c3cc8fd1SJed Brown 31511cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSPSetOperators()`, `SNESSetFunction()`, `MatMFFDComputeJacobian()`, `SNESComputeJacobianDefaultColor()`, `MatStructure`, 3152db781477SPatrick Sanan `SNESSetPicard()`, `SNESJacobianFunction` 31539b94acceSBarry Smith @*/ 3154d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetJacobian(SNES snes, Mat Amat, Mat Pmat, PetscErrorCode (*J)(SNES, Vec, Mat, Mat, void *), void *ctx) 3155d71ae5a4SJacob Faibussowitsch { 31566cab3a1bSJed Brown DM dm; 31573a7fca6bSBarry Smith 31583a40ed3dSBarry Smith PetscFunctionBegin; 31590700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3160e5d3d808SBarry Smith if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2); 3161e5d3d808SBarry Smith if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3); 3162e5d3d808SBarry Smith if (Amat) PetscCheckSameComm(snes, 1, Amat, 2); 3163e5d3d808SBarry Smith if (Pmat) PetscCheckSameComm(snes, 1, Pmat, 3); 31649566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 31659566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, J, ctx)); 3166e5d3d808SBarry Smith if (Amat) { 31679566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)Amat)); 31689566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian)); 3169f5af7f23SKarl Rupp 3170e5d3d808SBarry Smith snes->jacobian = Amat; 31713a7fca6bSBarry Smith } 3172e5d3d808SBarry Smith if (Pmat) { 31739566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)Pmat)); 31749566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian_pre)); 3175f5af7f23SKarl Rupp 3176e5d3d808SBarry Smith snes->jacobian_pre = Pmat; 31773a7fca6bSBarry Smith } 31783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 31799b94acceSBarry Smith } 318062fef451SLois Curfman McInnes 3181c2aafc4cSSatish Balay /*@C 3182b4fd4287SBarry Smith SNESGetJacobian - Returns the Jacobian matrix and optionally the user 3183b4fd4287SBarry Smith provided context for evaluating the Jacobian. 3184b4fd4287SBarry Smith 3185420bcc1bSBarry Smith Not Collective, but `Mat` object will be parallel if `SNES` is 3186c7afd0dbSLois Curfman McInnes 3187b4fd4287SBarry Smith Input Parameter: 3188b4fd4287SBarry Smith . snes - the nonlinear solver context 3189b4fd4287SBarry Smith 3190b4fd4287SBarry Smith Output Parameters: 3191dc4c0fb0SBarry Smith + Amat - location to stash (approximate) Jacobian matrix (or `NULL`) 3192dc4c0fb0SBarry Smith . Pmat - location to stash matrix used to compute the preconditioner (or `NULL`) 319320f4b53cSBarry Smith . J - location to put Jacobian function (or `NULL`), for calling sequence see `SNESJacobianFunction` 3194dc4c0fb0SBarry Smith - ctx - location to stash Jacobian ctx (or `NULL`) 3195fee21e36SBarry Smith 319636851e7fSLois Curfman McInnes Level: advanced 319736851e7fSLois Curfman McInnes 31981cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `Mat`, `SNESSetJacobian()`, `SNESComputeJacobian()`, `SNESJacobianFunction`, `SNESGetFunction()` 3199b4fd4287SBarry Smith @*/ 3200d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetJacobian(SNES snes, Mat *Amat, Mat *Pmat, PetscErrorCode (**J)(SNES, Vec, Mat, Mat, void *), void **ctx) 3201d71ae5a4SJacob Faibussowitsch { 32026cab3a1bSJed Brown DM dm; 32036cab3a1bSJed Brown 32043a40ed3dSBarry Smith PetscFunctionBegin; 32050700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3206e5d3d808SBarry Smith if (Amat) *Amat = snes->jacobian; 3207e5d3d808SBarry Smith if (Pmat) *Pmat = snes->jacobian_pre; 32089566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 3209800f99ffSJeremy L Thompson PetscCall(DMSNESGetJacobian(dm, J, ctx)); 32103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3211b4fd4287SBarry Smith } 3212b4fd4287SBarry Smith 3213d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetDefaultComputeJacobian(SNES snes) 3214d71ae5a4SJacob Faibussowitsch { 321558b371f3SBarry Smith DM dm; 321658b371f3SBarry Smith DMSNES sdm; 321758b371f3SBarry Smith 321858b371f3SBarry Smith PetscFunctionBegin; 32199566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 32209566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 322158b371f3SBarry Smith if (!sdm->ops->computejacobian && snes->jacobian_pre) { 322258b371f3SBarry Smith DM dm; 322358b371f3SBarry Smith PetscBool isdense, ismf; 322458b371f3SBarry Smith 32259566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 32269566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &isdense, MATSEQDENSE, MATMPIDENSE, MATDENSE, NULL)); 32279566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &ismf, MATMFFD, MATSHELL, NULL)); 322858b371f3SBarry Smith if (isdense) { 32299566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefault, NULL)); 323058b371f3SBarry Smith } else if (!ismf) { 32319566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefaultColor, NULL)); 323258b371f3SBarry Smith } 323358b371f3SBarry Smith } 32343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 323558b371f3SBarry Smith } 323658b371f3SBarry Smith 32379b94acceSBarry Smith /*@ 32389b94acceSBarry Smith SNESSetUp - Sets up the internal data structures for the later use 3239272ac6f2SLois Curfman McInnes of a nonlinear solver. 32409b94acceSBarry Smith 3241c3339decSBarry Smith Collective 3242fee21e36SBarry Smith 32432fe279fdSBarry Smith Input Parameter: 3244f6dfbefdSBarry Smith . snes - the `SNES` context 3245c7afd0dbSLois Curfman McInnes 3246dc4c0fb0SBarry Smith Level: advanced 3247dc4c0fb0SBarry Smith 3248f6dfbefdSBarry Smith Note: 3249f6dfbefdSBarry Smith For basic use of the `SNES` solvers the user need not explicitly call 3250f6dfbefdSBarry Smith `SNESSetUp()`, since these actions will automatically occur during 3251f6dfbefdSBarry Smith the call to `SNESSolve()`. However, if one wishes to control this 3252f6dfbefdSBarry Smith phase separately, `SNESSetUp()` should be called after `SNESCreate()` 3253f6dfbefdSBarry Smith and optional routines of the form SNESSetXXX(), but before `SNESSolve()`. 3254272ac6f2SLois Curfman McInnes 32551cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`, `SNESDestroy()` 32569b94acceSBarry Smith @*/ 3257d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUp(SNES snes) 3258d71ae5a4SJacob Faibussowitsch { 32596cab3a1bSJed Brown DM dm; 3260942e3340SBarry Smith DMSNES sdm; 3261c35f09e5SBarry Smith SNESLineSearch linesearch, pclinesearch; 32626e2a1849SPeter Brune void *lsprectx, *lspostctx; 32639b5c1c08SStefano Zampini PetscBool mf_operator, mf; 32649b5c1c08SStefano Zampini Vec f, fpc; 32659b5c1c08SStefano Zampini void *funcctx; 32669b5c1c08SStefano Zampini void *jacctx, *appctx; 32679b5c1c08SStefano Zampini Mat j, jpre; 32686b2b7091SBarry Smith PetscErrorCode (*precheck)(SNESLineSearch, Vec, Vec, PetscBool *, void *); 32696b2b7091SBarry Smith PetscErrorCode (*postcheck)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *); 32706e2a1849SPeter Brune PetscErrorCode (*func)(SNES, Vec, Vec, void *); 3271d1e9a80fSBarry Smith PetscErrorCode (*jac)(SNES, Vec, Mat, Mat, void *); 32723a40ed3dSBarry Smith 32733a40ed3dSBarry Smith PetscFunctionBegin; 32740700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 32753ba16761SJacob Faibussowitsch if (snes->setupcalled) PetscFunctionReturn(PETSC_SUCCESS); 3276fc8bc0e3SRichard Tran Mills PetscCall(PetscLogEventBegin(SNES_SetUp, snes, 0, 0, 0)); 32779b94acceSBarry Smith 327848a46eb9SPierre Jolivet if (!((PetscObject)snes)->type_name) PetscCall(SNESSetType(snes, SNESNEWTONLS)); 327985385478SLisandro Dalcin 32809566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &snes->vec_func, NULL, NULL)); 328158c9b817SLisandro Dalcin 32829566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 32839566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 32849566063dSJacob Faibussowitsch PetscCall(SNESSetDefaultComputeJacobian(snes)); 328558b371f3SBarry Smith 328648a46eb9SPierre Jolivet if (!snes->vec_func) PetscCall(DMCreateGlobalVector(dm, &snes->vec_func)); 3287efd51863SBarry Smith 328848a46eb9SPierre Jolivet if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 3289b710008aSBarry Smith 3290d8d34be6SBarry Smith if (snes->linesearch) { 32919566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 32929566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetFunction(snes->linesearch, SNESComputeFunction)); 3293d8d34be6SBarry Smith } 32949e764e56SPeter Brune 32959b5c1c08SStefano Zampini PetscCall(SNESGetUseMatrixFree(snes, &mf_operator, &mf)); 3296b552625fSStefano Zampini if (snes->npc && snes->npcside == PC_LEFT) { 3297172a4300SPeter Brune snes->mf = PETSC_TRUE; 3298172a4300SPeter Brune snes->mf_operator = PETSC_FALSE; 3299172a4300SPeter Brune } 3300d8f46077SPeter Brune 3301efd4aadfSBarry Smith if (snes->npc) { 33026e2a1849SPeter Brune /* copy the DM over */ 33039566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 33049566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes->npc, dm)); 33056e2a1849SPeter Brune 33069566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &f, &func, &funcctx)); 33079566063dSJacob Faibussowitsch PetscCall(VecDuplicate(f, &fpc)); 33089566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes->npc, fpc, func, funcctx)); 33099566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, &j, &jpre, &jac, &jacctx)); 33109566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes->npc, j, jpre, jac, jacctx)); 33119566063dSJacob Faibussowitsch PetscCall(SNESGetApplicationContext(snes, &appctx)); 33129566063dSJacob Faibussowitsch PetscCall(SNESSetApplicationContext(snes->npc, appctx)); 33139b5c1c08SStefano Zampini PetscCall(SNESSetUseMatrixFree(snes->npc, mf_operator, mf)); 33149566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fpc)); 33156e2a1849SPeter Brune 33166e2a1849SPeter Brune /* copy the function pointers over */ 33179566063dSJacob Faibussowitsch PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)snes->npc)); 33186e2a1849SPeter Brune 33196e2a1849SPeter Brune /* default to 1 iteration */ 33209566063dSJacob Faibussowitsch PetscCall(SNESSetTolerances(snes->npc, 0.0, 0.0, 0.0, 1, snes->npc->max_funcs)); 3321efd4aadfSBarry Smith if (snes->npcside == PC_RIGHT) { 33229566063dSJacob Faibussowitsch PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_FINAL_ONLY)); 3323a9936a0cSPeter Brune } else { 33249566063dSJacob Faibussowitsch PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_NONE)); 3325a9936a0cSPeter Brune } 33269566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes->npc)); 33276e2a1849SPeter Brune 33286e2a1849SPeter Brune /* copy the line search context over */ 3329d8d34be6SBarry Smith if (snes->linesearch && snes->npc->linesearch) { 33309566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &linesearch)); 33319566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes->npc, &pclinesearch)); 33329566063dSJacob Faibussowitsch PetscCall(SNESLineSearchGetPreCheck(linesearch, &precheck, &lsprectx)); 33339566063dSJacob Faibussowitsch PetscCall(SNESLineSearchGetPostCheck(linesearch, &postcheck, &lspostctx)); 33349566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetPreCheck(pclinesearch, precheck, lsprectx)); 33359566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetPostCheck(pclinesearch, postcheck, lspostctx)); 33369566063dSJacob Faibussowitsch PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch)); 33376e2a1849SPeter Brune } 3338d8d34be6SBarry Smith } 33391baa6e33SBarry Smith if (snes->mf) PetscCall(SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version)); 334048a46eb9SPierre Jolivet if (snes->ops->usercompute && !snes->user) PetscCall((*snes->ops->usercompute)(snes, (void **)&snes->user)); 33416e2a1849SPeter Brune 334237ec4e1aSPeter Brune snes->jac_iter = 0; 334337ec4e1aSPeter Brune snes->pre_iter = 0; 334437ec4e1aSPeter Brune 3345dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, setup); 334658c9b817SLisandro Dalcin 33479566063dSJacob Faibussowitsch PetscCall(SNESSetDefaultComputeJacobian(snes)); 334858b371f3SBarry Smith 3349b552625fSStefano Zampini if (snes->npc && snes->npcside == PC_LEFT) { 33506c67d002SPeter Brune if (snes->functype == SNES_FUNCTION_PRECONDITIONED) { 3351d8d34be6SBarry Smith if (snes->linesearch) { 33529566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &linesearch)); 33539566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunctionDefaultNPC)); 33546c67d002SPeter Brune } 33556c67d002SPeter Brune } 3356d8d34be6SBarry Smith } 3357fc8bc0e3SRichard Tran Mills PetscCall(PetscLogEventEnd(SNES_SetUp, snes, 0, 0, 0)); 33587aaed0d8SBarry Smith snes->setupcalled = PETSC_TRUE; 33593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 33609b94acceSBarry Smith } 33619b94acceSBarry Smith 336237596af1SLisandro Dalcin /*@ 3363f6dfbefdSBarry Smith SNESReset - Resets a `SNES` context to the snessetupcalled = 0 state and removes any allocated `Vec`s and `Mat`s 336437596af1SLisandro Dalcin 3365c3339decSBarry Smith Collective 336637596af1SLisandro Dalcin 336737596af1SLisandro Dalcin Input Parameter: 3368f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 336937596af1SLisandro Dalcin 3370d25893d9SBarry Smith Level: intermediate 3371d25893d9SBarry Smith 337295452b02SPatrick Sanan Notes: 3373f6dfbefdSBarry Smith Call this if you wish to reuse a `SNES` but with different size vectors 337437596af1SLisandro Dalcin 3375f6dfbefdSBarry Smith Also calls the application context destroy routine set with `SNESSetComputeApplicationContext()` 3376f6dfbefdSBarry Smith 33771cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESDestroy()`, `SNESCreate()`, `SNESSetUp()`, `SNESSolve()` 337837596af1SLisandro Dalcin @*/ 3379d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESReset(SNES snes) 3380d71ae5a4SJacob Faibussowitsch { 338137596af1SLisandro Dalcin PetscFunctionBegin; 338237596af1SLisandro Dalcin PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3383d25893d9SBarry Smith if (snes->ops->userdestroy && snes->user) { 33849566063dSJacob Faibussowitsch PetscCall((*snes->ops->userdestroy)((void **)&snes->user)); 33850298fd71SBarry Smith snes->user = NULL; 3386d25893d9SBarry Smith } 33871baa6e33SBarry Smith if (snes->npc) PetscCall(SNESReset(snes->npc)); 33888a23116dSBarry Smith 3389dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, reset); 33901baa6e33SBarry Smith if (snes->ksp) PetscCall(KSPReset(snes->ksp)); 33919e764e56SPeter Brune 33921baa6e33SBarry Smith if (snes->linesearch) PetscCall(SNESLineSearchReset(snes->linesearch)); 33939e764e56SPeter Brune 33949566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_rhs)); 33959566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol)); 33969566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol_update)); 33979566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_func)); 33989566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian)); 33999566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian_pre)); 34009566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->picard)); 34019566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(snes->nwork, &snes->work)); 34029566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(snes->nvwork, &snes->vwork)); 3403f5af7f23SKarl Rupp 340440fdac6aSLawrence Mitchell snes->alwayscomputesfinalresidual = PETSC_FALSE; 340540fdac6aSLawrence Mitchell 340637596af1SLisandro Dalcin snes->nwork = snes->nvwork = 0; 340737596af1SLisandro Dalcin snes->setupcalled = PETSC_FALSE; 34083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 340937596af1SLisandro Dalcin } 341037596af1SLisandro Dalcin 341152baeb72SSatish Balay /*@ 3412420bcc1bSBarry Smith SNESConvergedReasonViewCancel - Clears all the reason view functions for a `SNES` object provided with `SNESConvergedReasonViewSet()` 3413c4421ceaSFande Kong 3414c3339decSBarry Smith Collective 3415c4421ceaSFande Kong 3416c4421ceaSFande Kong Input Parameter: 3417f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 3418c4421ceaSFande Kong 3419c4421ceaSFande Kong Level: intermediate 3420c4421ceaSFande Kong 3421420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESReset()`, `SNESConvergedReasonViewSet()` 3422c4421ceaSFande Kong @*/ 3423d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewCancel(SNES snes) 3424d71ae5a4SJacob Faibussowitsch { 3425c4421ceaSFande Kong PetscInt i; 3426c4421ceaSFande Kong 3427c4421ceaSFande Kong PetscFunctionBegin; 3428c4421ceaSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3429c4421ceaSFande Kong for (i = 0; i < snes->numberreasonviews; i++) { 343048a46eb9SPierre Jolivet if (snes->reasonviewdestroy[i]) PetscCall((*snes->reasonviewdestroy[i])(&snes->reasonviewcontext[i])); 3431c4421ceaSFande Kong } 3432c4421ceaSFande Kong snes->numberreasonviews = 0; 34333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3434c4421ceaSFande Kong } 3435c4421ceaSFande Kong 34361fb7b255SJunchao Zhang /*@C 34379b94acceSBarry Smith SNESDestroy - Destroys the nonlinear solver context that was created 3438f6dfbefdSBarry Smith with `SNESCreate()`. 34399b94acceSBarry Smith 3440c3339decSBarry Smith Collective 3441c7afd0dbSLois Curfman McInnes 34429b94acceSBarry Smith Input Parameter: 3443f6dfbefdSBarry Smith . snes - the `SNES` context 34449b94acceSBarry Smith 344536851e7fSLois Curfman McInnes Level: beginner 344636851e7fSLois Curfman McInnes 34471cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()` 34489b94acceSBarry Smith @*/ 3449d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESDestroy(SNES *snes) 3450d71ae5a4SJacob Faibussowitsch { 34513a40ed3dSBarry Smith PetscFunctionBegin; 34523ba16761SJacob Faibussowitsch if (!*snes) PetscFunctionReturn(PETSC_SUCCESS); 34536bf464f9SBarry Smith PetscValidHeaderSpecific((*snes), SNES_CLASSID, 1); 34549371c9d4SSatish Balay if (--((PetscObject)(*snes))->refct > 0) { 34559371c9d4SSatish Balay *snes = NULL; 34563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 34579371c9d4SSatish Balay } 3458d4bb536fSBarry Smith 34599566063dSJacob Faibussowitsch PetscCall(SNESReset((*snes))); 34609566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&(*snes)->npc)); 34616b8b9a38SLisandro Dalcin 3462e04113cfSBarry Smith /* if memory was published with SAWs then destroy it */ 34639566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsViewOff((PetscObject)*snes)); 3464dbbe0bcdSBarry Smith PetscTryTypeMethod((*snes), destroy); 34656d4c513bSLisandro Dalcin 34669566063dSJacob Faibussowitsch if ((*snes)->dm) PetscCall(DMCoarsenHookRemove((*snes)->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, *snes)); 34679566063dSJacob Faibussowitsch PetscCall(DMDestroy(&(*snes)->dm)); 34689566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&(*snes)->ksp)); 34699566063dSJacob Faibussowitsch PetscCall(SNESLineSearchDestroy(&(*snes)->linesearch)); 34706b8b9a38SLisandro Dalcin 34719566063dSJacob Faibussowitsch PetscCall(PetscFree((*snes)->kspconvctx)); 347248a46eb9SPierre Jolivet if ((*snes)->ops->convergeddestroy) PetscCall((*(*snes)->ops->convergeddestroy)((*snes)->cnvP)); 347348a46eb9SPierre Jolivet if ((*snes)->conv_hist_alloc) PetscCall(PetscFree2((*snes)->conv_hist, (*snes)->conv_hist_its)); 34749566063dSJacob Faibussowitsch PetscCall(SNESMonitorCancel((*snes))); 34759566063dSJacob Faibussowitsch PetscCall(SNESConvergedReasonViewCancel((*snes))); 34769566063dSJacob Faibussowitsch PetscCall(PetscHeaderDestroy(snes)); 34773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 34789b94acceSBarry Smith } 34799b94acceSBarry Smith 34809b94acceSBarry Smith /* ----------- Routines to set solver parameters ---------- */ 34819b94acceSBarry Smith 3482a8054027SBarry Smith /*@ 3483a8054027SBarry Smith SNESSetLagPreconditioner - Determines when the preconditioner is rebuilt in the nonlinear solve. 3484a8054027SBarry Smith 3485c3339decSBarry Smith Logically Collective 3486a8054027SBarry Smith 3487a8054027SBarry Smith Input Parameters: 3488f6dfbefdSBarry Smith + snes - the `SNES` context 3489d8e291bfSBarry Smith - lag - 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time 34903b4f5425SBarry Smith the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that 3491a8054027SBarry Smith 3492a8054027SBarry Smith Options Database Keys: 3493420bcc1bSBarry Smith + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple `SNESSolve()` 34943d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 3495420bcc1bSBarry Smith . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple `SNESSolve()` 34963d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 3497a8054027SBarry Smith 3498dc4c0fb0SBarry Smith Level: intermediate 3499dc4c0fb0SBarry Smith 3500420bcc1bSBarry Smith Notes: 3501a8054027SBarry Smith The default is 1 3502420bcc1bSBarry Smith 3503f6dfbefdSBarry Smith The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagPreconditionerPersists()` was called 3504d8e291bfSBarry Smith 3505f6dfbefdSBarry Smith `SNESSetLagPreconditionerPersists()` allows using the same uniform lagging (for example every second linear solve) across multiple nonlinear solves. 3506a8054027SBarry Smith 35071cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetLagPreconditionerPersists()`, 3508f6dfbefdSBarry Smith `SNESSetLagJacobianPersists()`, `SNES`, `SNESSolve()` 3509a8054027SBarry Smith @*/ 3510d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditioner(SNES snes, PetscInt lag) 3511d71ae5a4SJacob Faibussowitsch { 3512a8054027SBarry Smith PetscFunctionBegin; 35130700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 35145f80ce2aSJacob Faibussowitsch PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater"); 35155f80ce2aSJacob Faibussowitsch PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0"); 3516c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, lag, 2); 3517a8054027SBarry Smith snes->lagpreconditioner = lag; 35183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3519a8054027SBarry Smith } 3520a8054027SBarry Smith 3521efd51863SBarry Smith /*@ 3522f6dfbefdSBarry Smith SNESSetGridSequence - sets the number of steps of grid sequencing that `SNES` will do 3523efd51863SBarry Smith 3524c3339decSBarry Smith Logically Collective 3525efd51863SBarry Smith 3526efd51863SBarry Smith Input Parameters: 3527f6dfbefdSBarry Smith + snes - the `SNES` context 3528efd51863SBarry Smith - steps - the number of refinements to do, defaults to 0 3529efd51863SBarry Smith 3530f6dfbefdSBarry Smith Options Database Key: 353167b8a455SSatish Balay . -snes_grid_sequence <steps> - Use grid sequencing to generate initial guess 3532efd51863SBarry Smith 3533efd51863SBarry Smith Level: intermediate 3534efd51863SBarry Smith 3535f6dfbefdSBarry Smith Note: 3536f6dfbefdSBarry Smith Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing. 3537c0df2a02SJed Brown 3538420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetGridSequence()`, 3539420bcc1bSBarry Smith `SNESetDM()` 3540efd51863SBarry Smith @*/ 3541d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetGridSequence(SNES snes, PetscInt steps) 3542d71ae5a4SJacob Faibussowitsch { 3543efd51863SBarry Smith PetscFunctionBegin; 3544efd51863SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3545efd51863SBarry Smith PetscValidLogicalCollectiveInt(snes, steps, 2); 3546efd51863SBarry Smith snes->gridsequence = steps; 35473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3548efd51863SBarry Smith } 3549efd51863SBarry Smith 3550fa19ca70SBarry Smith /*@ 3551f6dfbefdSBarry Smith SNESGetGridSequence - gets the number of steps of grid sequencing that `SNES` will do 3552fa19ca70SBarry Smith 3553c3339decSBarry Smith Logically Collective 3554fa19ca70SBarry Smith 3555fa19ca70SBarry Smith Input Parameter: 3556f6dfbefdSBarry Smith . snes - the `SNES` context 3557fa19ca70SBarry Smith 3558fa19ca70SBarry Smith Output Parameter: 3559fa19ca70SBarry Smith . steps - the number of refinements to do, defaults to 0 3560fa19ca70SBarry Smith 3561fa19ca70SBarry Smith Level: intermediate 3562fa19ca70SBarry Smith 35631cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetGridSequence()` 3564fa19ca70SBarry Smith @*/ 3565d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetGridSequence(SNES snes, PetscInt *steps) 3566d71ae5a4SJacob Faibussowitsch { 3567fa19ca70SBarry Smith PetscFunctionBegin; 3568fa19ca70SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3569fa19ca70SBarry Smith *steps = snes->gridsequence; 35703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3571fa19ca70SBarry Smith } 3572fa19ca70SBarry Smith 3573a8054027SBarry Smith /*@ 3574f6dfbefdSBarry Smith SNESGetLagPreconditioner - Return how often the preconditioner is rebuilt 3575a8054027SBarry Smith 35763f9fe445SBarry Smith Not Collective 3577a8054027SBarry Smith 3578a8054027SBarry Smith Input Parameter: 3579f6dfbefdSBarry Smith . snes - the `SNES` context 3580a8054027SBarry Smith 3581a8054027SBarry Smith Output Parameter: 3582a8054027SBarry 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 35833b4f5425SBarry Smith the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that 3584a8054027SBarry Smith 3585dc4c0fb0SBarry Smith Level: intermediate 3586dc4c0fb0SBarry Smith 3587a8054027SBarry Smith Notes: 3588a8054027SBarry Smith The default is 1 3589f6dfbefdSBarry Smith 3590a8054027SBarry Smith The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 3591a8054027SBarry Smith 35921cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3593a8054027SBarry Smith @*/ 3594d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagPreconditioner(SNES snes, PetscInt *lag) 3595d71ae5a4SJacob Faibussowitsch { 3596a8054027SBarry Smith PetscFunctionBegin; 35970700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3598a8054027SBarry Smith *lag = snes->lagpreconditioner; 35993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3600a8054027SBarry Smith } 3601a8054027SBarry Smith 3602e35cf81dSBarry Smith /*@ 3603f6dfbefdSBarry Smith SNESSetLagJacobian - Set when the Jacobian is rebuilt in the nonlinear solve. See `SNESSetLagPreconditioner()` for determining how 3604e35cf81dSBarry Smith often the preconditioner is rebuilt. 3605e35cf81dSBarry Smith 3606c3339decSBarry Smith Logically Collective 3607e35cf81dSBarry Smith 3608e35cf81dSBarry Smith Input Parameters: 3609f6dfbefdSBarry Smith + snes - the `SNES` context 3610e35cf81dSBarry 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 3611fe3ffe1eSBarry Smith the Jacobian is built etc. -2 means rebuild at next chance but then never again 3612e35cf81dSBarry Smith 3613e35cf81dSBarry Smith Options Database Keys: 361479a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 36153d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 361679a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 36173d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag. 3618e35cf81dSBarry Smith 3619dc4c0fb0SBarry Smith Level: intermediate 3620dc4c0fb0SBarry Smith 3621e35cf81dSBarry Smith Notes: 3622e35cf81dSBarry Smith The default is 1 3623f6dfbefdSBarry Smith 3624e35cf81dSBarry Smith The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 3625f6dfbefdSBarry Smith 3626fe3ffe1eSBarry 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 3627fe3ffe1eSBarry Smith at the next Newton step but never again (unless it is reset to another value) 3628e35cf81dSBarry Smith 36291cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagPreconditioner()`, `SNESGetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3630e35cf81dSBarry Smith @*/ 3631d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobian(SNES snes, PetscInt lag) 3632d71ae5a4SJacob Faibussowitsch { 3633e35cf81dSBarry Smith PetscFunctionBegin; 36340700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 36355f80ce2aSJacob Faibussowitsch PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater"); 36365f80ce2aSJacob Faibussowitsch PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0"); 3637c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, lag, 2); 3638e35cf81dSBarry Smith snes->lagjacobian = lag; 36393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3640e35cf81dSBarry Smith } 3641e35cf81dSBarry Smith 3642e35cf81dSBarry Smith /*@ 3643f6dfbefdSBarry Smith SNESGetLagJacobian - Get how often the Jacobian is rebuilt. See `SNESGetLagPreconditioner()` to determine when the preconditioner is rebuilt 3644e35cf81dSBarry Smith 36453f9fe445SBarry Smith Not Collective 3646e35cf81dSBarry Smith 3647e35cf81dSBarry Smith Input Parameter: 3648f6dfbefdSBarry Smith . snes - the `SNES` context 3649e35cf81dSBarry Smith 3650e35cf81dSBarry Smith Output Parameter: 3651e35cf81dSBarry 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 3652e35cf81dSBarry Smith the Jacobian is built etc. 3653e35cf81dSBarry Smith 3654dc4c0fb0SBarry Smith Level: intermediate 3655dc4c0fb0SBarry Smith 3656e35cf81dSBarry Smith Notes: 3657e35cf81dSBarry Smith The default is 1 3658f6dfbefdSBarry Smith 3659f6dfbefdSBarry Smith The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagJacobianPersists()` was called. 3660e35cf81dSBarry Smith 36611cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetLagJacobian()`, `SNESSetLagPreconditioner()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3662e35cf81dSBarry Smith 3663e35cf81dSBarry Smith @*/ 3664d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagJacobian(SNES snes, PetscInt *lag) 3665d71ae5a4SJacob Faibussowitsch { 3666e35cf81dSBarry Smith PetscFunctionBegin; 36670700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3668e35cf81dSBarry Smith *lag = snes->lagjacobian; 36693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3670e35cf81dSBarry Smith } 3671e35cf81dSBarry Smith 367237ec4e1aSPeter Brune /*@ 3673f6dfbefdSBarry Smith SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple nonlinear solves 367437ec4e1aSPeter Brune 3675c3339decSBarry Smith Logically collective 367637ec4e1aSPeter Brune 3677d8d19677SJose E. Roman Input Parameters: 3678f6dfbefdSBarry Smith + snes - the `SNES` context 36799d7e2deaSPeter Brune - flg - jacobian lagging persists if true 368037ec4e1aSPeter Brune 368137ec4e1aSPeter Brune Options Database Keys: 368279a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 36833d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 368479a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 36853d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 36863d5a8a6aSBarry Smith 3687dc4c0fb0SBarry Smith Level: advanced 3688dc4c0fb0SBarry Smith 368995452b02SPatrick Sanan Notes: 3690420bcc1bSBarry Smith Normally when `SNESSetLagJacobian()` is used, the Jacobian is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior 3691f6dfbefdSBarry Smith 369295452b02SPatrick Sanan This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by 369337ec4e1aSPeter Brune several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several 369437ec4e1aSPeter Brune timesteps may present huge efficiency gains. 369537ec4e1aSPeter Brune 369642747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditionerPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()` 369737ec4e1aSPeter Brune @*/ 3698d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobianPersists(SNES snes, PetscBool flg) 3699d71ae5a4SJacob Faibussowitsch { 370037ec4e1aSPeter Brune PetscFunctionBegin; 370137ec4e1aSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 370237ec4e1aSPeter Brune PetscValidLogicalCollectiveBool(snes, flg, 2); 370337ec4e1aSPeter Brune snes->lagjac_persist = flg; 37043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 370537ec4e1aSPeter Brune } 370637ec4e1aSPeter Brune 370737ec4e1aSPeter Brune /*@ 3708d8e291bfSBarry Smith SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple nonlinear solves 370937ec4e1aSPeter Brune 3710c3339decSBarry Smith Logically Collective 371137ec4e1aSPeter Brune 3712d8d19677SJose E. Roman Input Parameters: 3713f6dfbefdSBarry Smith + snes - the `SNES` context 37149d7e2deaSPeter Brune - flg - preconditioner lagging persists if true 371537ec4e1aSPeter Brune 371637ec4e1aSPeter Brune Options Database Keys: 371779a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 37183d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 371979a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 37203d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 372137ec4e1aSPeter Brune 3722dc4c0fb0SBarry Smith Level: developer 3723dc4c0fb0SBarry Smith 372495452b02SPatrick Sanan Notes: 3725420bcc1bSBarry Smith Normally when `SNESSetLagPreconditioner()` is used, the preconditioner is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior 3726f6dfbefdSBarry Smith 372795452b02SPatrick Sanan This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale 372837ec4e1aSPeter Brune by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over 372937ec4e1aSPeter Brune several timesteps may present huge efficiency gains. 373037ec4e1aSPeter Brune 37311cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobianPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagPreconditioner()` 373237ec4e1aSPeter Brune @*/ 3733d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes, PetscBool flg) 3734d71ae5a4SJacob Faibussowitsch { 373537ec4e1aSPeter Brune PetscFunctionBegin; 373637ec4e1aSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 373737ec4e1aSPeter Brune PetscValidLogicalCollectiveBool(snes, flg, 2); 373837ec4e1aSPeter Brune snes->lagpre_persist = flg; 37393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 374037ec4e1aSPeter Brune } 374137ec4e1aSPeter Brune 37429b94acceSBarry Smith /*@ 3743f6dfbefdSBarry Smith SNESSetForceIteration - force `SNESSolve()` to take at least one iteration regardless of the initial residual norm 3744be5caee7SBarry Smith 3745c3339decSBarry Smith Logically Collective 3746be5caee7SBarry Smith 3747be5caee7SBarry Smith Input Parameters: 3748f6dfbefdSBarry Smith + snes - the `SNES` context 3749f6dfbefdSBarry Smith - force - `PETSC_TRUE` require at least one iteration 3750be5caee7SBarry Smith 3751f6dfbefdSBarry Smith Options Database Key: 3752be5caee7SBarry Smith . -snes_force_iteration <force> - Sets forcing an iteration 3753be5caee7SBarry Smith 3754dc4c0fb0SBarry Smith Level: intermediate 3755dc4c0fb0SBarry Smith 3756f6dfbefdSBarry Smith Note: 3757f6dfbefdSBarry Smith This is used sometimes with `TS` to prevent `TS` from detecting a false steady state solution 3758be5caee7SBarry Smith 37591cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `TS`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()` 3760be5caee7SBarry Smith @*/ 3761d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetForceIteration(SNES snes, PetscBool force) 3762d71ae5a4SJacob Faibussowitsch { 3763be5caee7SBarry Smith PetscFunctionBegin; 3764be5caee7SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3765be5caee7SBarry Smith snes->forceiteration = force; 37663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3767be5caee7SBarry Smith } 3768be5caee7SBarry Smith 376985216dc7SFande Kong /*@ 3770f6dfbefdSBarry Smith SNESGetForceIteration - Check whether or not `SNESSolve()` take at least one iteration regardless of the initial residual norm 377185216dc7SFande Kong 3772c3339decSBarry Smith Logically Collective 377385216dc7SFande Kong 37742fe279fdSBarry Smith Input Parameter: 3775f6dfbefdSBarry Smith . snes - the `SNES` context 377685216dc7SFande Kong 377785216dc7SFande Kong Output Parameter: 3778dc4c0fb0SBarry Smith . force - `PETSC_TRUE` requires at least one iteration. 377985216dc7SFande Kong 378006dd6b0eSSatish Balay Level: intermediate 378106dd6b0eSSatish Balay 37821cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetForceIteration()`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()` 378385216dc7SFande Kong @*/ 3784d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetForceIteration(SNES snes, PetscBool *force) 3785d71ae5a4SJacob Faibussowitsch { 378685216dc7SFande Kong PetscFunctionBegin; 378785216dc7SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 378885216dc7SFande Kong *force = snes->forceiteration; 37893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 379085216dc7SFande Kong } 3791be5caee7SBarry Smith 3792be5caee7SBarry Smith /*@ 3793f6dfbefdSBarry Smith SNESSetTolerances - Sets `SNES` various parameters used in convergence tests. 37949b94acceSBarry Smith 3795c3339decSBarry Smith Logically Collective 3796c7afd0dbSLois Curfman McInnes 37979b94acceSBarry Smith Input Parameters: 3798f6dfbefdSBarry Smith + snes - the `SNES` context 379970441072SBarry Smith . abstol - absolute convergence tolerance 380033174efeSLois Curfman McInnes . rtol - relative convergence tolerance 38015358d0d4SBarry Smith . stol - convergence tolerance in terms of the norm of the change in the solution between steps, || delta x || < stol*|| x || 3802f6dfbefdSBarry Smith . maxit - maximum number of iterations, default 50. 3803f6dfbefdSBarry Smith - maxf - maximum number of function evaluations (-1 indicates no limit), default 1000 3804fee21e36SBarry Smith 380533174efeSLois Curfman McInnes Options Database Keys: 380670441072SBarry Smith + -snes_atol <abstol> - Sets abstol 3807c7afd0dbSLois Curfman McInnes . -snes_rtol <rtol> - Sets rtol 3808c7afd0dbSLois Curfman McInnes . -snes_stol <stol> - Sets stol 3809c7afd0dbSLois Curfman McInnes . -snes_max_it <maxit> - Sets maxit 3810c7afd0dbSLois Curfman McInnes - -snes_max_funcs <maxf> - Sets maxf 38119b94acceSBarry Smith 381236851e7fSLois Curfman McInnes Level: intermediate 381336851e7fSLois Curfman McInnes 381400677de2SStefano Zampini .seealso: [](ch_snes), `SNESSolve()`, `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()`, `SNESSetForceIteration()` 38159b94acceSBarry Smith @*/ 3816d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTolerances(SNES snes, PetscReal abstol, PetscReal rtol, PetscReal stol, PetscInt maxit, PetscInt maxf) 3817d71ae5a4SJacob Faibussowitsch { 38183a40ed3dSBarry Smith PetscFunctionBegin; 38190700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3820c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, abstol, 2); 3821c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, rtol, 3); 3822c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, stol, 4); 3823c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, maxit, 5); 3824c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, maxf, 6); 3825c5eb9154SBarry Smith 382613bcc0bdSJacob Faibussowitsch if (abstol != (PetscReal)PETSC_DEFAULT) { 38275f80ce2aSJacob Faibussowitsch PetscCheck(abstol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)abstol); 3828ab54825eSJed Brown snes->abstol = abstol; 3829ab54825eSJed Brown } 383013bcc0bdSJacob Faibussowitsch if (rtol != (PetscReal)PETSC_DEFAULT) { 38315f80ce2aSJacob 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); 3832ab54825eSJed Brown snes->rtol = rtol; 3833ab54825eSJed Brown } 383413bcc0bdSJacob Faibussowitsch if (stol != (PetscReal)PETSC_DEFAULT) { 38355f80ce2aSJacob Faibussowitsch PetscCheck(stol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Step tolerance %g must be non-negative", (double)stol); 3836c60f73f4SPeter Brune snes->stol = stol; 3837ab54825eSJed Brown } 3838ab54825eSJed Brown if (maxit != PETSC_DEFAULT) { 383963a3b9bcSJacob Faibussowitsch PetscCheck(maxit >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", maxit); 3840ab54825eSJed Brown snes->max_its = maxit; 3841ab54825eSJed Brown } 3842ab54825eSJed Brown if (maxf != PETSC_DEFAULT) { 384363a3b9bcSJacob Faibussowitsch PetscCheck(maxf >= -1, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations %" PetscInt_FMT " must be -1 or nonnegative", maxf); 3844ab54825eSJed Brown snes->max_funcs = maxf; 3845ab54825eSJed Brown } 384688976e71SPeter Brune snes->tolerancesset = PETSC_TRUE; 38473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 38489b94acceSBarry Smith } 38499b94acceSBarry Smith 3850e4d06f11SPatrick Farrell /*@ 3851f6dfbefdSBarry Smith SNESSetDivergenceTolerance - Sets the divergence tolerance used for the `SNES` divergence test. 3852e4d06f11SPatrick Farrell 3853c3339decSBarry Smith Logically Collective 3854e4d06f11SPatrick Farrell 3855e4d06f11SPatrick Farrell Input Parameters: 3856f6dfbefdSBarry Smith + snes - the `SNES` context 3857f6dfbefdSBarry Smith - divtol - the divergence tolerance. Use -1 to deactivate the test, default is 1e4 3858e4d06f11SPatrick Farrell 3859f6dfbefdSBarry Smith Options Database Key: 3860dc4c0fb0SBarry Smith . -snes_divergence_tolerance <divtol> - Sets `divtol` 3861e4d06f11SPatrick Farrell 3862e4d06f11SPatrick Farrell Level: intermediate 3863e4d06f11SPatrick Farrell 38641cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetTolerances()`, `SNESGetDivergenceTolerance` 3865e4d06f11SPatrick Farrell @*/ 3866d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDivergenceTolerance(SNES snes, PetscReal divtol) 3867d71ae5a4SJacob Faibussowitsch { 3868e4d06f11SPatrick Farrell PetscFunctionBegin; 3869e4d06f11SPatrick Farrell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3870e4d06f11SPatrick Farrell PetscValidLogicalCollectiveReal(snes, divtol, 2); 3871e4d06f11SPatrick Farrell 387213bcc0bdSJacob Faibussowitsch if (divtol != (PetscReal)PETSC_DEFAULT) { 3873e4d06f11SPatrick Farrell snes->divtol = divtol; 38749371c9d4SSatish Balay } else { 3875e4d06f11SPatrick Farrell snes->divtol = 1.0e4; 3876e4d06f11SPatrick Farrell } 38773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3878e4d06f11SPatrick Farrell } 3879e4d06f11SPatrick Farrell 38809b94acceSBarry Smith /*@ 388133174efeSLois Curfman McInnes SNESGetTolerances - Gets various parameters used in convergence tests. 388233174efeSLois Curfman McInnes 3883c7afd0dbSLois Curfman McInnes Not Collective 3884c7afd0dbSLois Curfman McInnes 388533174efeSLois Curfman McInnes Input Parameters: 3886f6dfbefdSBarry Smith + snes - the `SNES` context 388785385478SLisandro Dalcin . atol - absolute convergence tolerance 388833174efeSLois Curfman McInnes . rtol - relative convergence tolerance 388933174efeSLois Curfman McInnes . stol - convergence tolerance in terms of the norm 389033174efeSLois Curfman McInnes of the change in the solution between steps 389133174efeSLois Curfman McInnes . maxit - maximum number of iterations 3892c7afd0dbSLois Curfman McInnes - maxf - maximum number of function evaluations 3893fee21e36SBarry Smith 389436851e7fSLois Curfman McInnes Level: intermediate 389536851e7fSLois Curfman McInnes 3896dc4c0fb0SBarry Smith Note: 3897dc4c0fb0SBarry Smith The user can specify `NULL` for any parameter that is not needed. 3898dc4c0fb0SBarry Smith 38991cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTolerances()` 390033174efeSLois Curfman McInnes @*/ 3901d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetTolerances(SNES snes, PetscReal *atol, PetscReal *rtol, PetscReal *stol, PetscInt *maxit, PetscInt *maxf) 3902d71ae5a4SJacob Faibussowitsch { 39033a40ed3dSBarry Smith PetscFunctionBegin; 39040700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 390585385478SLisandro Dalcin if (atol) *atol = snes->abstol; 390633174efeSLois Curfman McInnes if (rtol) *rtol = snes->rtol; 3907c60f73f4SPeter Brune if (stol) *stol = snes->stol; 390833174efeSLois Curfman McInnes if (maxit) *maxit = snes->max_its; 390933174efeSLois Curfman McInnes if (maxf) *maxf = snes->max_funcs; 39103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 391133174efeSLois Curfman McInnes } 391233174efeSLois Curfman McInnes 3913e4d06f11SPatrick Farrell /*@ 3914e4d06f11SPatrick Farrell SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test. 3915e4d06f11SPatrick Farrell 3916e4d06f11SPatrick Farrell Not Collective 3917e4d06f11SPatrick Farrell 3918e4d06f11SPatrick Farrell Input Parameters: 3919f6dfbefdSBarry Smith + snes - the `SNES` context 3920e4d06f11SPatrick Farrell - divtol - divergence tolerance 3921e4d06f11SPatrick Farrell 3922e4d06f11SPatrick Farrell Level: intermediate 3923e4d06f11SPatrick Farrell 39241cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetDivergenceTolerance()` 3925e4d06f11SPatrick Farrell @*/ 3926d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDivergenceTolerance(SNES snes, PetscReal *divtol) 3927d71ae5a4SJacob Faibussowitsch { 3928e4d06f11SPatrick Farrell PetscFunctionBegin; 3929e4d06f11SPatrick Farrell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3930e4d06f11SPatrick Farrell if (divtol) *divtol = snes->divtol; 39313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3932e4d06f11SPatrick Farrell } 3933e4d06f11SPatrick Farrell 393433174efeSLois Curfman McInnes /*@ 39359b94acceSBarry Smith SNESSetTrustRegionTolerance - Sets the trust region parameter tolerance. 39369b94acceSBarry Smith 3937c3339decSBarry Smith Logically Collective 3938fee21e36SBarry Smith 3939c7afd0dbSLois Curfman McInnes Input Parameters: 3940f6dfbefdSBarry Smith + snes - the `SNES` context 3941c7afd0dbSLois Curfman McInnes - tol - tolerance 3942c7afd0dbSLois Curfman McInnes 39439b94acceSBarry Smith Options Database Key: 39444a221d59SStefano Zampini . -snes_tr_tol <tol> - Sets tol 39459b94acceSBarry Smith 394636851e7fSLois Curfman McInnes Level: intermediate 394736851e7fSLois Curfman McInnes 39481cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNEWTONTR`, `SNESSetTolerances()` 39499b94acceSBarry Smith @*/ 3950d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTrustRegionTolerance(SNES snes, PetscReal tol) 3951d71ae5a4SJacob Faibussowitsch { 39523a40ed3dSBarry Smith PetscFunctionBegin; 39530700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3954c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, tol, 2); 39559b94acceSBarry Smith snes->deltatol = tol; 39563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 39579b94acceSBarry Smith } 39589b94acceSBarry Smith 39596ba87a44SLisandro Dalcin PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *); 39606ba87a44SLisandro Dalcin 3961d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorLGRange(SNES snes, PetscInt n, PetscReal rnorm, void *monctx) 3962d71ae5a4SJacob Faibussowitsch { 3963b271bb04SBarry Smith PetscDrawLG lg; 3964b271bb04SBarry Smith PetscReal x, y, per; 3965b271bb04SBarry Smith PetscViewer v = (PetscViewer)monctx; 3966b271bb04SBarry Smith static PetscReal prev; /* should be in the context */ 3967b271bb04SBarry Smith PetscDraw draw; 3968b271bb04SBarry Smith 3969459f5d12SBarry Smith PetscFunctionBegin; 39704d4332d5SBarry Smith PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 4); 39719566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 0, &lg)); 39729566063dSJacob Faibussowitsch if (!n) PetscCall(PetscDrawLGReset(lg)); 39739566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 39749566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "Residual norm")); 3975b271bb04SBarry Smith x = (PetscReal)n; 397677b4d14cSPeter Brune if (rnorm > 0.0) y = PetscLog10Real(rnorm); 397794c9c6d3SKarl Rupp else y = -15.0; 39789566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 39796934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 39809566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 39819566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 3982b271bb04SBarry Smith } 3983b271bb04SBarry Smith 39849566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 1, &lg)); 39859566063dSJacob Faibussowitsch if (!n) PetscCall(PetscDrawLGReset(lg)); 39869566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 3987aaa8cc7dSPierre Jolivet PetscCall(PetscDrawSetTitle(draw, "% elements > .2*max element")); 39889566063dSJacob Faibussowitsch PetscCall(SNESMonitorRange_Private(snes, n, &per)); 3989b271bb04SBarry Smith x = (PetscReal)n; 3990b271bb04SBarry Smith y = 100.0 * per; 39919566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 39926934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 39939566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 39949566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 3995b271bb04SBarry Smith } 3996b271bb04SBarry Smith 39979566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 2, &lg)); 39989371c9d4SSatish Balay if (!n) { 39999371c9d4SSatish Balay prev = rnorm; 40009371c9d4SSatish Balay PetscCall(PetscDrawLGReset(lg)); 40019371c9d4SSatish Balay } 40029566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 40039566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm")); 4004b271bb04SBarry Smith x = (PetscReal)n; 4005b271bb04SBarry Smith y = (prev - rnorm) / prev; 40069566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 40076934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 40089566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 40099566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 4010b271bb04SBarry Smith } 4011b271bb04SBarry Smith 40129566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 3, &lg)); 40139566063dSJacob Faibussowitsch if (!n) PetscCall(PetscDrawLGReset(lg)); 40149566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 40159566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm*(% > .2 max)")); 4016b271bb04SBarry Smith x = (PetscReal)n; 4017b271bb04SBarry Smith y = (prev - rnorm) / (prev * per); 4018b271bb04SBarry Smith if (n > 2) { /*skip initial crazy value */ 40199566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 4020b271bb04SBarry Smith } 40216934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 40229566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 40239566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 4024b271bb04SBarry Smith } 4025b271bb04SBarry Smith prev = rnorm; 40263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4027b271bb04SBarry Smith } 4028b271bb04SBarry Smith 4029228d79bcSJed Brown /*@ 40302d157150SStefano Zampini SNESConverged - Run the convergence test and update the `SNESConvergedReason`. 40312d157150SStefano Zampini 40322d157150SStefano Zampini Collective 40332d157150SStefano Zampini 40342d157150SStefano Zampini Input Parameters: 40352d157150SStefano Zampini + snes - the `SNES` context 40362d157150SStefano Zampini . it - current iteration 40372d157150SStefano Zampini . xnorm - 2-norm of current iterate 40382d157150SStefano Zampini . snorm - 2-norm of current step 40392d157150SStefano Zampini - fnorm - 2-norm of function 40402d157150SStefano Zampini 40412d157150SStefano Zampini Level: developer 40422d157150SStefano Zampini 40432d157150SStefano Zampini Note: 4044420bcc1bSBarry Smith This routine is called by the `SNESSolve()` implementations. 40452d157150SStefano Zampini It does not typically need to be called by the user. 40462d157150SStefano Zampini 4047be50c303SSatish Balay .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`, `SNESGetConvergenceTest()` 40482d157150SStefano Zampini @*/ 40492d157150SStefano Zampini PetscErrorCode SNESConverged(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm) 40502d157150SStefano Zampini { 40512d157150SStefano Zampini PetscFunctionBegin; 40522d157150SStefano Zampini if (!snes->reason) { 40532d157150SStefano Zampini if (snes->normschedule == SNES_NORM_ALWAYS) PetscUseTypeMethod(snes, converged, it, xnorm, snorm, fnorm, &snes->reason, snes->cnvP); 40542d157150SStefano Zampini if (it == snes->max_its && !snes->reason) { 40552d157150SStefano Zampini if (snes->normschedule == SNES_NORM_ALWAYS) { 40562d157150SStefano Zampini PetscCall(PetscInfo(snes, "Maximum number of iterations has been reached: %" PetscInt_FMT "\n", snes->max_its)); 40572d157150SStefano Zampini snes->reason = SNES_DIVERGED_MAX_IT; 40582d157150SStefano Zampini } else snes->reason = SNES_CONVERGED_ITS; 40592d157150SStefano Zampini } 40602d157150SStefano Zampini } 40612d157150SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 40622d157150SStefano Zampini } 40632d157150SStefano Zampini 40642d157150SStefano Zampini /*@ 4065228d79bcSJed Brown SNESMonitor - runs the user provided monitor routines, if they exist 4066228d79bcSJed Brown 4067c3339decSBarry Smith Collective 4068228d79bcSJed Brown 4069228d79bcSJed Brown Input Parameters: 4070f6dfbefdSBarry Smith + snes - nonlinear solver context obtained from `SNESCreate()` 4071228d79bcSJed Brown . iter - iteration number 4072228d79bcSJed Brown - rnorm - relative norm of the residual 4073228d79bcSJed Brown 4074dc4c0fb0SBarry Smith Level: developer 4075dc4c0fb0SBarry Smith 4076f6dfbefdSBarry Smith Note: 4077420bcc1bSBarry Smith This routine is called by the `SNESSolve()` implementations. 4078228d79bcSJed Brown It does not typically need to be called by the user. 4079228d79bcSJed Brown 40801cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorSet()` 4081228d79bcSJed Brown @*/ 4082d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitor(SNES snes, PetscInt iter, PetscReal rnorm) 4083d71ae5a4SJacob Faibussowitsch { 40847a03ce2fSLisandro Dalcin PetscInt i, n = snes->numbermonitors; 40857a03ce2fSLisandro Dalcin 40867a03ce2fSLisandro Dalcin PetscFunctionBegin; 40875f3c5e7aSBarry Smith if (n > 0) SNESCheckFunctionNorm(snes, rnorm); 40889566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(snes->vec_sol)); 408948a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall((*snes->monitor[i])(snes, iter, rnorm, snes->monitorcontext[i])); 40909566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(snes->vec_sol)); 40913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 40927a03ce2fSLisandro Dalcin } 40937a03ce2fSLisandro Dalcin 40949b94acceSBarry Smith /* ------------ Routines to set performance monitoring options ----------- */ 40959b94acceSBarry Smith 4096bf388a1fSBarry Smith /*MC 4097f6dfbefdSBarry Smith SNESMonitorFunction - functional form passed to `SNESMonitorSet()` to monitor convergence of nonlinear solver 4098bf388a1fSBarry Smith 4099bf388a1fSBarry Smith Synopsis: 4100aaa7dc30SBarry Smith #include <petscsnes.h> 410137fdd005SBarry Smith PetscErrorCode SNESMonitorFunction(SNES snes, PetscInt its, PetscReal norm, void *mctx) 4102bf388a1fSBarry Smith 4103c3339decSBarry Smith Collective 41041843f636SBarry Smith 41051843f636SBarry Smith Input Parameters: 4106f6dfbefdSBarry Smith + snes - the `SNES` context 4107bf388a1fSBarry Smith . its - iteration number 4108bf388a1fSBarry Smith . norm - 2-norm function value (may be estimated) 4109bf388a1fSBarry Smith - mctx - [optional] monitoring context 4110bf388a1fSBarry Smith 4111878cb397SSatish Balay Level: advanced 4112878cb397SSatish Balay 41131cc06b55SBarry Smith .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSet()`, `SNESMonitorGet()` 4114bf388a1fSBarry Smith M*/ 4115bf388a1fSBarry Smith 41169b94acceSBarry Smith /*@C 4117a6570f20SBarry Smith SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every 41189b94acceSBarry Smith iteration of the nonlinear solver to display the iteration's 41199b94acceSBarry Smith progress. 41209b94acceSBarry Smith 4121c3339decSBarry Smith Logically Collective 4122fee21e36SBarry Smith 4123c7afd0dbSLois Curfman McInnes Input Parameters: 4124f6dfbefdSBarry Smith + snes - the `SNES` context 412520f4b53cSBarry Smith . f - the monitor function, for the calling sequence see `SNESMonitorFunction` 4126420bcc1bSBarry Smith . mctx - [optional] user-defined context for private data for the monitor routine (use `NULL` if no context is desired) 4127dc4c0fb0SBarry Smith - monitordestroy - [optional] routine that frees monitor context (may be `NULL`) 41289b94acceSBarry Smith 41299665c990SLois Curfman McInnes Options Database Keys: 4130f6dfbefdSBarry Smith + -snes_monitor - sets `SNESMonitorDefault()` 4131798534f6SMatthew G. Knepley . -snes_monitor draw::draw_lg - sets line graph monitor, 4132dc4c0fb0SBarry 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 4133c7afd0dbSLois Curfman McInnes the options database. 41349665c990SLois Curfman McInnes 4135dc4c0fb0SBarry Smith Level: intermediate 4136dc4c0fb0SBarry Smith 4137f6dfbefdSBarry Smith Note: 41386bc08f3fSLois Curfman McInnes Several different monitoring routines may be set by calling 4139f6dfbefdSBarry Smith `SNESMonitorSet()` multiple times; all will be called in the 41406bc08f3fSLois Curfman McInnes order in which they were set. 4141639f9d9dSBarry Smith 4142420bcc1bSBarry Smith Fortran Note: 4143f6dfbefdSBarry Smith Only a single monitor function can be set for each `SNES` object 4144025f1a04SBarry Smith 41451cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESMonitorDefault()`, `SNESMonitorCancel()`, `SNESMonitorFunction` 41469b94acceSBarry Smith @*/ 4147d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorSet(SNES snes, PetscErrorCode (*f)(SNES, PetscInt, PetscReal, void *), void *mctx, PetscErrorCode (*monitordestroy)(void **)) 4148d71ae5a4SJacob Faibussowitsch { 4149b90d0a6eSBarry Smith PetscInt i; 415078064530SBarry Smith PetscBool identical; 4151b90d0a6eSBarry Smith 41523a40ed3dSBarry Smith PetscFunctionBegin; 41530700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4154b90d0a6eSBarry Smith for (i = 0; i < snes->numbermonitors; i++) { 41559566063dSJacob Faibussowitsch PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, mctx, monitordestroy, (PetscErrorCode(*)(void))snes->monitor[i], snes->monitorcontext[i], snes->monitordestroy[i], &identical)); 41563ba16761SJacob Faibussowitsch if (identical) PetscFunctionReturn(PETSC_SUCCESS); 4157649052a6SBarry Smith } 41585f80ce2aSJacob Faibussowitsch PetscCheck(snes->numbermonitors < MAXSNESMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set"); 41596e4dcb14SBarry Smith snes->monitor[snes->numbermonitors] = f; 4160b8a78c4aSBarry Smith snes->monitordestroy[snes->numbermonitors] = monitordestroy; 4161639f9d9dSBarry Smith snes->monitorcontext[snes->numbermonitors++] = (void *)mctx; 41623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 41639b94acceSBarry Smith } 41649b94acceSBarry Smith 4165a278d85bSSatish Balay /*@ 4166f6dfbefdSBarry Smith SNESMonitorCancel - Clears all the monitor functions for a `SNES` object. 41675cd90555SBarry Smith 4168c3339decSBarry Smith Logically Collective 4169c7afd0dbSLois Curfman McInnes 41702fe279fdSBarry Smith Input Parameter: 4171f6dfbefdSBarry Smith . snes - the `SNES` context 41725cd90555SBarry Smith 41731a480d89SAdministrator Options Database Key: 4174a6570f20SBarry Smith . -snes_monitor_cancel - cancels all monitors that have been hardwired 4175dc4c0fb0SBarry Smith into a code by calls to `SNESMonitorSet()`, but does not cancel those 4176c7afd0dbSLois Curfman McInnes set via the options database 41775cd90555SBarry Smith 4178dc4c0fb0SBarry Smith Level: intermediate 4179dc4c0fb0SBarry Smith 4180f6dfbefdSBarry Smith Note: 4181f6dfbefdSBarry Smith There is no way to clear one specific monitor from a `SNES` object. 41825cd90555SBarry Smith 41831cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorGet()`, `SNESMonitorDefault()`, `SNESMonitorSet()` 41845cd90555SBarry Smith @*/ 4185d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorCancel(SNES snes) 4186d71ae5a4SJacob Faibussowitsch { 4187d952e501SBarry Smith PetscInt i; 4188d952e501SBarry Smith 41895cd90555SBarry Smith PetscFunctionBegin; 41900700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4191d952e501SBarry Smith for (i = 0; i < snes->numbermonitors; i++) { 419248a46eb9SPierre Jolivet if (snes->monitordestroy[i]) PetscCall((*snes->monitordestroy[i])(&snes->monitorcontext[i])); 4193d952e501SBarry Smith } 41945cd90555SBarry Smith snes->numbermonitors = 0; 41953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 41965cd90555SBarry Smith } 41975cd90555SBarry Smith 4198bf388a1fSBarry Smith /*MC 4199bf388a1fSBarry Smith SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver 4200bf388a1fSBarry Smith 4201bf388a1fSBarry Smith Synopsis: 4202aaa7dc30SBarry Smith #include <petscsnes.h> 420337fdd005SBarry Smith PetscErrorCode SNESConvergenceTest(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *cctx) 4204bf388a1fSBarry Smith 4205c3339decSBarry Smith Collective 42061843f636SBarry Smith 42071843f636SBarry Smith Input Parameters: 4208f6dfbefdSBarry Smith + snes - the `SNES` context 4209bf388a1fSBarry Smith . it - current iteration (0 is the first and is before any Newton step) 4210bf388a1fSBarry Smith . xnorm - 2-norm of current iterate 4211bf388a1fSBarry Smith . gnorm - 2-norm of current step 42121843f636SBarry Smith . f - 2-norm of function 42131843f636SBarry Smith - cctx - [optional] convergence context 42141843f636SBarry Smith 42151843f636SBarry Smith Output Parameter: 42161843f636SBarry Smith . reason - reason for convergence/divergence, only needs to be set when convergence or divergence is detected 4217bf388a1fSBarry Smith 4218878cb397SSatish Balay Level: intermediate 4219bf388a1fSBarry Smith 42201cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`, `SNESGetConvergenceTest()` 4221bf388a1fSBarry Smith M*/ 4222bf388a1fSBarry Smith 42239b94acceSBarry Smith /*@C 42249b94acceSBarry Smith SNESSetConvergenceTest - Sets the function that is to be used 42259b94acceSBarry Smith to test for convergence of the nonlinear iterative solution. 42269b94acceSBarry Smith 4227c3339decSBarry Smith Logically Collective 4228fee21e36SBarry Smith 4229c7afd0dbSLois Curfman McInnes Input Parameters: 4230f6dfbefdSBarry Smith + snes - the `SNES` context 4231e4094ef1SJacob Faibussowitsch . SNESConvergenceTestFunction - routine to test for convergence 4232dc4c0fb0SBarry Smith . cctx - [optional] context for private data for the convergence routine (may be `NULL`) 4233dc4c0fb0SBarry Smith - destroy - [optional] destructor for the context (may be `NULL`; `PETSC_NULL_FUNCTION` in Fortran) 42349b94acceSBarry Smith 423536851e7fSLois Curfman McInnes Level: advanced 423636851e7fSLois Curfman McInnes 42371cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedDefault()`, `SNESConvergedSkip()`, `SNESConvergenceTestFunction` 42389b94acceSBarry Smith @*/ 4239d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceTest(SNES snes, PetscErrorCode (*SNESConvergenceTestFunction)(SNES, PetscInt, PetscReal, PetscReal, PetscReal, SNESConvergedReason *, void *), void *cctx, PetscErrorCode (*destroy)(void *)) 4240d71ae5a4SJacob Faibussowitsch { 42413a40ed3dSBarry Smith PetscFunctionBegin; 42420700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4243e2a6519dSDmitry Karpeev if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip; 42441baa6e33SBarry Smith if (snes->ops->convergeddestroy) PetscCall((*snes->ops->convergeddestroy)(snes->cnvP)); 4245bf388a1fSBarry Smith snes->ops->converged = SNESConvergenceTestFunction; 42467f7931b9SBarry Smith snes->ops->convergeddestroy = destroy; 424785385478SLisandro Dalcin snes->cnvP = cctx; 42483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 42499b94acceSBarry Smith } 42509b94acceSBarry Smith 425152baeb72SSatish Balay /*@ 4252f6dfbefdSBarry Smith SNESGetConvergedReason - Gets the reason the `SNES` iteration was stopped. 4253184914b5SBarry Smith 4254184914b5SBarry Smith Not Collective 4255184914b5SBarry Smith 4256184914b5SBarry Smith Input Parameter: 4257f6dfbefdSBarry Smith . snes - the `SNES` context 4258184914b5SBarry Smith 4259184914b5SBarry Smith Output Parameter: 4260f6dfbefdSBarry Smith . reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` for the individual convergence tests for complete lists 4261184914b5SBarry Smith 4262f6dfbefdSBarry Smith Options Database Key: 42636a4d7782SBarry Smith . -snes_converged_reason - prints the reason to standard out 42646a4d7782SBarry Smith 4265184914b5SBarry Smith Level: intermediate 4266184914b5SBarry Smith 4267f6dfbefdSBarry Smith Note: 4268f6dfbefdSBarry Smith Should only be called after the call the `SNESSolve()` is complete, if it is called earlier it returns the value `SNES__CONVERGED_ITERATING`. 4269184914b5SBarry Smith 42701cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESSetConvergedReason()`, `SNESConvergedReason`, `SNESGetConvergedReasonString()` 4271184914b5SBarry Smith @*/ 4272d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReason(SNES snes, SNESConvergedReason *reason) 4273d71ae5a4SJacob Faibussowitsch { 4274184914b5SBarry Smith PetscFunctionBegin; 42750700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 42764f572ea9SToby Isaac PetscAssertPointer(reason, 2); 4277184914b5SBarry Smith *reason = snes->reason; 42783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4279184914b5SBarry Smith } 4280184914b5SBarry Smith 4281c4421ceaSFande Kong /*@C 4282f6dfbefdSBarry Smith SNESGetConvergedReasonString - Return a human readable string for `SNESConvergedReason` 4283c4421ceaSFande Kong 4284c4421ceaSFande Kong Not Collective 4285c4421ceaSFande Kong 4286c4421ceaSFande Kong Input Parameter: 4287f6dfbefdSBarry Smith . snes - the `SNES` context 4288c4421ceaSFande Kong 4289c4421ceaSFande Kong Output Parameter: 4290dc4c0fb0SBarry Smith . strreason - a human readable string that describes `SNES` converged reason 4291c4421ceaSFande Kong 429299c90e12SSatish Balay Level: beginner 4293c4421ceaSFande Kong 42941cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetConvergedReason()` 4295c4421ceaSFande Kong @*/ 4296d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReasonString(SNES snes, const char **strreason) 4297d71ae5a4SJacob Faibussowitsch { 4298c4421ceaSFande Kong PetscFunctionBegin; 4299c4421ceaSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 43004f572ea9SToby Isaac PetscAssertPointer(strreason, 2); 4301c4421ceaSFande Kong *strreason = SNESConvergedReasons[snes->reason]; 43023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4303c4421ceaSFande Kong } 4304c4421ceaSFande Kong 430533866048SMatthew G. Knepley /*@ 4306f6dfbefdSBarry Smith SNESSetConvergedReason - Sets the reason the `SNES` iteration was stopped. 430733866048SMatthew G. Knepley 430833866048SMatthew G. Knepley Not Collective 430933866048SMatthew G. Knepley 431033866048SMatthew G. Knepley Input Parameters: 4311f6dfbefdSBarry Smith + snes - the `SNES` context 4312f6dfbefdSBarry Smith - reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` or the 431333866048SMatthew G. Knepley manual pages for the individual convergence tests for complete lists 431433866048SMatthew G. Knepley 4315f6dfbefdSBarry Smith Level: developer 4316f6dfbefdSBarry Smith 4317420bcc1bSBarry Smith Developer Note: 4318f6dfbefdSBarry Smith Called inside the various `SNESSolve()` implementations 431933866048SMatthew G. Knepley 43201cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetConvergedReason()`, `SNESSetConvergenceTest()`, `SNESConvergedReason` 432133866048SMatthew G. Knepley @*/ 4322d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergedReason(SNES snes, SNESConvergedReason reason) 4323d71ae5a4SJacob Faibussowitsch { 432433866048SMatthew G. Knepley PetscFunctionBegin; 432533866048SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 43265f3c5e7aSBarry Smith PetscCheck(!snes->errorifnotconverged || reason > 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "SNES code should have previously errored due to negative reason"); 432733866048SMatthew G. Knepley snes->reason = reason; 43283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 432933866048SMatthew G. Knepley } 433033866048SMatthew G. Knepley 4331c9005455SLois Curfman McInnes /*@ 4332420bcc1bSBarry Smith SNESSetConvergenceHistory - Sets the arrays used to hold the convergence history. 4333c9005455SLois Curfman McInnes 4334c3339decSBarry Smith Logically Collective 4335fee21e36SBarry Smith 4336c7afd0dbSLois Curfman McInnes Input Parameters: 4337f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 43388c7482ecSBarry Smith . a - array to hold history, this array will contain the function norms computed at each step 4339cd5578b5SBarry Smith . its - integer array holds the number of linear iterations for each solve. 4340420bcc1bSBarry Smith . na - size of `a` and `its` 4341f6dfbefdSBarry Smith - reset - `PETSC_TRUE` indicates each new nonlinear solve resets the history counter to zero, 4342758f92a0SBarry Smith else it continues storing new values for new nonlinear solves after the old ones 4343c7afd0dbSLois Curfman McInnes 4344dc4c0fb0SBarry Smith Level: intermediate 4345dc4c0fb0SBarry Smith 4346308dcc3eSBarry Smith Notes: 4347dc4c0fb0SBarry Smith If 'a' and 'its' are `NULL` then space is allocated for the history. If 'na' `PETSC_DECIDE` or `PETSC_DEFAULT` then a 4348308dcc3eSBarry Smith default array of length 10000 is allocated. 4349308dcc3eSBarry Smith 4350c9005455SLois Curfman McInnes This routine is useful, e.g., when running a code for purposes 4351c9005455SLois Curfman McInnes of accurate performance monitoring, when no I/O should be done 4352c9005455SLois Curfman McInnes during the section of code that is being timed. 4353c9005455SLois Curfman McInnes 4354420bcc1bSBarry Smith If the arrays run out of space after a number of iterations then the later values are not saved in the history 4355420bcc1bSBarry Smith 43561cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetConvergenceHistory()` 4357c9005455SLois Curfman McInnes @*/ 4358d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceHistory(SNES snes, PetscReal a[], PetscInt its[], PetscInt na, PetscBool reset) 4359d71ae5a4SJacob Faibussowitsch { 43603a40ed3dSBarry Smith PetscFunctionBegin; 43610700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 43624f572ea9SToby Isaac if (a) PetscAssertPointer(a, 2); 43634f572ea9SToby Isaac if (its) PetscAssertPointer(its, 3); 43647a1ec6d4SBarry Smith if (!a) { 4365308dcc3eSBarry Smith if (na == PETSC_DECIDE || na == PETSC_DEFAULT) na = 1000; 43669566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(na, &a, na, &its)); 4367071fcb05SBarry Smith snes->conv_hist_alloc = PETSC_TRUE; 4368308dcc3eSBarry Smith } 4369c9005455SLois Curfman McInnes snes->conv_hist = a; 4370758f92a0SBarry Smith snes->conv_hist_its = its; 4371115dd874SBarry Smith snes->conv_hist_max = (size_t)na; 4372a12bc48fSLisandro Dalcin snes->conv_hist_len = 0; 4373758f92a0SBarry Smith snes->conv_hist_reset = reset; 43743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4375758f92a0SBarry Smith } 4376758f92a0SBarry Smith 4377d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB) 4378c6db04a5SJed Brown #include <engine.h> /* MATLAB include file */ 4379c6db04a5SJed Brown #include <mex.h> /* MATLAB include file */ 438099e0435eSBarry Smith 4381d71ae5a4SJacob Faibussowitsch PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes) 4382d71ae5a4SJacob Faibussowitsch { 4383308dcc3eSBarry Smith mxArray *mat; 4384308dcc3eSBarry Smith PetscInt i; 4385308dcc3eSBarry Smith PetscReal *ar; 4386308dcc3eSBarry Smith 4387308dcc3eSBarry Smith mat = mxCreateDoubleMatrix(snes->conv_hist_len, 1, mxREAL); 4388308dcc3eSBarry Smith ar = (PetscReal *)mxGetData(mat); 4389f5af7f23SKarl Rupp for (i = 0; i < snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i]; 439011cc89d2SBarry Smith return mat; 4391308dcc3eSBarry Smith } 4392308dcc3eSBarry Smith #endif 4393308dcc3eSBarry Smith 43940c4c9dddSBarry Smith /*@C 4395420bcc1bSBarry Smith SNESGetConvergenceHistory - Gets the arrays used to hold the convergence history. 4396758f92a0SBarry Smith 43973f9fe445SBarry Smith Not Collective 4398758f92a0SBarry Smith 4399758f92a0SBarry Smith Input Parameter: 4400f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 4401758f92a0SBarry Smith 4402758f92a0SBarry Smith Output Parameters: 4403f6dfbefdSBarry Smith + a - array to hold history, usually was set with `SNESSetConvergenceHistory()` 4404758f92a0SBarry Smith . its - integer array holds the number of linear iterations (or 4405758f92a0SBarry Smith negative if not converged) for each solve. 440620f4b53cSBarry Smith - na - size of `a` and `its` 4407758f92a0SBarry Smith 4408dc4c0fb0SBarry Smith Level: intermediate 4409dc4c0fb0SBarry Smith 441020f4b53cSBarry Smith Note: 441120f4b53cSBarry Smith This routine is useful, e.g., when running a code for purposes 441220f4b53cSBarry Smith of accurate performance monitoring, when no I/O should be done 441320f4b53cSBarry Smith during the section of code that is being timed. 441420f4b53cSBarry Smith 4415420bcc1bSBarry Smith Fortran Note: 4416758f92a0SBarry Smith The calling sequence for this routine in Fortran is 4417dc4c0fb0SBarry Smith .vb 4418dc4c0fb0SBarry Smith call SNESGetConvergenceHistory(SNES snes, integer na, integer ierr) 4419dc4c0fb0SBarry Smith .ve 4420758f92a0SBarry Smith 44211cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceHistory()` 4422758f92a0SBarry Smith @*/ 4423d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergenceHistory(SNES snes, PetscReal *a[], PetscInt *its[], PetscInt *na) 4424d71ae5a4SJacob Faibussowitsch { 4425758f92a0SBarry Smith PetscFunctionBegin; 44260700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4427758f92a0SBarry Smith if (a) *a = snes->conv_hist; 4428758f92a0SBarry Smith if (its) *its = snes->conv_hist_its; 4429115dd874SBarry Smith if (na) *na = (PetscInt)snes->conv_hist_len; 44303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4431c9005455SLois Curfman McInnes } 4432c9005455SLois Curfman McInnes 4433ac226902SBarry Smith /*@C 443476b2cf59SMatthew Knepley SNESSetUpdate - Sets the general-purpose update function called 4435eec8f646SJed Brown at the beginning of every iteration of the nonlinear solve. Specifically 44367e4bb74cSBarry Smith it is called just before the Jacobian is "evaluated". 443776b2cf59SMatthew Knepley 4438c3339decSBarry Smith Logically Collective 443976b2cf59SMatthew Knepley 444076b2cf59SMatthew Knepley Input Parameters: 4441a2b725a8SWilliam Gropp + snes - The nonlinear solver context 4442a2b725a8SWilliam Gropp - func - The function 444376b2cf59SMatthew Knepley 444420f4b53cSBarry Smith Calling sequence of `func`: 444520f4b53cSBarry Smith + snes - the nonlinear solver context 444620f4b53cSBarry Smith - step - The current step of the iteration 444776b2cf59SMatthew Knepley 4448fe97e370SBarry Smith Level: advanced 4449fe97e370SBarry Smith 4450420bcc1bSBarry Smith Notes: 4451f6dfbefdSBarry 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 4452f6dfbefdSBarry Smith to `SNESSetFunction()`, or `SNESSetPicard()` 4453fe97e370SBarry Smith This is not used by most users. 445476b2cf59SMatthew Knepley 4455aaa8cc7dSPierre 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. 44566b7fb656SBarry Smith 4457e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetJacobian()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRSetPostCheck()`, 4458db781477SPatrick Sanan `SNESMonitorSet()`, `SNESSetDivergenceTest()` 445976b2cf59SMatthew Knepley @*/ 44600b4db180SJacob Faibussowitsch PetscErrorCode SNESSetUpdate(SNES snes, PetscErrorCode (*func)(SNES snes, PetscInt step)) 4461d71ae5a4SJacob Faibussowitsch { 446276b2cf59SMatthew Knepley PetscFunctionBegin; 44630700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4464e7788613SBarry Smith snes->ops->update = func; 44653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 446676b2cf59SMatthew Knepley } 446776b2cf59SMatthew Knepley 446891f3e32bSBarry Smith /*@C 4469f6dfbefdSBarry Smith SNESConvergedReasonView - Displays the reason a `SNES` solve converged or diverged to a viewer 44702a359c20SBarry Smith 4471c3339decSBarry Smith Collective 44722a359c20SBarry Smith 4473e4094ef1SJacob Faibussowitsch Input Parameters: 4474f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 44752a359c20SBarry Smith - viewer - the viewer to display the reason 44762a359c20SBarry Smith 44772a359c20SBarry Smith Options Database Keys: 4478ee300463SSatish Balay + -snes_converged_reason - print reason for converged or diverged, also prints number of iterations 4479ee300463SSatish Balay - -snes_converged_reason ::failed - only print reason and number of iterations when diverged 4480eafd5ff0SAlex Lindsay 4481420bcc1bSBarry Smith Level: beginner 4482420bcc1bSBarry Smith 4483f6dfbefdSBarry Smith Note: 4484f6dfbefdSBarry Smith To change the format of the output call `PetscViewerPushFormat`(viewer,format) before this call. Use `PETSC_VIEWER_DEFAULT` for the default, 4485f6dfbefdSBarry Smith use `PETSC_VIEWER_FAILED` to only display a reason if it fails. 44862a359c20SBarry Smith 44871cc06b55SBarry Smith .seealso: [](ch_snes), `SNESConvergedReason`, `PetscViewer`, `SNES`, 4488f6dfbefdSBarry Smith `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, 4489f6dfbefdSBarry Smith `SNESConvergedReasonViewFromOptions()`, 4490db781477SPatrick Sanan `PetscViewerPushFormat()`, `PetscViewerPopFormat()` 44912a359c20SBarry Smith @*/ 4492d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonView(SNES snes, PetscViewer viewer) 4493d71ae5a4SJacob Faibussowitsch { 449475cca76cSMatthew G. Knepley PetscViewerFormat format; 44952a359c20SBarry Smith PetscBool isAscii; 44962a359c20SBarry Smith 44972a359c20SBarry Smith PetscFunctionBegin; 449819a666eeSBarry Smith if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)); 44999566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii)); 45002a359c20SBarry Smith if (isAscii) { 45019566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 45029566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel)); 450375cca76cSMatthew G. Knepley if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 450475cca76cSMatthew G. Knepley DM dm; 450575cca76cSMatthew G. Knepley Vec u; 450675cca76cSMatthew G. Knepley PetscDS prob; 450775cca76cSMatthew G. Knepley PetscInt Nf, f; 450895cbbfd3SMatthew G. Knepley PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *); 450995cbbfd3SMatthew G. Knepley void **exactCtx; 451075cca76cSMatthew G. Knepley PetscReal error; 451175cca76cSMatthew G. Knepley 45129566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 45139566063dSJacob Faibussowitsch PetscCall(SNESGetSolution(snes, &u)); 45149566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob)); 45159566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(prob, &Nf)); 45169566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(Nf, &exactSol, Nf, &exactCtx)); 45179566063dSJacob Faibussowitsch for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f])); 45189566063dSJacob Faibussowitsch PetscCall(DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error)); 45199566063dSJacob Faibussowitsch PetscCall(PetscFree2(exactSol, exactCtx)); 45209566063dSJacob Faibussowitsch if (error < 1.0e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n")); 452163a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", (double)error)); 452275cca76cSMatthew G. Knepley } 4523eafd5ff0SAlex Lindsay if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) { 45242a359c20SBarry Smith if (((PetscObject)snes)->prefix) { 452563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter)); 45262a359c20SBarry Smith } else { 452763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve converged due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter)); 45282a359c20SBarry Smith } 4529eafd5ff0SAlex Lindsay } else if (snes->reason <= 0) { 45302a359c20SBarry Smith if (((PetscObject)snes)->prefix) { 453163a3b9bcSJacob 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)); 45322a359c20SBarry Smith } else { 453363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve did not converge due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter)); 45342a359c20SBarry Smith } 45352a359c20SBarry Smith } 45369566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel)); 45372a359c20SBarry Smith } 45383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 45392a359c20SBarry Smith } 45402a359c20SBarry Smith 4541c4421ceaSFande Kong /*@C 4542c4421ceaSFande Kong SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the 4543aaa8cc7dSPierre Jolivet end of the nonlinear solver to display the convergence reason of the nonlinear solver. 4544c4421ceaSFande Kong 4545c3339decSBarry Smith Logically Collective 4546c4421ceaSFande Kong 4547c4421ceaSFande Kong Input Parameters: 4548f6dfbefdSBarry Smith + snes - the `SNES` context 4549420bcc1bSBarry Smith . f - the `SNESConvergedReason` view function 4550420bcc1bSBarry Smith . vctx - [optional] user-defined context for private data for the `SNESConvergedReason` view function (use `NULL` if no context is desired) 4551420bcc1bSBarry Smith - reasonviewdestroy - [optional] routine that frees the context (may be `NULL`) 4552420bcc1bSBarry Smith 4553420bcc1bSBarry Smith Calling sequence of `f`: 4554420bcc1bSBarry Smith + snes - the `SNES` context 4555420bcc1bSBarry Smith - vctx - [optional] user-defined context for private data for the function 4556420bcc1bSBarry Smith 4557420bcc1bSBarry Smith Calling sequence of `reasonviewerdestroy`: 4558420bcc1bSBarry Smith . vctx - [optional] user-defined context for private data for the function 4559c4421ceaSFande Kong 4560c4421ceaSFande Kong Options Database Keys: 4561f6dfbefdSBarry Smith + -snes_converged_reason - sets a default `SNESConvergedReasonView()` 4562420bcc1bSBarry Smith - -snes_converged_reason_view_cancel - cancels all converged reason viewers that have been hardwired into a code by 4563420bcc1bSBarry Smith calls to `SNESConvergedReasonViewSet()`, but does not cancel those set via the options database. 4564c4421ceaSFande Kong 4565dc4c0fb0SBarry Smith Level: intermediate 4566dc4c0fb0SBarry Smith 4567f6dfbefdSBarry Smith Note: 4568c4421ceaSFande Kong Several different converged reason view routines may be set by calling 4569f6dfbefdSBarry Smith `SNESConvergedReasonViewSet()` multiple times; all will be called in the 4570c4421ceaSFande Kong order in which they were set. 4571c4421ceaSFande Kong 45721cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`, `SNESConvergedReasonViewCancel()` 4573c4421ceaSFande Kong @*/ 4574420bcc1bSBarry Smith PetscErrorCode SNESConvergedReasonViewSet(SNES snes, PetscErrorCode (*f)(SNES snes, void *vctx), void *vctx, PetscErrorCode (*reasonviewdestroy)(void **vctx)) 4575d71ae5a4SJacob Faibussowitsch { 4576c4421ceaSFande Kong PetscInt i; 4577c4421ceaSFande Kong PetscBool identical; 4578c4421ceaSFande Kong 4579c4421ceaSFande Kong PetscFunctionBegin; 4580c4421ceaSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4581c4421ceaSFande Kong for (i = 0; i < snes->numberreasonviews; i++) { 45829566063dSJacob Faibussowitsch PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, vctx, reasonviewdestroy, (PetscErrorCode(*)(void))snes->reasonview[i], snes->reasonviewcontext[i], snes->reasonviewdestroy[i], &identical)); 45833ba16761SJacob Faibussowitsch if (identical) PetscFunctionReturn(PETSC_SUCCESS); 4584c4421ceaSFande Kong } 45855f80ce2aSJacob Faibussowitsch PetscCheck(snes->numberreasonviews < MAXSNESREASONVIEWS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many SNES reasonview set"); 4586c4421ceaSFande Kong snes->reasonview[snes->numberreasonviews] = f; 4587c4421ceaSFande Kong snes->reasonviewdestroy[snes->numberreasonviews] = reasonviewdestroy; 4588c4421ceaSFande Kong snes->reasonviewcontext[snes->numberreasonviews++] = (void *)vctx; 45893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4590c4421ceaSFande Kong } 4591c4421ceaSFande Kong 459291f3e32bSBarry Smith /*@ 4593420bcc1bSBarry Smith SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a `SNESConvergedReason` is to be viewed at the end of `SNESSolve()` 4594c4421ceaSFande Kong All the user-provided convergedReasonView routines will be involved as well, if they exist. 45952a359c20SBarry Smith 4596c3339decSBarry Smith Collective 45972a359c20SBarry Smith 45982fe279fdSBarry Smith Input Parameter: 4599f6dfbefdSBarry Smith . snes - the `SNES` object 46002a359c20SBarry Smith 4601f6dfbefdSBarry Smith Level: advanced 46022a359c20SBarry Smith 46031cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESConvergedReasonViewSet()`, `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, 4604f6dfbefdSBarry Smith `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()` 46052a359c20SBarry Smith @*/ 4606d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes) 4607d71ae5a4SJacob Faibussowitsch { 46082a359c20SBarry Smith PetscViewer viewer; 46092a359c20SBarry Smith PetscBool flg; 46102a359c20SBarry Smith static PetscBool incall = PETSC_FALSE; 46112a359c20SBarry Smith PetscViewerFormat format; 4612c4421ceaSFande Kong PetscInt i; 46132a359c20SBarry Smith 46142a359c20SBarry Smith PetscFunctionBegin; 46153ba16761SJacob Faibussowitsch if (incall) PetscFunctionReturn(PETSC_SUCCESS); 46162a359c20SBarry Smith incall = PETSC_TRUE; 4617c4421ceaSFande Kong 4618c4421ceaSFande Kong /* All user-provided viewers are called first, if they exist. */ 461948a46eb9SPierre Jolivet for (i = 0; i < snes->numberreasonviews; i++) PetscCall((*snes->reasonview[i])(snes, snes->reasonviewcontext[i])); 4620c4421ceaSFande Kong 4621c4421ceaSFande Kong /* Call PETSc default routine if users ask for it */ 46229566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_converged_reason", &viewer, &format, &flg)); 46232a359c20SBarry Smith if (flg) { 46249566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(viewer, format)); 46259566063dSJacob Faibussowitsch PetscCall(SNESConvergedReasonView(snes, viewer)); 46269566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer)); 4627cd791dc2SBarry Smith PetscCall(PetscOptionsRestoreViewer(&viewer)); 46282a359c20SBarry Smith } 46292a359c20SBarry Smith incall = PETSC_FALSE; 46303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 46312a359c20SBarry Smith } 46322a359c20SBarry Smith 4633487a658cSBarry Smith /*@ 4634f69a0ea3SMatthew Knepley SNESSolve - Solves a nonlinear system F(x) = b. 46359b94acceSBarry Smith 4636c3339decSBarry Smith Collective 4637c7afd0dbSLois Curfman McInnes 4638b2002411SLois Curfman McInnes Input Parameters: 4639f6dfbefdSBarry Smith + snes - the `SNES` context 4640dc4c0fb0SBarry Smith . b - the constant part of the equation F(x) = b, or `NULL` to use zero. 464185385478SLisandro Dalcin - x - the solution vector. 46429b94acceSBarry Smith 4643dc4c0fb0SBarry Smith Level: beginner 4644dc4c0fb0SBarry Smith 4645f6dfbefdSBarry Smith Note: 4646420bcc1bSBarry Smith The user should initialize the vector, `x`, with the initial guess 4647420bcc1bSBarry Smith for the nonlinear solve prior to calling `SNESSolve()` or use `SNESSetInitialSolution()`. In particular, 46488ddd3da0SLois Curfman McInnes to employ an initial guess of zero, the user should explicitly set 4649f6dfbefdSBarry Smith this vector to zero by calling `VecSet()`. 46508ddd3da0SLois Curfman McInnes 46511cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESSetFunction()`, `SNESSetJacobian()`, `SNESSetGridSequence()`, `SNESGetSolution()`, 4652db781477SPatrick Sanan `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRGetPreCheck()`, `SNESNewtonTRSetPostCheck()`, `SNESNewtonTRGetPostCheck()`, 4653420bcc1bSBarry Smith `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`, `SNESSetInitialSolution()` 46549b94acceSBarry Smith @*/ 4655d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSolve(SNES snes, Vec b, Vec x) 4656d71ae5a4SJacob Faibussowitsch { 4657ace3abfcSBarry Smith PetscBool flg; 4658efd51863SBarry Smith PetscInt grid; 46590298fd71SBarry Smith Vec xcreated = NULL; 4660caa4e7f2SJed Brown DM dm; 4661052efed2SBarry Smith 46623a40ed3dSBarry Smith PetscFunctionBegin; 46630700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4664a69afd8bSBarry Smith if (x) PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4665a69afd8bSBarry Smith if (x) PetscCheckSameComm(snes, 1, x, 3); 46660700a824SBarry Smith if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 466785385478SLisandro Dalcin if (b) PetscCheckSameComm(snes, 1, b, 2); 466885385478SLisandro Dalcin 466934b4d3a8SMatthew G. Knepley /* High level operations using the nonlinear solver */ 467006fc46c8SMatthew G. Knepley { 467106fc46c8SMatthew G. Knepley PetscViewer viewer; 467206fc46c8SMatthew G. Knepley PetscViewerFormat format; 46737c88af5aSMatthew G. Knepley PetscInt num; 467406fc46c8SMatthew G. Knepley PetscBool flg; 467506fc46c8SMatthew G. Knepley static PetscBool incall = PETSC_FALSE; 467606fc46c8SMatthew G. Knepley 467706fc46c8SMatthew G. Knepley if (!incall) { 467834b4d3a8SMatthew G. Knepley /* Estimate the convergence rate of the discretization */ 46799566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg)); 468006fc46c8SMatthew G. Knepley if (flg) { 468106fc46c8SMatthew G. Knepley PetscConvEst conv; 468246079b62SMatthew G. Knepley DM dm; 468346079b62SMatthew G. Knepley PetscReal *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */ 468446079b62SMatthew G. Knepley PetscInt Nf; 468506fc46c8SMatthew G. Knepley 468606fc46c8SMatthew G. Knepley incall = PETSC_TRUE; 46879566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 46889566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 46899566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(Nf, &alpha)); 46909566063dSJacob Faibussowitsch PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)snes), &conv)); 46919566063dSJacob Faibussowitsch PetscCall(PetscConvEstSetSolver(conv, (PetscObject)snes)); 46929566063dSJacob Faibussowitsch PetscCall(PetscConvEstSetFromOptions(conv)); 46939566063dSJacob Faibussowitsch PetscCall(PetscConvEstSetUp(conv)); 46949566063dSJacob Faibussowitsch PetscCall(PetscConvEstGetConvRate(conv, alpha)); 46959566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(viewer, format)); 46969566063dSJacob Faibussowitsch PetscCall(PetscConvEstRateView(conv, alpha, viewer)); 46979566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer)); 4698cd791dc2SBarry Smith PetscCall(PetscOptionsRestoreViewer(&viewer)); 46999566063dSJacob Faibussowitsch PetscCall(PetscConvEstDestroy(&conv)); 47009566063dSJacob Faibussowitsch PetscCall(PetscFree(alpha)); 470106fc46c8SMatthew G. Knepley incall = PETSC_FALSE; 470206fc46c8SMatthew G. Knepley } 470334b4d3a8SMatthew G. Knepley /* Adaptively refine the initial grid */ 4704b2588ea6SMatthew G. Knepley num = 1; 47059566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_initial", &num, &flg)); 470634b4d3a8SMatthew G. Knepley if (flg) { 470734b4d3a8SMatthew G. Knepley DMAdaptor adaptor; 470834b4d3a8SMatthew G. Knepley 470934b4d3a8SMatthew G. Knepley incall = PETSC_TRUE; 47109566063dSJacob Faibussowitsch PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor)); 47119566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSolver(adaptor, snes)); 47129566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSequenceLength(adaptor, num)); 47139566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetFromOptions(adaptor)); 47149566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetUp(adaptor)); 47159566063dSJacob Faibussowitsch PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x)); 47169566063dSJacob Faibussowitsch PetscCall(DMAdaptorDestroy(&adaptor)); 471734b4d3a8SMatthew G. Knepley incall = PETSC_FALSE; 471834b4d3a8SMatthew G. Knepley } 47197c88af5aSMatthew G. Knepley /* Use grid sequencing to adapt */ 47207c88af5aSMatthew G. Knepley num = 0; 47219566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_sequence", &num, NULL)); 47227c88af5aSMatthew G. Knepley if (num) { 47237c88af5aSMatthew G. Knepley DMAdaptor adaptor; 47247c88af5aSMatthew G. Knepley 47257c88af5aSMatthew G. Knepley incall = PETSC_TRUE; 47269566063dSJacob Faibussowitsch PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor)); 47279566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSolver(adaptor, snes)); 47289566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSequenceLength(adaptor, num)); 47299566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetFromOptions(adaptor)); 47309566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetUp(adaptor)); 47319566063dSJacob Faibussowitsch PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x)); 47329566063dSJacob Faibussowitsch PetscCall(DMAdaptorDestroy(&adaptor)); 47337c88af5aSMatthew G. Knepley incall = PETSC_FALSE; 47347c88af5aSMatthew G. Knepley } 473506fc46c8SMatthew G. Knepley } 473606fc46c8SMatthew G. Knepley } 4737ad540459SPierre Jolivet if (!x) x = snes->vec_sol; 4738caa4e7f2SJed Brown if (!x) { 47399566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 47409566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dm, &xcreated)); 4741a69afd8bSBarry Smith x = xcreated; 4742a69afd8bSBarry Smith } 47439566063dSJacob Faibussowitsch PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view_pre")); 4744f05ece33SBarry Smith 47459566063dSJacob Faibussowitsch for (grid = 0; grid < snes->gridsequence; grid++) PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)))); 4746efd51863SBarry Smith for (grid = 0; grid < snes->gridsequence + 1; grid++) { 474785385478SLisandro Dalcin /* set solution vector */ 47489566063dSJacob Faibussowitsch if (!grid) PetscCall(PetscObjectReference((PetscObject)x)); 47499566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol)); 475085385478SLisandro Dalcin snes->vec_sol = x; 47519566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 4752caa4e7f2SJed Brown 4753caa4e7f2SJed Brown /* set affine vector if provided */ 47549566063dSJacob Faibussowitsch if (b) PetscCall(PetscObjectReference((PetscObject)b)); 47559566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_rhs)); 475685385478SLisandro Dalcin snes->vec_rhs = b; 475785385478SLisandro Dalcin 47585f80ce2aSJacob 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"); 47595f80ce2aSJacob Faibussowitsch PetscCheck(snes->vec_func != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be function vector"); 47605f80ce2aSJacob Faibussowitsch PetscCheck(snes->vec_rhs != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be right hand side vector"); 4761aa624791SPierre Jolivet if (!snes->vec_sol_update /* && snes->vec_sol */) PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_sol_update)); 47629566063dSJacob Faibussowitsch PetscCall(DMShellSetGlobalVector(dm, snes->vec_sol)); 47639566063dSJacob Faibussowitsch PetscCall(SNESSetUp(snes)); 47643f149594SLisandro Dalcin 47657eee914bSBarry Smith if (!grid) { 476625e27a38SBarry Smith if (snes->ops->computeinitialguess) PetscCallBack("SNES callback initial guess", (*snes->ops->computeinitialguess)(snes, snes->vec_sol, snes->initialguessP)); 4767dd568438SSatish Balay } 4768d25893d9SBarry Smith 4769abc0a331SBarry Smith if (snes->conv_hist_reset) snes->conv_hist_len = 0; 47709371c9d4SSatish Balay if (snes->counters_reset) { 47719371c9d4SSatish Balay snes->nfuncs = 0; 47729371c9d4SSatish Balay snes->linear_its = 0; 47739371c9d4SSatish Balay snes->numFailures = 0; 47749371c9d4SSatish Balay } 4775d5e45103SBarry Smith 47762d157150SStefano Zampini snes->reason = SNES_CONVERGED_ITERATING; 47779566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_Solve, snes, 0, 0, 0)); 4778dbbe0bcdSBarry Smith PetscUseTypeMethod(snes, solve); 47799566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_Solve, snes, 0, 0, 0)); 47802d157150SStefano Zampini PetscCheck(snes->reason, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error, solver %s returned without setting converged reason", ((PetscObject)snes)->type_name); 4781422a814eSBarry Smith snes->domainerror = PETSC_FALSE; /* clear the flag if it has been set */ 47823f149594SLisandro Dalcin 478337ec4e1aSPeter Brune if (snes->lagjac_persist) snes->jac_iter += snes->iter; 478437ec4e1aSPeter Brune if (snes->lagpre_persist) snes->pre_iter += snes->iter; 478537ec4e1aSPeter Brune 47869566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_test_local_min", NULL, NULL, &flg)); 47879566063dSJacob Faibussowitsch if (flg && !PetscPreLoadingOn) PetscCall(SNESTestLocalMin(snes)); 4788c4421ceaSFande Kong /* Call converged reason views. This may involve user-provided viewers as well */ 47899566063dSJacob Faibussowitsch PetscCall(SNESConvergedReasonViewFromOptions(snes)); 47905968eb51SBarry Smith 47915f80ce2aSJacob Faibussowitsch if (snes->errorifnotconverged) PetscCheck(snes->reason >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_NOT_CONVERGED, "SNESSolve has not converged"); 47929c8e83a9SBarry Smith if (snes->reason < 0) break; 4793efd51863SBarry Smith if (grid < snes->gridsequence) { 4794efd51863SBarry Smith DM fine; 4795efd51863SBarry Smith Vec xnew; 4796efd51863SBarry Smith Mat interp; 4797efd51863SBarry Smith 47989566063dSJacob Faibussowitsch PetscCall(DMRefine(snes->dm, PetscObjectComm((PetscObject)snes), &fine)); 47995f80ce2aSJacob Faibussowitsch PetscCheck(fine, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_INCOMP, "DMRefine() did not perform any refinement, cannot continue grid sequencing"); 48009566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(snes->dm, fine, &interp, NULL)); 48019566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(fine, &xnew)); 48029566063dSJacob Faibussowitsch PetscCall(MatInterpolate(interp, x, xnew)); 48039566063dSJacob Faibussowitsch PetscCall(DMInterpolate(snes->dm, interp, fine)); 48049566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interp)); 4805efd51863SBarry Smith x = xnew; 4806efd51863SBarry Smith 48079566063dSJacob Faibussowitsch PetscCall(SNESReset(snes)); 48089566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes, fine)); 48099566063dSJacob Faibussowitsch PetscCall(SNESResetFromOptions(snes)); 48109566063dSJacob Faibussowitsch PetscCall(DMDestroy(&fine)); 48119566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)))); 4812efd51863SBarry Smith } 4813efd51863SBarry Smith } 48149566063dSJacob Faibussowitsch PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view")); 48159566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(snes->vec_sol, (PetscObject)snes, "-snes_view_solution")); 48169566063dSJacob Faibussowitsch PetscCall(DMMonitor(snes->dm)); 48179566063dSJacob Faibussowitsch PetscCall(SNESMonitorPauseFinal_Internal(snes)); 48183f7e2da0SPeter Brune 48199566063dSJacob Faibussowitsch PetscCall(VecDestroy(&xcreated)); 48209566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsBlock((PetscObject)snes)); 48213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 48229b94acceSBarry Smith } 48239b94acceSBarry Smith 48249b94acceSBarry Smith /* --------- Internal routines for SNES Package --------- */ 48259b94acceSBarry Smith 482682bf6240SBarry Smith /*@C 48274b0e389bSBarry Smith SNESSetType - Sets the method for the nonlinear solver. 48289b94acceSBarry Smith 4829c3339decSBarry Smith Collective 4830fee21e36SBarry Smith 4831c7afd0dbSLois Curfman McInnes Input Parameters: 4832f6dfbefdSBarry Smith + snes - the `SNES` context 4833454a90a3SBarry Smith - type - a known method 4834c7afd0dbSLois Curfman McInnes 4835c7afd0dbSLois Curfman McInnes Options Database Key: 4836454a90a3SBarry Smith . -snes_type <type> - Sets the method; use -help for a list 483704d7464bSBarry Smith of available methods (for instance, newtonls or newtontr) 4838ae12b187SLois Curfman McInnes 4839dc4c0fb0SBarry Smith Level: intermediate 4840dc4c0fb0SBarry Smith 48419b94acceSBarry Smith Notes: 4842e090d566SSatish Balay See "petsc/include/petscsnes.h" for available methods (for instance) 4843f6dfbefdSBarry Smith + `SNESNEWTONLS` - Newton's method with line search 4844c7afd0dbSLois Curfman McInnes (systems of nonlinear equations) 48454a221d59SStefano Zampini - `SNESNEWTONTR` - Newton's method with trust region 4846c7afd0dbSLois Curfman McInnes (systems of nonlinear equations) 48479b94acceSBarry Smith 4848f6dfbefdSBarry Smith Normally, it is best to use the `SNESSetFromOptions()` command and then 4849f6dfbefdSBarry Smith set the `SNES` solver type from the options database rather than by using 4850ae12b187SLois Curfman McInnes this routine. Using the options database provides the user with 4851ae12b187SLois Curfman McInnes maximum flexibility in evaluating the many nonlinear solvers. 4852f6dfbefdSBarry Smith The `SNESSetType()` routine is provided for those situations where it 4853ae12b187SLois Curfman McInnes is necessary to set the nonlinear solver independently of the command 4854ae12b187SLois Curfman McInnes line or options database. This might be the case, for example, when 4855ae12b187SLois Curfman McInnes the choice of solver changes during the execution of the program, 4856ae12b187SLois Curfman McInnes and the user's application is taking responsibility for choosing the 4857b0a32e0cSBarry Smith appropriate method. 485836851e7fSLois Curfman McInnes 4859420bcc1bSBarry Smith Developer Note: 4860f6dfbefdSBarry Smith `SNESRegister()` adds a constructor for a new `SNESType` to `SNESList`, `SNESSetType()` locates 4861f6dfbefdSBarry Smith the constructor in that list and calls it to create the specific object. 48628f6c3df8SBarry Smith 48631cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESType`, `SNESCreate()`, `SNESDestroy()`, `SNESGetType()`, `SNESSetFromOptions()` 48649b94acceSBarry Smith @*/ 4865d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetType(SNES snes, SNESType type) 4866d71ae5a4SJacob Faibussowitsch { 4867ace3abfcSBarry Smith PetscBool match; 48685f80ce2aSJacob Faibussowitsch PetscErrorCode (*r)(SNES); 48693a40ed3dSBarry Smith 48703a40ed3dSBarry Smith PetscFunctionBegin; 48710700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 48724f572ea9SToby Isaac PetscAssertPointer(type, 2); 487382bf6240SBarry Smith 48749566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes, type, &match)); 48753ba16761SJacob Faibussowitsch if (match) PetscFunctionReturn(PETSC_SUCCESS); 487692ff6ae8SBarry Smith 48779566063dSJacob Faibussowitsch PetscCall(PetscFunctionListFind(SNESList, type, &r)); 48786adde796SStefano Zampini PetscCheck(r, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested SNES type %s", type); 487975396ef9SLisandro Dalcin /* Destroy the previous private SNES context */ 4880dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, destroy); 488175396ef9SLisandro Dalcin /* Reinitialize function pointers in SNESOps structure */ 48829e5d0892SLisandro Dalcin snes->ops->setup = NULL; 48839e5d0892SLisandro Dalcin snes->ops->solve = NULL; 48849e5d0892SLisandro Dalcin snes->ops->view = NULL; 48859e5d0892SLisandro Dalcin snes->ops->setfromoptions = NULL; 48869e5d0892SLisandro Dalcin snes->ops->destroy = NULL; 48877fe760d5SStefano Zampini 48887fe760d5SStefano Zampini /* It may happen the user has customized the line search before calling SNESSetType */ 48899566063dSJacob Faibussowitsch if (((PetscObject)snes)->type_name) PetscCall(SNESLineSearchDestroy(&snes->linesearch)); 48907fe760d5SStefano Zampini 489175396ef9SLisandro Dalcin /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */ 489275396ef9SLisandro Dalcin snes->setupcalled = PETSC_FALSE; 4893f5af7f23SKarl Rupp 48949566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)snes, type)); 48959566063dSJacob Faibussowitsch PetscCall((*r)(snes)); 48963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 48979b94acceSBarry Smith } 48989b94acceSBarry Smith 48999b94acceSBarry Smith /*@C 4900f6dfbefdSBarry Smith SNESGetType - Gets the `SNES` method type and name (as a string). 49019b94acceSBarry Smith 4902c7afd0dbSLois Curfman McInnes Not Collective 4903c7afd0dbSLois Curfman McInnes 49049b94acceSBarry Smith Input Parameter: 49054b0e389bSBarry Smith . snes - nonlinear solver context 49069b94acceSBarry Smith 49079b94acceSBarry Smith Output Parameter: 4908f6dfbefdSBarry Smith . type - `SNES` method (a character string) 49099b94acceSBarry Smith 491036851e7fSLois Curfman McInnes Level: intermediate 491136851e7fSLois Curfman McInnes 49121cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetType()`, `SNESType`, `SNESSetFromOptions()`, `SNES` 49139b94acceSBarry Smith @*/ 4914d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetType(SNES snes, SNESType *type) 4915d71ae5a4SJacob Faibussowitsch { 49163a40ed3dSBarry Smith PetscFunctionBegin; 49170700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 49184f572ea9SToby Isaac PetscAssertPointer(type, 2); 49197adad957SLisandro Dalcin *type = ((PetscObject)snes)->type_name; 49203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49219b94acceSBarry Smith } 49229b94acceSBarry Smith 49233cd8a7caSMatthew G. Knepley /*@ 4924f6dfbefdSBarry Smith SNESSetSolution - Sets the solution vector for use by the `SNES` routines. 49253cd8a7caSMatthew G. Knepley 4926c3339decSBarry Smith Logically Collective 49273cd8a7caSMatthew G. Knepley 49283cd8a7caSMatthew G. Knepley Input Parameters: 4929f6dfbefdSBarry Smith + snes - the `SNES` context obtained from `SNESCreate()` 49303cd8a7caSMatthew G. Knepley - u - the solution vector 49313cd8a7caSMatthew G. Knepley 49323cd8a7caSMatthew G. Knepley Level: beginner 49333cd8a7caSMatthew G. Knepley 49341cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetSolution()`, `Vec` 49353cd8a7caSMatthew G. Knepley @*/ 4936d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetSolution(SNES snes, Vec u) 4937d71ae5a4SJacob Faibussowitsch { 49383cd8a7caSMatthew G. Knepley DM dm; 49393cd8a7caSMatthew G. Knepley 49403cd8a7caSMatthew G. Knepley PetscFunctionBegin; 49413cd8a7caSMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 49423cd8a7caSMatthew G. Knepley PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 49439566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)u)); 49449566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol)); 49453cd8a7caSMatthew G. Knepley 49463cd8a7caSMatthew G. Knepley snes->vec_sol = u; 49473cd8a7caSMatthew G. Knepley 49489566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 49499566063dSJacob Faibussowitsch PetscCall(DMShellSetGlobalVector(dm, u)); 49503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49513cd8a7caSMatthew G. Knepley } 49523cd8a7caSMatthew G. Knepley 495352baeb72SSatish Balay /*@ 49549b94acceSBarry Smith SNESGetSolution - Returns the vector where the approximate solution is 4955f6dfbefdSBarry Smith stored. This is the fine grid solution when using `SNESSetGridSequence()`. 49569b94acceSBarry Smith 4957420bcc1bSBarry Smith Not Collective, but `x` is parallel if `snes` is parallel 4958c7afd0dbSLois Curfman McInnes 49599b94acceSBarry Smith Input Parameter: 4960f6dfbefdSBarry Smith . snes - the `SNES` context 49619b94acceSBarry Smith 49629b94acceSBarry Smith Output Parameter: 49639b94acceSBarry Smith . x - the solution 49649b94acceSBarry Smith 496570e92668SMatthew Knepley Level: intermediate 496636851e7fSLois Curfman McInnes 49671cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetSolution()`, `SNESSolve()`, `SNES`, `SNESGetSolutionUpdate()`, `SNESGetFunction()` 49689b94acceSBarry Smith @*/ 4969d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolution(SNES snes, Vec *x) 4970d71ae5a4SJacob Faibussowitsch { 49713a40ed3dSBarry Smith PetscFunctionBegin; 49720700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 49734f572ea9SToby Isaac PetscAssertPointer(x, 2); 497485385478SLisandro Dalcin *x = snes->vec_sol; 49753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 497670e92668SMatthew Knepley } 497770e92668SMatthew Knepley 497852baeb72SSatish Balay /*@ 49799b94acceSBarry Smith SNESGetSolutionUpdate - Returns the vector where the solution update is 49809b94acceSBarry Smith stored. 49819b94acceSBarry Smith 4982420bcc1bSBarry Smith Not Collective, but `x` is parallel if `snes` is parallel 4983c7afd0dbSLois Curfman McInnes 49849b94acceSBarry Smith Input Parameter: 4985f6dfbefdSBarry Smith . snes - the `SNES` context 49869b94acceSBarry Smith 49879b94acceSBarry Smith Output Parameter: 49889b94acceSBarry Smith . x - the solution update 49899b94acceSBarry Smith 499036851e7fSLois Curfman McInnes Level: advanced 499136851e7fSLois Curfman McInnes 49921cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()` 49939b94acceSBarry Smith @*/ 4994d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionUpdate(SNES snes, Vec *x) 4995d71ae5a4SJacob Faibussowitsch { 49963a40ed3dSBarry Smith PetscFunctionBegin; 49970700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 49984f572ea9SToby Isaac PetscAssertPointer(x, 2); 499985385478SLisandro Dalcin *x = snes->vec_sol_update; 50003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50019b94acceSBarry Smith } 50029b94acceSBarry Smith 50039b94acceSBarry Smith /*@C 5004f6dfbefdSBarry Smith SNESGetFunction - Returns the function that defines the nonlinear system set with `SNESSetFunction()` 50059b94acceSBarry Smith 5006420bcc1bSBarry Smith Not Collective, but `r` is parallel if `snes` is parallel. Collective if `r` is requested, but has not been created yet. 5007c7afd0dbSLois Curfman McInnes 50089b94acceSBarry Smith Input Parameter: 5009f6dfbefdSBarry Smith . snes - the `SNES` context 50109b94acceSBarry Smith 5011d8d19677SJose E. Roman Output Parameters: 5012dc4c0fb0SBarry Smith + r - the vector that is used to store residuals (or `NULL` if you don't want it) 501320f4b53cSBarry Smith . f - the function (or `NULL` if you don't want it); for calling sequence see `SNESFunction` 5014dc4c0fb0SBarry Smith - ctx - the function context (or `NULL` if you don't want it) 50159b94acceSBarry Smith 501636851e7fSLois Curfman McInnes Level: advanced 501736851e7fSLois Curfman McInnes 5018f6dfbefdSBarry Smith Note: 5019dc4c0fb0SBarry Smith The vector `r` DOES NOT, in general, contain the current value of the `SNES` nonlinear function 502004edfde5SBarry Smith 5021e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetSolution()`, `SNESFunction` 50229b94acceSBarry Smith @*/ 5023d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunction(SNES snes, Vec *r, PetscErrorCode (**f)(SNES, Vec, Vec, void *), void **ctx) 5024d71ae5a4SJacob Faibussowitsch { 50256cab3a1bSJed Brown DM dm; 5026a63bb30eSJed Brown 50273a40ed3dSBarry Smith PetscFunctionBegin; 50280700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5029a63bb30eSJed Brown if (r) { 5030a63bb30eSJed Brown if (!snes->vec_func) { 5031a63bb30eSJed Brown if (snes->vec_rhs) { 50329566063dSJacob Faibussowitsch PetscCall(VecDuplicate(snes->vec_rhs, &snes->vec_func)); 5033a63bb30eSJed Brown } else if (snes->vec_sol) { 50349566063dSJacob Faibussowitsch PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_func)); 5035a63bb30eSJed Brown } else if (snes->dm) { 50369566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(snes->dm, &snes->vec_func)); 5037a63bb30eSJed Brown } 5038a63bb30eSJed Brown } 5039a63bb30eSJed Brown *r = snes->vec_func; 5040a63bb30eSJed Brown } 50419566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 50429566063dSJacob Faibussowitsch PetscCall(DMSNESGetFunction(dm, f, ctx)); 50433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50449b94acceSBarry Smith } 50459b94acceSBarry Smith 5046c79ef259SPeter Brune /*@C 504737fdd005SBarry Smith SNESGetNGS - Returns the function and context set with `SNESSetNGS()` 5048c79ef259SPeter Brune 5049c79ef259SPeter Brune Input Parameter: 5050f6dfbefdSBarry Smith . snes - the `SNES` context 5051c79ef259SPeter Brune 5052d8d19677SJose E. Roman Output Parameters: 505337fdd005SBarry Smith + f - the function (or `NULL`) see `SNESSetNGS()` for details 5054dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`) 5055c79ef259SPeter Brune 5056c79ef259SPeter Brune Level: advanced 5057c79ef259SPeter Brune 50581cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNGS()`, `SNESGetFunction()` 5059c79ef259SPeter Brune @*/ 5060d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNGS(SNES snes, PetscErrorCode (**f)(SNES, Vec, Vec, void *), void **ctx) 5061d71ae5a4SJacob Faibussowitsch { 50626cab3a1bSJed Brown DM dm; 50636cab3a1bSJed Brown 5064646217ecSPeter Brune PetscFunctionBegin; 5065646217ecSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 50669566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 50679566063dSJacob Faibussowitsch PetscCall(DMSNESGetNGS(dm, f, ctx)); 50683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5069646217ecSPeter Brune } 5070646217ecSPeter Brune 50713c7409f5SSatish Balay /*@C 50723c7409f5SSatish Balay SNESSetOptionsPrefix - Sets the prefix used for searching for all 5073f6dfbefdSBarry Smith `SNES` options in the database. 50743c7409f5SSatish Balay 5075c3339decSBarry Smith Logically Collective 5076fee21e36SBarry Smith 5077d8d19677SJose E. Roman Input Parameters: 5078f6dfbefdSBarry Smith + snes - the `SNES` context 5079c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names 5080c7afd0dbSLois Curfman McInnes 5081dc4c0fb0SBarry Smith Level: advanced 5082dc4c0fb0SBarry Smith 5083f6dfbefdSBarry Smith Note: 5084a83b1b31SSatish Balay A hyphen (-) must NOT be given at the beginning of the prefix name. 5085c7afd0dbSLois Curfman McInnes The first character of all runtime options is AUTOMATICALLY the hyphen. 5086d850072dSLois Curfman McInnes 50871cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESAppendOptionsPrefix()` 50883c7409f5SSatish Balay @*/ 5089d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetOptionsPrefix(SNES snes, const char prefix[]) 5090d71ae5a4SJacob Faibussowitsch { 50913a40ed3dSBarry Smith PetscFunctionBegin; 50920700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 50939566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes, prefix)); 50949566063dSJacob Faibussowitsch if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 509535f5d045SPeter Brune if (snes->linesearch) { 50969566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 50979566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch, prefix)); 509835f5d045SPeter Brune } 50999566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(snes->ksp, prefix)); 51003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 51013c7409f5SSatish Balay } 51023c7409f5SSatish Balay 51033c7409f5SSatish Balay /*@C 5104f525115eSLois Curfman McInnes SNESAppendOptionsPrefix - Appends to the prefix used for searching for all 5105f6dfbefdSBarry Smith `SNES` options in the database. 51063c7409f5SSatish Balay 5107c3339decSBarry Smith Logically Collective 5108fee21e36SBarry Smith 5109c7afd0dbSLois Curfman McInnes Input Parameters: 5110f6dfbefdSBarry Smith + snes - the `SNES` context 5111c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names 5112c7afd0dbSLois Curfman McInnes 5113dc4c0fb0SBarry Smith Level: advanced 5114dc4c0fb0SBarry Smith 5115f6dfbefdSBarry Smith Note: 5116a83b1b31SSatish Balay A hyphen (-) must NOT be given at the beginning of the prefix name. 5117c7afd0dbSLois Curfman McInnes The first character of all runtime options is AUTOMATICALLY the hyphen. 5118d850072dSLois Curfman McInnes 51191cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetOptionsPrefix()`, `SNESSetOptionsPrefix()` 51203c7409f5SSatish Balay @*/ 5121d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESAppendOptionsPrefix(SNES snes, const char prefix[]) 5122d71ae5a4SJacob Faibussowitsch { 51233a40ed3dSBarry Smith PetscFunctionBegin; 51240700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 51259566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes, prefix)); 51269566063dSJacob Faibussowitsch if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 512735f5d045SPeter Brune if (snes->linesearch) { 51289566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 51299566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch, prefix)); 513035f5d045SPeter Brune } 51319566063dSJacob Faibussowitsch PetscCall(KSPAppendOptionsPrefix(snes->ksp, prefix)); 51323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 51333c7409f5SSatish Balay } 51343c7409f5SSatish Balay 51359ab63eb5SSatish Balay /*@C 5136f6dfbefdSBarry Smith SNESGetOptionsPrefix - Gets the prefix used for searching for all 5137f6dfbefdSBarry Smith `SNES` options in the database. 51383c7409f5SSatish Balay 5139c7afd0dbSLois Curfman McInnes Not Collective 5140c7afd0dbSLois Curfman McInnes 51413c7409f5SSatish Balay Input Parameter: 5142f6dfbefdSBarry Smith . snes - the `SNES` context 51433c7409f5SSatish Balay 51443c7409f5SSatish Balay Output Parameter: 51453c7409f5SSatish Balay . prefix - pointer to the prefix string used 51463c7409f5SSatish Balay 514736851e7fSLois Curfman McInnes Level: advanced 514836851e7fSLois Curfman McInnes 5149420bcc1bSBarry Smith Fortran Note: 5150dc4c0fb0SBarry Smith The user should pass in a string 'prefix' of 5151dc4c0fb0SBarry Smith sufficient length to hold the prefix. 5152dc4c0fb0SBarry Smith 51531cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetOptionsPrefix()`, `SNESAppendOptionsPrefix()` 51543c7409f5SSatish Balay @*/ 5155d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetOptionsPrefix(SNES snes, const char *prefix[]) 5156d71ae5a4SJacob Faibussowitsch { 51573a40ed3dSBarry Smith PetscFunctionBegin; 51580700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 51599566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)snes, prefix)); 51603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 51613c7409f5SSatish Balay } 51623c7409f5SSatish Balay 51633cea93caSBarry Smith /*@C 51641c84c290SBarry Smith SNESRegister - Adds a method to the nonlinear solver package. 51651c84c290SBarry Smith 516620f4b53cSBarry Smith Not Collective 51671c84c290SBarry Smith 51681c84c290SBarry Smith Input Parameters: 516920f4b53cSBarry Smith + sname - name of a new user-defined solver 517020f4b53cSBarry Smith - function - routine to create method context 51711c84c290SBarry Smith 5172dc4c0fb0SBarry Smith Level: advanced 5173dc4c0fb0SBarry Smith 5174f6dfbefdSBarry Smith Note: 5175f6dfbefdSBarry Smith `SNESRegister()` may be called multiple times to add several user-defined solvers. 51761c84c290SBarry Smith 5177e4094ef1SJacob Faibussowitsch Example Usage: 51781c84c290SBarry Smith .vb 5179bdf89e91SBarry Smith SNESRegister("my_solver", MySolverCreate); 51801c84c290SBarry Smith .ve 51811c84c290SBarry Smith 51821c84c290SBarry Smith Then, your solver can be chosen with the procedural interface via 51831c84c290SBarry Smith $ SNESSetType(snes, "my_solver") 51841c84c290SBarry Smith or at runtime via the option 51851c84c290SBarry Smith $ -snes_type my_solver 51861c84c290SBarry Smith 51871cc06b55SBarry Smith .seealso: [](ch_snes), `SNESRegisterAll()`, `SNESRegisterDestroy()` 51883cea93caSBarry Smith @*/ 5189d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESRegister(const char sname[], PetscErrorCode (*function)(SNES)) 5190d71ae5a4SJacob Faibussowitsch { 5191b2002411SLois Curfman McInnes PetscFunctionBegin; 51929566063dSJacob Faibussowitsch PetscCall(SNESInitializePackage()); 51939566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&SNESList, sname, function)); 51943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5195b2002411SLois Curfman McInnes } 5196da9b6338SBarry Smith 5197d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestLocalMin(SNES snes) 5198d71ae5a4SJacob Faibussowitsch { 519977431f27SBarry Smith PetscInt N, i, j; 5200da9b6338SBarry Smith Vec u, uh, fh; 5201da9b6338SBarry Smith PetscScalar value; 5202da9b6338SBarry Smith PetscReal norm; 5203da9b6338SBarry Smith 5204da9b6338SBarry Smith PetscFunctionBegin; 52059566063dSJacob Faibussowitsch PetscCall(SNESGetSolution(snes, &u)); 52069566063dSJacob Faibussowitsch PetscCall(VecDuplicate(u, &uh)); 52079566063dSJacob Faibussowitsch PetscCall(VecDuplicate(u, &fh)); 5208da9b6338SBarry Smith 5209da9b6338SBarry Smith /* currently only works for sequential */ 52109566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Testing FormFunction() for local min\n")); 52119566063dSJacob Faibussowitsch PetscCall(VecGetSize(u, &N)); 5212da9b6338SBarry Smith for (i = 0; i < N; i++) { 52139566063dSJacob Faibussowitsch PetscCall(VecCopy(u, uh)); 521463a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "i = %" PetscInt_FMT "\n", i)); 5215da9b6338SBarry Smith for (j = -10; j < 11; j++) { 52168b49ba18SBarry Smith value = PetscSign(j) * PetscExpReal(PetscAbs(j) - 10.0); 52179566063dSJacob Faibussowitsch PetscCall(VecSetValue(uh, i, value, ADD_VALUES)); 52189566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, uh, fh)); 52199566063dSJacob Faibussowitsch PetscCall(VecNorm(fh, NORM_2, &norm)); 522063a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), " j norm %" PetscInt_FMT " %18.16e\n", j, (double)norm)); 5221da9b6338SBarry Smith value = -value; 52229566063dSJacob Faibussowitsch PetscCall(VecSetValue(uh, i, value, ADD_VALUES)); 5223da9b6338SBarry Smith } 5224da9b6338SBarry Smith } 52259566063dSJacob Faibussowitsch PetscCall(VecDestroy(&uh)); 52269566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fh)); 52273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5228da9b6338SBarry Smith } 522971f87433Sdalcinl 523071f87433Sdalcinl /*@ 5231f6dfbefdSBarry Smith SNESKSPSetUseEW - Sets `SNES` to the use Eisenstat-Walker method for 523271f87433Sdalcinl computing relative tolerance for linear solvers within an inexact 523371f87433Sdalcinl Newton method. 523471f87433Sdalcinl 5235c3339decSBarry Smith Logically Collective 523671f87433Sdalcinl 523771f87433Sdalcinl Input Parameters: 5238f6dfbefdSBarry Smith + snes - `SNES` context 5239f6dfbefdSBarry Smith - flag - `PETSC_TRUE` or `PETSC_FALSE` 524071f87433Sdalcinl 5241f6dfbefdSBarry Smith Options Database Keys: 524264ba62caSBarry Smith + -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence 524364ba62caSBarry Smith . -snes_ksp_ew_version ver - version of Eisenstat-Walker method 524464ba62caSBarry Smith . -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0 524564ba62caSBarry Smith . -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax 524664ba62caSBarry Smith . -snes_ksp_ew_gamma <gamma> - Sets gamma 524764ba62caSBarry Smith . -snes_ksp_ew_alpha <alpha> - Sets alpha 524864ba62caSBarry Smith . -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2 524964ba62caSBarry Smith - -snes_ksp_ew_threshold <threshold> - Sets threshold 525064ba62caSBarry Smith 5251dc4c0fb0SBarry Smith Level: advanced 5252dc4c0fb0SBarry Smith 5253f6dfbefdSBarry Smith Note: 5254f6dfbefdSBarry Smith The default is to use a constant relative tolerance for 525571f87433Sdalcinl the inner linear solvers. Alternatively, one can use the 525671f87433Sdalcinl Eisenstat-Walker method, where the relative convergence tolerance 525771f87433Sdalcinl is reset at each Newton iteration according progress of the nonlinear 525871f87433Sdalcinl solver. 525971f87433Sdalcinl 5260e4094ef1SJacob Faibussowitsch References: 5261f6dfbefdSBarry Smith . - * S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an inexact Newton method", SISC 17 (1), pp.16-32, 1996. 526271f87433Sdalcinl 52631cc06b55SBarry Smith .seealso: [](ch_snes), `KSP`, `SNES`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()` 526471f87433Sdalcinl @*/ 5265d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetUseEW(SNES snes, PetscBool flag) 5266d71ae5a4SJacob Faibussowitsch { 526771f87433Sdalcinl PetscFunctionBegin; 52680700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5269acfcf0e5SJed Brown PetscValidLogicalCollectiveBool(snes, flag, 2); 527071f87433Sdalcinl snes->ksp_ewconv = flag; 52713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 527271f87433Sdalcinl } 527371f87433Sdalcinl 527471f87433Sdalcinl /*@ 5275f6dfbefdSBarry Smith SNESKSPGetUseEW - Gets if `SNES` is using Eisenstat-Walker method 527671f87433Sdalcinl for computing relative tolerance for linear solvers within an 527771f87433Sdalcinl inexact Newton method. 527871f87433Sdalcinl 527971f87433Sdalcinl Not Collective 528071f87433Sdalcinl 528171f87433Sdalcinl Input Parameter: 5282f6dfbefdSBarry Smith . snes - `SNES` context 528371f87433Sdalcinl 528471f87433Sdalcinl Output Parameter: 5285f6dfbefdSBarry Smith . flag - `PETSC_TRUE` or `PETSC_FALSE` 528671f87433Sdalcinl 528771f87433Sdalcinl Level: advanced 528871f87433Sdalcinl 52891cc06b55SBarry Smith .seealso: [](ch_snes), `SNESKSPSetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()` 529071f87433Sdalcinl @*/ 5291d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag) 5292d71ae5a4SJacob Faibussowitsch { 529371f87433Sdalcinl PetscFunctionBegin; 52940700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 52954f572ea9SToby Isaac PetscAssertPointer(flag, 2); 529671f87433Sdalcinl *flag = snes->ksp_ewconv; 52973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 529871f87433Sdalcinl } 529971f87433Sdalcinl 530071f87433Sdalcinl /*@ 5301fa9f3622SBarry Smith SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker 530271f87433Sdalcinl convergence criteria for the linear solvers within an inexact 530371f87433Sdalcinl Newton method. 530471f87433Sdalcinl 5305c3339decSBarry Smith Logically Collective 530671f87433Sdalcinl 530771f87433Sdalcinl Input Parameters: 5308f6dfbefdSBarry Smith + snes - `SNES` context 53090f0abf79SStefano Zampini . version - version 1, 2 (default is 2), 3 or 4 531071f87433Sdalcinl . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 531171f87433Sdalcinl . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 531271f87433Sdalcinl . gamma - multiplicative factor for version 2 rtol computation 531371f87433Sdalcinl (0 <= gamma2 <= 1) 531471f87433Sdalcinl . alpha - power for version 2 rtol computation (1 < alpha <= 2) 531571f87433Sdalcinl . alpha2 - power for safeguard 531671f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1) 531771f87433Sdalcinl 5318dc4c0fb0SBarry Smith Level: advanced 5319dc4c0fb0SBarry Smith 5320f6dfbefdSBarry Smith Notes: 532171f87433Sdalcinl Version 3 was contributed by Luis Chacon, June 2006. 532271f87433Sdalcinl 5323f6dfbefdSBarry Smith Use `PETSC_DEFAULT` to retain the default for any of the parameters. 532471f87433Sdalcinl 53251cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()` 532671f87433Sdalcinl @*/ 5327d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetParametersEW(SNES snes, PetscInt version, PetscReal rtol_0, PetscReal rtol_max, PetscReal gamma, PetscReal alpha, PetscReal alpha2, PetscReal threshold) 5328d71ae5a4SJacob Faibussowitsch { 5329fa9f3622SBarry Smith SNESKSPEW *kctx; 53305fd66863SKarl Rupp 533171f87433Sdalcinl PetscFunctionBegin; 53320700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5333fa9f3622SBarry Smith kctx = (SNESKSPEW *)snes->kspconvctx; 53345f80ce2aSJacob Faibussowitsch PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing"); 5335c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, version, 2); 5336c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, rtol_0, 3); 5337c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, rtol_max, 4); 5338c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, gamma, 5); 5339c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, alpha, 6); 5340c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, alpha2, 7); 5341c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, threshold, 8); 534271f87433Sdalcinl 534371f87433Sdalcinl if (version != PETSC_DEFAULT) kctx->version = version; 534413bcc0bdSJacob Faibussowitsch if (rtol_0 != (PetscReal)PETSC_DEFAULT) kctx->rtol_0 = rtol_0; 534513bcc0bdSJacob Faibussowitsch if (rtol_max != (PetscReal)PETSC_DEFAULT) kctx->rtol_max = rtol_max; 534613bcc0bdSJacob Faibussowitsch if (gamma != (PetscReal)PETSC_DEFAULT) kctx->gamma = gamma; 534713bcc0bdSJacob Faibussowitsch if (alpha != (PetscReal)PETSC_DEFAULT) kctx->alpha = alpha; 534813bcc0bdSJacob Faibussowitsch if (alpha2 != (PetscReal)PETSC_DEFAULT) kctx->alpha2 = alpha2; 534913bcc0bdSJacob Faibussowitsch if (threshold != (PetscReal)PETSC_DEFAULT) kctx->threshold = threshold; 535071f87433Sdalcinl 53510f0abf79SStefano 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); 53520b121fc5SBarry 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); 53530b121fc5SBarry 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); 53540b121fc5SBarry 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); 53550b121fc5SBarry 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); 53560b121fc5SBarry 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); 53573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 535871f87433Sdalcinl } 535971f87433Sdalcinl 536071f87433Sdalcinl /*@ 5361fa9f3622SBarry Smith SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker 536271f87433Sdalcinl convergence criteria for the linear solvers within an inexact 536371f87433Sdalcinl Newton method. 536471f87433Sdalcinl 536571f87433Sdalcinl Not Collective 536671f87433Sdalcinl 536797bb3fdcSJose E. Roman Input Parameter: 5368f6dfbefdSBarry Smith . snes - `SNES` context 536971f87433Sdalcinl 537071f87433Sdalcinl Output Parameters: 53710f0abf79SStefano Zampini + version - version 1, 2 (default is 2), 3 or 4 537271f87433Sdalcinl . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 537371f87433Sdalcinl . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 5374bf388a1fSBarry Smith . gamma - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1) 537571f87433Sdalcinl . alpha - power for version 2 rtol computation (1 < alpha <= 2) 537671f87433Sdalcinl . alpha2 - power for safeguard 537771f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1) 537871f87433Sdalcinl 537971f87433Sdalcinl Level: advanced 538071f87433Sdalcinl 53811cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPSetParametersEW()` 538271f87433Sdalcinl @*/ 5383d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetParametersEW(SNES snes, PetscInt *version, PetscReal *rtol_0, PetscReal *rtol_max, PetscReal *gamma, PetscReal *alpha, PetscReal *alpha2, PetscReal *threshold) 5384d71ae5a4SJacob Faibussowitsch { 5385fa9f3622SBarry Smith SNESKSPEW *kctx; 53865fd66863SKarl Rupp 538771f87433Sdalcinl PetscFunctionBegin; 53880700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5389fa9f3622SBarry Smith kctx = (SNESKSPEW *)snes->kspconvctx; 53905f80ce2aSJacob Faibussowitsch PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing"); 539171f87433Sdalcinl if (version) *version = kctx->version; 539271f87433Sdalcinl if (rtol_0) *rtol_0 = kctx->rtol_0; 539371f87433Sdalcinl if (rtol_max) *rtol_max = kctx->rtol_max; 539471f87433Sdalcinl if (gamma) *gamma = kctx->gamma; 539571f87433Sdalcinl if (alpha) *alpha = kctx->alpha; 539671f87433Sdalcinl if (alpha2) *alpha2 = kctx->alpha2; 539771f87433Sdalcinl if (threshold) *threshold = kctx->threshold; 53983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 539971f87433Sdalcinl } 540071f87433Sdalcinl 54015c0db29aSPierre Jolivet PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx) 5402d71ae5a4SJacob Faibussowitsch { 54035c0db29aSPierre Jolivet SNES snes = (SNES)ctx; 5404fa9f3622SBarry Smith SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx; 540571f87433Sdalcinl PetscReal rtol = PETSC_DEFAULT, stol; 540671f87433Sdalcinl 540771f87433Sdalcinl PetscFunctionBegin; 54083ba16761SJacob Faibussowitsch if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS); 540930058271SDmitry Karpeev if (!snes->iter) { 541030058271SDmitry Karpeev rtol = kctx->rtol_0; /* first time in, so use the original user rtol */ 54119566063dSJacob Faibussowitsch PetscCall(VecNorm(snes->vec_func, NORM_2, &kctx->norm_first)); 54120f0abf79SStefano Zampini } else { 54130fdf79fbSJacob 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); 541471f87433Sdalcinl if (kctx->version == 1) { 54150f0abf79SStefano Zampini rtol = PetscAbsReal(snes->norm - kctx->lresid_last) / kctx->norm_last; 541685ec1a3cSBarry Smith stol = PetscPowReal(kctx->rtol_last, kctx->alpha2); 541771f87433Sdalcinl if (stol > kctx->threshold) rtol = PetscMax(rtol, stol); 541871f87433Sdalcinl } else if (kctx->version == 2) { 541985ec1a3cSBarry Smith rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha); 542085ec1a3cSBarry Smith stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha); 542171f87433Sdalcinl if (stol > kctx->threshold) rtol = PetscMax(rtol, stol); 542271f87433Sdalcinl } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */ 542385ec1a3cSBarry Smith rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha); 542471f87433Sdalcinl /* safeguard: avoid sharp decrease of rtol */ 542585ec1a3cSBarry Smith stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha); 542671f87433Sdalcinl stol = PetscMax(rtol, stol); 542771f87433Sdalcinl rtol = PetscMin(kctx->rtol_0, stol); 542871f87433Sdalcinl /* safeguard: avoid oversolving */ 542930058271SDmitry Karpeev stol = kctx->gamma * (kctx->norm_first * snes->rtol) / snes->norm; 543071f87433Sdalcinl stol = PetscMax(rtol, stol); 543171f87433Sdalcinl rtol = PetscMin(kctx->rtol_0, stol); 54320fdf79fbSJacob Faibussowitsch } else /* if (kctx->version == 4) */ { 54330fdf79fbSJacob Faibussowitsch /* H.-B. An et al. Journal of Computational and Applied Mathematics 200 (2007) 47-60 */ 54340f0abf79SStefano Zampini PetscReal ared = PetscAbsReal(kctx->norm_last - snes->norm); 54350f0abf79SStefano Zampini PetscReal pred = PetscAbsReal(kctx->norm_last - kctx->lresid_last); 54360f0abf79SStefano Zampini PetscReal rk = ared / pred; 54370f0abf79SStefano Zampini if (rk < kctx->v4_p1) rtol = 1. - 2. * kctx->v4_p1; 54380f0abf79SStefano Zampini else if (rk < kctx->v4_p2) rtol = kctx->rtol_last; 54390f0abf79SStefano Zampini else if (rk < kctx->v4_p3) rtol = kctx->v4_m1 * kctx->rtol_last; 54400f0abf79SStefano Zampini else rtol = kctx->v4_m2 * kctx->rtol_last; 54410f0abf79SStefano Zampini 5442a4598233SStefano 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; 54430f0abf79SStefano Zampini kctx->rtol_last_2 = kctx->rtol_last; 54440f0abf79SStefano Zampini kctx->rk_last_2 = kctx->rk_last; 54450f0abf79SStefano Zampini kctx->rk_last = rk; 54460fdf79fbSJacob Faibussowitsch } 54470f0abf79SStefano Zampini } 54480f0abf79SStefano Zampini /* safeguard: avoid rtol greater than rtol_max */ 544971f87433Sdalcinl rtol = PetscMin(rtol, kctx->rtol_max); 54509566063dSJacob Faibussowitsch PetscCall(KSPSetTolerances(ksp, rtol, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT)); 545163a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "iter %" PetscInt_FMT ", Eisenstat-Walker (version %" PetscInt_FMT ") KSP rtol=%g\n", snes->iter, kctx->version, (double)rtol)); 54523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 545371f87433Sdalcinl } 545471f87433Sdalcinl 54555c0db29aSPierre Jolivet PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx) 5456d71ae5a4SJacob Faibussowitsch { 54575c0db29aSPierre Jolivet SNES snes = (SNES)ctx; 5458fa9f3622SBarry Smith SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx; 545971f87433Sdalcinl PCSide pcside; 546071f87433Sdalcinl Vec lres; 546171f87433Sdalcinl 546271f87433Sdalcinl PetscFunctionBegin; 54633ba16761SJacob Faibussowitsch if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS); 54649566063dSJacob Faibussowitsch PetscCall(KSPGetTolerances(ksp, &kctx->rtol_last, NULL, NULL, NULL)); 546571dbe336SPeter Brune kctx->norm_last = snes->norm; 54660f0abf79SStefano Zampini if (kctx->version == 1 || kctx->version == 4) { 54674f00ce20SMatthew G. Knepley PC pc; 54680f0abf79SStefano Zampini PetscBool getRes; 54694f00ce20SMatthew G. Knepley 54709566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksp, &pc)); 54710f0abf79SStefano Zampini PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &getRes)); 54720f0abf79SStefano Zampini if (!getRes) { 54730f0abf79SStefano Zampini KSPNormType normtype; 54740f0abf79SStefano Zampini 54750f0abf79SStefano Zampini PetscCall(KSPGetNormType(ksp, &normtype)); 54760f0abf79SStefano Zampini getRes = (PetscBool)(normtype == KSP_NORM_UNPRECONDITIONED); 54770f0abf79SStefano Zampini } 54789566063dSJacob Faibussowitsch PetscCall(KSPGetPCSide(ksp, &pcside)); 54790f0abf79SStefano Zampini if (pcside == PC_RIGHT || getRes) { /* KSP residual is true linear residual */ 54809566063dSJacob Faibussowitsch PetscCall(KSPGetResidualNorm(ksp, &kctx->lresid_last)); 548171f87433Sdalcinl } else { 548271f87433Sdalcinl /* KSP residual is preconditioned residual */ 548371f87433Sdalcinl /* compute true linear residual norm */ 54840f0abf79SStefano Zampini Mat J; 54850f0abf79SStefano Zampini PetscCall(KSPGetOperators(ksp, &J, NULL)); 54869566063dSJacob Faibussowitsch PetscCall(VecDuplicate(b, &lres)); 54870f0abf79SStefano Zampini PetscCall(MatMult(J, x, lres)); 54889566063dSJacob Faibussowitsch PetscCall(VecAYPX(lres, -1.0, b)); 54899566063dSJacob Faibussowitsch PetscCall(VecNorm(lres, NORM_2, &kctx->lresid_last)); 54909566063dSJacob Faibussowitsch PetscCall(VecDestroy(&lres)); 549171f87433Sdalcinl } 549271f87433Sdalcinl } 54933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 549471f87433Sdalcinl } 549571f87433Sdalcinl 5496d4211eb9SBarry Smith /*@ 5497f6dfbefdSBarry Smith SNESGetKSP - Returns the `KSP` context for a `SNES` solver. 5498d4211eb9SBarry Smith 5499420bcc1bSBarry Smith Not Collective, but if `snes` is parallel, then `ksp` is parallel 5500d4211eb9SBarry Smith 5501d4211eb9SBarry Smith Input Parameter: 5502f6dfbefdSBarry Smith . snes - the `SNES` context 5503d4211eb9SBarry Smith 5504d4211eb9SBarry Smith Output Parameter: 5505f6dfbefdSBarry Smith . ksp - the `KSP` context 5506d4211eb9SBarry Smith 5507dc4c0fb0SBarry Smith Level: beginner 5508dc4c0fb0SBarry Smith 5509d4211eb9SBarry Smith Notes: 5510f6dfbefdSBarry Smith The user can then directly manipulate the `KSP` context to set various 5511d4211eb9SBarry Smith options, etc. Likewise, the user can then extract and manipulate the 5512f6dfbefdSBarry Smith `PC` contexts as well. 5513f6dfbefdSBarry Smith 5514f6dfbefdSBarry Smith Some `SNESType`s do not use a `KSP` but a `KSP` is still returned by this function 5515d4211eb9SBarry Smith 55161cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSP`, `PC`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()` 5517d4211eb9SBarry Smith @*/ 5518d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetKSP(SNES snes, KSP *ksp) 5519d71ae5a4SJacob Faibussowitsch { 552071f87433Sdalcinl PetscFunctionBegin; 5521d4211eb9SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 55224f572ea9SToby Isaac PetscAssertPointer(ksp, 2); 5523d4211eb9SBarry Smith 5524d4211eb9SBarry Smith if (!snes->ksp) { 55259566063dSJacob Faibussowitsch PetscCall(KSPCreate(PetscObjectComm((PetscObject)snes), &snes->ksp)); 55269566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->ksp, (PetscObject)snes, 1)); 5527d4211eb9SBarry Smith 55285c0db29aSPierre Jolivet PetscCall(KSPSetPreSolve(snes->ksp, KSPPreSolve_SNESEW, snes)); 55295c0db29aSPierre Jolivet PetscCall(KSPSetPostSolve(snes->ksp, KSPPostSolve_SNESEW, snes)); 5530a5c2985bSBarry Smith 55319566063dSJacob Faibussowitsch PetscCall(KSPMonitorSetFromOptions(snes->ksp, "-snes_monitor_ksp", "snes_preconditioned_residual", snes)); 55329566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptions((PetscObject)snes->ksp, ((PetscObject)snes)->options)); 5533d4211eb9SBarry Smith } 5534d4211eb9SBarry Smith *ksp = snes->ksp; 55353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 553671f87433Sdalcinl } 55376c699258SBarry Smith 5538af0996ceSBarry Smith #include <petsc/private/dmimpl.h> 55396c699258SBarry Smith /*@ 5540f6dfbefdSBarry Smith SNESSetDM - Sets the `DM` that may be used by some nonlinear solvers or their underlying preconditioners 55416c699258SBarry Smith 5542c3339decSBarry Smith Logically Collective 55436c699258SBarry Smith 55446c699258SBarry Smith Input Parameters: 55452a808120SBarry Smith + snes - the nonlinear solver context 5546420bcc1bSBarry Smith - dm - the `DM`, cannot be `NULL` 5547dc4c0fb0SBarry Smith 5548dc4c0fb0SBarry Smith Level: intermediate 55496c699258SBarry Smith 5550f6dfbefdSBarry Smith Note: 5551f6dfbefdSBarry Smith A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`, 5552f6dfbefdSBarry Smith even when not using interfaces like `DMSNESSetFunction()`. Use `DMClone()` to get a distinct `DM` when solving different 5553e03a659cSJed Brown problems using the same function space. 5554e03a659cSJed Brown 5555420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()` 55566c699258SBarry Smith @*/ 5557d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDM(SNES snes, DM dm) 5558d71ae5a4SJacob Faibussowitsch { 5559345fed2cSBarry Smith KSP ksp; 5560942e3340SBarry Smith DMSNES sdm; 55616c699258SBarry Smith 55626c699258SBarry Smith PetscFunctionBegin; 55630700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 55642a808120SBarry Smith PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 55659566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 5566942e3340SBarry Smith if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */ 556751f4b3c7SToby Isaac if (snes->dm->dmsnes && !dm->dmsnes) { 55689566063dSJacob Faibussowitsch PetscCall(DMCopyDMSNES(snes->dm, dm)); 55699566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(snes->dm, &sdm)); 5570f5af7f23SKarl Rupp if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */ 55716cab3a1bSJed Brown } 55729566063dSJacob Faibussowitsch PetscCall(DMCoarsenHookRemove(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes)); 55739566063dSJacob Faibussowitsch PetscCall(DMDestroy(&snes->dm)); 55746cab3a1bSJed Brown } 55756c699258SBarry Smith snes->dm = dm; 5576116d1032SJed Brown snes->dmAuto = PETSC_FALSE; 5577f5af7f23SKarl Rupp 55789566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 55799566063dSJacob Faibussowitsch PetscCall(KSPSetDM(ksp, dm)); 55809566063dSJacob Faibussowitsch PetscCall(KSPSetDMActive(ksp, PETSC_FALSE)); 5581efd4aadfSBarry Smith if (snes->npc) { 55829566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes->npc, snes->dm)); 55839566063dSJacob Faibussowitsch PetscCall(SNESSetNPCSide(snes, snes->npcside)); 55842c155ee1SBarry Smith } 55853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 55866c699258SBarry Smith } 55876c699258SBarry Smith 55886c699258SBarry Smith /*@ 5589420bcc1bSBarry Smith SNESGetDM - Gets the `DM` that may be used by some solvers/preconditioners 55906c699258SBarry Smith 5591f6dfbefdSBarry Smith Not Collective but dm obtained is parallel on snes 55926c699258SBarry Smith 55936c699258SBarry Smith Input Parameter: 5594420bcc1bSBarry Smith . snes - the `SNES` context 55956c699258SBarry Smith 55966c699258SBarry Smith Output Parameter: 5597420bcc1bSBarry Smith . dm - the `DM` 55986c699258SBarry Smith 55996c699258SBarry Smith Level: intermediate 56006c699258SBarry Smith 5601420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESSetDM()`, `KSPSetDM()`, `KSPGetDM()` 56026c699258SBarry Smith @*/ 5603d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDM(SNES snes, DM *dm) 5604d71ae5a4SJacob Faibussowitsch { 56056c699258SBarry Smith PetscFunctionBegin; 56060700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 56076cab3a1bSJed Brown if (!snes->dm) { 56089566063dSJacob Faibussowitsch PetscCall(DMShellCreate(PetscObjectComm((PetscObject)snes), &snes->dm)); 5609116d1032SJed Brown snes->dmAuto = PETSC_TRUE; 56106cab3a1bSJed Brown } 56116c699258SBarry Smith *dm = snes->dm; 56123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 56136c699258SBarry Smith } 56140807856dSBarry Smith 561531823bd8SMatthew G Knepley /*@ 5616be95d8f1SBarry Smith SNESSetNPC - Sets the nonlinear preconditioner to be used. 561731823bd8SMatthew G Knepley 5618c3339decSBarry Smith Collective 561931823bd8SMatthew G Knepley 562031823bd8SMatthew G Knepley Input Parameters: 5621f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 5622420bcc1bSBarry Smith - npc - the nonlinear preconditioner object 562331823bd8SMatthew G Knepley 5624dc4c0fb0SBarry Smith Level: developer 5625dc4c0fb0SBarry Smith 562631823bd8SMatthew G Knepley Notes: 5627f6dfbefdSBarry Smith Use `SNESGetNPC()` to retrieve the preconditioner context (for example, 562831823bd8SMatthew G Knepley to configure it using the API). 562931823bd8SMatthew G Knepley 5630f6dfbefdSBarry Smith Only some `SNESType` can use a nonlinear preconditioner 5631f6dfbefdSBarry Smith 5632420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNGS`, `SNESFAS`, `SNESGetNPC()`, `SNESHasNPC()` 563331823bd8SMatthew G Knepley @*/ 5634d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPC(SNES snes, SNES npc) 5635d71ae5a4SJacob Faibussowitsch { 563631823bd8SMatthew G Knepley PetscFunctionBegin; 563731823bd8SMatthew G Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5638f6dfbefdSBarry Smith PetscValidHeaderSpecific(npc, SNES_CLASSID, 2); 5639f6dfbefdSBarry Smith PetscCheckSameComm(snes, 1, npc, 2); 5640f6dfbefdSBarry Smith PetscCall(PetscObjectReference((PetscObject)npc)); 56419566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&snes->npc)); 5642f6dfbefdSBarry Smith snes->npc = npc; 56433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 564431823bd8SMatthew G Knepley } 564531823bd8SMatthew G Knepley 564631823bd8SMatthew G Knepley /*@ 5647f6dfbefdSBarry Smith SNESGetNPC - Gets a nonlinear preconditioning solver SNES` to be used to precondition the original nonlinear solver. 564831823bd8SMatthew G Knepley 5649f6dfbefdSBarry Smith Not Collective; but any changes to the obtained the npc object must be applied collectively 565031823bd8SMatthew G Knepley 565131823bd8SMatthew G Knepley Input Parameter: 5652f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 565331823bd8SMatthew G Knepley 565431823bd8SMatthew G Knepley Output Parameter: 5655e4094ef1SJacob Faibussowitsch . pc - preconditioner context 565631823bd8SMatthew G Knepley 5657f6dfbefdSBarry Smith Options Database Key: 5658f6dfbefdSBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner 5659b5badacbSBarry Smith 5660dc4c0fb0SBarry Smith Level: developer 5661dc4c0fb0SBarry Smith 566295452b02SPatrick Sanan Notes: 5663f6dfbefdSBarry Smith If a `SNES` was previously set with `SNESSetNPC()` then that value is returned, otherwise a new `SNES` object is created. 5664be95d8f1SBarry Smith 5665f6dfbefdSBarry Smith The (preconditioner) `SNES` returned automatically inherits the same nonlinear function and Jacobian supplied to the original 5666f6dfbefdSBarry Smith `SNES` 5667951fe5abSBarry Smith 56681cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESHasNPC()`, `SNES`, `SNESCreate()` 566931823bd8SMatthew G Knepley @*/ 5670d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPC(SNES snes, SNES *pc) 5671d71ae5a4SJacob Faibussowitsch { 5672a64e098fSPeter Brune const char *optionsprefix; 567331823bd8SMatthew G Knepley 567431823bd8SMatthew G Knepley PetscFunctionBegin; 567531823bd8SMatthew G Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 56764f572ea9SToby Isaac PetscAssertPointer(pc, 2); 5677efd4aadfSBarry Smith if (!snes->npc) { 5678ec785e5bSStefano Zampini void *ctx; 5679ec785e5bSStefano Zampini 56809566063dSJacob Faibussowitsch PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &snes->npc)); 56819566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->npc, (PetscObject)snes, 1)); 56829566063dSJacob Faibussowitsch PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 56839566063dSJacob Faibussowitsch PetscCall(SNESSetOptionsPrefix(snes->npc, optionsprefix)); 56849566063dSJacob Faibussowitsch PetscCall(SNESAppendOptionsPrefix(snes->npc, "npc_")); 5685fb87a551SStefano Zampini if (snes->ops->usercompute) { 5686fb87a551SStefano Zampini PetscCall(SNESSetComputeApplicationContext(snes, snes->ops->usercompute, snes->ops->userdestroy)); 5687fb87a551SStefano Zampini } else { 5688ec785e5bSStefano Zampini PetscCall(SNESGetApplicationContext(snes, &ctx)); 5689ec785e5bSStefano Zampini PetscCall(SNESSetApplicationContext(snes->npc, ctx)); 5690fb87a551SStefano Zampini } 56919566063dSJacob Faibussowitsch PetscCall(SNESSetCountersReset(snes->npc, PETSC_FALSE)); 569231823bd8SMatthew G Knepley } 5693efd4aadfSBarry Smith *pc = snes->npc; 56943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 569531823bd8SMatthew G Knepley } 569631823bd8SMatthew G Knepley 56973ad1a0b9SPatrick Farrell /*@ 56983ad1a0b9SPatrick Farrell SNESHasNPC - Returns whether a nonlinear preconditioner exists 56993ad1a0b9SPatrick Farrell 57003ad1a0b9SPatrick Farrell Not Collective 57013ad1a0b9SPatrick Farrell 57023ad1a0b9SPatrick Farrell Input Parameter: 5703f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 57043ad1a0b9SPatrick Farrell 57053ad1a0b9SPatrick Farrell Output Parameter: 5706420bcc1bSBarry Smith . has_npc - whether the `SNES` has a nonlinear preconditioner or not 57073ad1a0b9SPatrick Farrell 57083ad1a0b9SPatrick Farrell Level: developer 57093ad1a0b9SPatrick Farrell 57101cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESGetNPC()` 57113ad1a0b9SPatrick Farrell @*/ 5712d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc) 5713d71ae5a4SJacob Faibussowitsch { 57143ad1a0b9SPatrick Farrell PetscFunctionBegin; 57153ad1a0b9SPatrick Farrell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5716efd4aadfSBarry Smith *has_npc = (PetscBool)(snes->npc ? PETSC_TRUE : PETSC_FALSE); 57173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 57183ad1a0b9SPatrick Farrell } 57193ad1a0b9SPatrick Farrell 5720c40d0f55SPeter Brune /*@ 5721420bcc1bSBarry Smith SNESSetNPCSide - Sets the nonlinear preconditioning side. 5722c40d0f55SPeter Brune 5723c3339decSBarry Smith Logically Collective 5724c40d0f55SPeter Brune 5725c40d0f55SPeter Brune Input Parameter: 5726f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 5727c40d0f55SPeter Brune 5728c40d0f55SPeter Brune Output Parameter: 5729c40d0f55SPeter Brune . side - the preconditioning side, where side is one of 5730c40d0f55SPeter Brune .vb 57312d547940SBarry Smith PC_LEFT - left preconditioning 57322d547940SBarry Smith PC_RIGHT - right preconditioning (default for most nonlinear solvers) 5733c40d0f55SPeter Brune .ve 5734c40d0f55SPeter Brune 5735f6dfbefdSBarry Smith Options Database Key: 573667b8a455SSatish Balay . -snes_npc_side <right,left> - nonlinear preconditioner side 5737c40d0f55SPeter Brune 5738dc4c0fb0SBarry Smith Level: intermediate 5739dc4c0fb0SBarry Smith 5740f6dfbefdSBarry Smith Note: 5741f6dfbefdSBarry Smith `SNESNRICHARDSON` and `SNESNCG` only support left preconditioning. 57422d547940SBarry Smith 5743420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNRICHARDSON`, `SNESNCG`, `SNESType`, `SNESGetNPCSide()`, `KSPSetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide` 5744c40d0f55SPeter Brune @*/ 5745d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPCSide(SNES snes, PCSide side) 5746d71ae5a4SJacob Faibussowitsch { 5747c40d0f55SPeter Brune PetscFunctionBegin; 5748c40d0f55SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5749c40d0f55SPeter Brune PetscValidLogicalCollectiveEnum(snes, side, 2); 5750b552625fSStefano Zampini if (side == PC_SIDE_DEFAULT) side = PC_RIGHT; 575154c59aa7SJacob Faibussowitsch PetscCheck((side == PC_LEFT) || (side == PC_RIGHT), PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Only PC_LEFT and PC_RIGHT are supported"); 5752efd4aadfSBarry Smith snes->npcside = side; 57533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5754c40d0f55SPeter Brune } 5755c40d0f55SPeter Brune 5756c40d0f55SPeter Brune /*@ 5757be95d8f1SBarry Smith SNESGetNPCSide - Gets the preconditioning side. 5758c40d0f55SPeter Brune 5759c40d0f55SPeter Brune Not Collective 5760c40d0f55SPeter Brune 5761c40d0f55SPeter Brune Input Parameter: 5762f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 5763c40d0f55SPeter Brune 5764c40d0f55SPeter Brune Output Parameter: 5765c40d0f55SPeter Brune . side - the preconditioning side, where side is one of 5766c40d0f55SPeter Brune .vb 5767f6dfbefdSBarry Smith `PC_LEFT` - left preconditioning 5768f6dfbefdSBarry Smith `PC_RIGHT` - right preconditioning (default for most nonlinear solvers) 5769c40d0f55SPeter Brune .ve 5770c40d0f55SPeter Brune 5771c40d0f55SPeter Brune Level: intermediate 5772c40d0f55SPeter Brune 5773420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNPCSide()`, `KSPGetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide` 5774c40d0f55SPeter Brune @*/ 5775d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPCSide(SNES snes, PCSide *side) 5776d71ae5a4SJacob Faibussowitsch { 5777c40d0f55SPeter Brune PetscFunctionBegin; 5778c40d0f55SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 57794f572ea9SToby Isaac PetscAssertPointer(side, 2); 5780efd4aadfSBarry Smith *side = snes->npcside; 57813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5782c40d0f55SPeter Brune } 5783c40d0f55SPeter Brune 57849e764e56SPeter Brune /*@ 5785420bcc1bSBarry Smith SNESSetLineSearch - Sets the linesearch to be used for `SNES` 57869e764e56SPeter Brune 5787c3339decSBarry Smith Collective 57889e764e56SPeter Brune 57899e764e56SPeter Brune Input Parameters: 5790f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 57919e764e56SPeter Brune - linesearch - the linesearch object 57929e764e56SPeter Brune 5793dc4c0fb0SBarry Smith Level: developer 5794dc4c0fb0SBarry Smith 5795f6dfbefdSBarry Smith Note: 5796420bcc1bSBarry Smith This is almost never used, rather one uses `SNESGetLineSearch()` to retrieve the line search and set options on it 57979e764e56SPeter Brune to configure it using the API). 57989e764e56SPeter Brune 5799420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()` 58009e764e56SPeter Brune @*/ 5801d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch) 5802d71ae5a4SJacob Faibussowitsch { 58039e764e56SPeter Brune PetscFunctionBegin; 58049e764e56SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5805f1c6b773SPeter Brune PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 2); 58069e764e56SPeter Brune PetscCheckSameComm(snes, 1, linesearch, 2); 58079566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)linesearch)); 58089566063dSJacob Faibussowitsch PetscCall(SNESLineSearchDestroy(&snes->linesearch)); 5809f5af7f23SKarl Rupp 58109e764e56SPeter Brune snes->linesearch = linesearch; 5811f5af7f23SKarl Rupp 58123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 58139e764e56SPeter Brune } 58149e764e56SPeter Brune 5815a34ceb2aSJed Brown /*@ 5816420bcc1bSBarry Smith SNESGetLineSearch - Returns the line search context possibly set with `SNESSetLineSearch()` 5817f6dfbefdSBarry Smith or creates a default line search instance associated with the `SNES` and returns it. 58189e764e56SPeter Brune 58199e764e56SPeter Brune Not Collective 58209e764e56SPeter Brune 58219e764e56SPeter Brune Input Parameter: 5822f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 58239e764e56SPeter Brune 58249e764e56SPeter Brune Output Parameter: 58259e764e56SPeter Brune . linesearch - linesearch context 58269e764e56SPeter Brune 5827162e0bf5SPeter Brune Level: beginner 58289e764e56SPeter Brune 58291cc06b55SBarry Smith .seealso: [](ch_snes), `SNESLineSearch`, `SNESSetLineSearch()`, `SNESLineSearchCreate()` 58309e764e56SPeter Brune @*/ 5831d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch) 5832d71ae5a4SJacob Faibussowitsch { 58339e764e56SPeter Brune const char *optionsprefix; 58349e764e56SPeter Brune 58359e764e56SPeter Brune PetscFunctionBegin; 58369e764e56SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 58374f572ea9SToby Isaac PetscAssertPointer(linesearch, 2); 58389e764e56SPeter Brune if (!snes->linesearch) { 58399566063dSJacob Faibussowitsch PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 58409566063dSJacob Faibussowitsch PetscCall(SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch)); 58419566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetSNES(snes->linesearch, snes)); 58429566063dSJacob Faibussowitsch PetscCall(SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix)); 58439566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->linesearch, (PetscObject)snes, 1)); 58449e764e56SPeter Brune } 58459e764e56SPeter Brune *linesearch = snes->linesearch; 58463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 58479e764e56SPeter Brune } 5848