1af0996ceSBarry Smith #include <petsc/private/snesimpl.h> /*I "petscsnes.h" I*/ 207475bc1SBarry Smith #include <petscdmshell.h> 3d96771aaSLisandro Dalcin #include <petscdraw.h> 4a01aa210SMatthew G. Knepley #include <petscds.h> 534b4d3a8SMatthew G. Knepley #include <petscdmadaptor.h> 606fc46c8SMatthew G. Knepley #include <petscconvest.h> 79b94acceSBarry Smith 8ace3abfcSBarry Smith PetscBool SNESRegisterAllCalled = PETSC_FALSE; 90298fd71SBarry Smith PetscFunctionList SNESList = NULL; 108ba1e511SMatthew Knepley 118ba1e511SMatthew Knepley /* Logging support */ 1222c6f798SBarry Smith PetscClassId SNES_CLASSID, DMSNES_CLASSID; 13fc8bc0e3SRichard Tran Mills PetscLogEvent SNES_Solve, SNES_SetUp, SNES_FunctionEval, SNES_JacobianEval, SNES_NGSEval, SNES_NGSFuncEval, SNES_NPCSolve, SNES_ObjectiveEval; 14a09944afSBarry Smith 15e113a28aSBarry Smith /*@ 16dc4c0fb0SBarry Smith SNESSetErrorIfNotConverged - Causes `SNESSolve()` to generate an error immediately if the solver has not converged. 17e113a28aSBarry Smith 18c3339decSBarry Smith Logically Collective 19e113a28aSBarry Smith 20e113a28aSBarry Smith Input Parameters: 21f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 22f6dfbefdSBarry Smith - flg - `PETSC_TRUE` indicates you want the error generated 23e113a28aSBarry Smith 2420f4b53cSBarry Smith Options Database Key: 2567b8a455SSatish Balay . -snes_error_if_not_converged <true,false> - cause an immediate error condition and stop the program if the solver does not converge 26e113a28aSBarry Smith 27e113a28aSBarry Smith Level: intermediate 28e113a28aSBarry Smith 29f6dfbefdSBarry Smith Note: 30f6dfbefdSBarry Smith Normally PETSc continues if a solver fails to converge, you can call `SNESGetConvergedReason()` after a `SNESSolve()` 31f6dfbefdSBarry Smith to determine if it has converged. Otherwise the solution may be inaccurate or wrong 32e113a28aSBarry Smith 331cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetErrorIfNotConverged()`, `KSPGetErrorIfNotConverged()`, `KSPSetErrorIfNotConverged()` 34e113a28aSBarry Smith @*/ 35d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetErrorIfNotConverged(SNES snes, PetscBool flg) 36d71ae5a4SJacob Faibussowitsch { 37e113a28aSBarry Smith PetscFunctionBegin; 38e113a28aSBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 39acfcf0e5SJed Brown PetscValidLogicalCollectiveBool(snes, flg, 2); 40e113a28aSBarry Smith snes->errorifnotconverged = flg; 413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 42e113a28aSBarry Smith } 43e113a28aSBarry Smith 44e113a28aSBarry Smith /*@ 45f6dfbefdSBarry Smith SNESGetErrorIfNotConverged - Indicates if `SNESSolve()` will generate an error if the solver does not converge? 46e113a28aSBarry Smith 47e113a28aSBarry Smith Not Collective 48e113a28aSBarry Smith 49e113a28aSBarry Smith Input Parameter: 50f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 51e113a28aSBarry Smith 52e113a28aSBarry Smith Output Parameter: 53f6dfbefdSBarry Smith . flag - `PETSC_TRUE` if it will generate an error, else `PETSC_FALSE` 54e113a28aSBarry Smith 55e113a28aSBarry Smith Level: intermediate 56e113a28aSBarry Smith 571cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetErrorIfNotConverged()`, `KSPGetErrorIfNotConverged()`, `KSPSetErrorIfNotConverged()` 58e113a28aSBarry Smith @*/ 59d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetErrorIfNotConverged(SNES snes, PetscBool *flag) 60d71ae5a4SJacob Faibussowitsch { 61e113a28aSBarry Smith PetscFunctionBegin; 62e113a28aSBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 634f572ea9SToby Isaac PetscAssertPointer(flag, 2); 64e113a28aSBarry Smith *flag = snes->errorifnotconverged; 653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 66e113a28aSBarry Smith } 67e113a28aSBarry Smith 684fc747eaSLawrence Mitchell /*@ 69dc4c0fb0SBarry Smith SNESSetAlwaysComputesFinalResidual - tells the `SNES` to always compute the residual (nonlinear function value) at the final solution 704fc747eaSLawrence Mitchell 71c3339decSBarry Smith Logically Collective 724fc747eaSLawrence Mitchell 734fc747eaSLawrence Mitchell Input Parameters: 74f6dfbefdSBarry Smith + snes - the shell `SNES` 75f6dfbefdSBarry Smith - flg - `PETSC_TRUE` to always compute the residual 764fc747eaSLawrence Mitchell 774fc747eaSLawrence Mitchell Level: advanced 784fc747eaSLawrence Mitchell 79f6dfbefdSBarry Smith Note: 80f6dfbefdSBarry Smith Some solvers (such as smoothers in a `SNESFAS`) do not need the residual computed at the final solution so skip computing it 81f6dfbefdSBarry Smith to save time. 82f6dfbefdSBarry Smith 83420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSolve()`, `SNESGetAlwaysComputesFinalResidual()` 844fc747eaSLawrence Mitchell @*/ 85d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetAlwaysComputesFinalResidual(SNES snes, PetscBool flg) 86d71ae5a4SJacob Faibussowitsch { 874fc747eaSLawrence Mitchell PetscFunctionBegin; 884fc747eaSLawrence Mitchell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 894fc747eaSLawrence Mitchell snes->alwayscomputesfinalresidual = flg; 903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 914fc747eaSLawrence Mitchell } 924fc747eaSLawrence Mitchell 934fc747eaSLawrence Mitchell /*@ 94f6dfbefdSBarry Smith SNESGetAlwaysComputesFinalResidual - checks if the `SNES` always computes the residual at the final solution 954fc747eaSLawrence Mitchell 96c3339decSBarry Smith Logically Collective 974fc747eaSLawrence Mitchell 984fc747eaSLawrence Mitchell Input Parameter: 99f6dfbefdSBarry Smith . snes - the `SNES` context 1004fc747eaSLawrence Mitchell 1014fc747eaSLawrence Mitchell Output Parameter: 102f6dfbefdSBarry Smith . flg - `PETSC_TRUE` if the residual is computed 1034fc747eaSLawrence Mitchell 1044fc747eaSLawrence Mitchell Level: advanced 1054fc747eaSLawrence Mitchell 106420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSolve()`, `SNESSetAlwaysComputesFinalResidual()` 1074fc747eaSLawrence Mitchell @*/ 108d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetAlwaysComputesFinalResidual(SNES snes, PetscBool *flg) 109d71ae5a4SJacob Faibussowitsch { 1104fc747eaSLawrence Mitchell PetscFunctionBegin; 1114fc747eaSLawrence Mitchell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1124fc747eaSLawrence Mitchell *flg = snes->alwayscomputesfinalresidual; 1133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1144fc747eaSLawrence Mitchell } 1154fc747eaSLawrence Mitchell 116e725d27bSBarry Smith /*@ 117f6dfbefdSBarry Smith SNESSetFunctionDomainError - tells `SNES` that the input vector, a proposed new solution, to your function you provided to `SNESSetFunction()` is not 118f0b84518SBarry Smith in the functions domain. For example, a step with negative pressure. 1194936397dSBarry Smith 120c3339decSBarry Smith Logically Collective 1214936397dSBarry Smith 1222fe279fdSBarry Smith Input Parameter: 123f6dfbefdSBarry Smith . snes - the `SNES` context 1244936397dSBarry Smith 12528529972SSatish Balay Level: advanced 1264936397dSBarry Smith 127ced0f3aeSBarry Smith Notes: 128ced0f3aeSBarry Smith If this is called the `SNESSolve()` stops iterating and returns with a `SNESConvergedReason` of `SNES_DIVERGED_FUNCTION_DOMAIN` 129ced0f3aeSBarry Smith 130ced0f3aeSBarry Smith You should always call `SNESGetConvergedReason()` after each `SNESSolve()` and verify if the iteration converged (positive result) or diverged (negative result). 131ced0f3aeSBarry Smith 132f0b84518SBarry Smith You can direct `SNES` to avoid certain steps by using `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()` or 133f0b84518SBarry Smith `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()` 134f0b84518SBarry Smith 1358434afd1SBarry Smith .seealso: [](ch_snes), `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetJacobianDomainError()`, `SNESVISetVariableBounds()`, 136ced0f3aeSBarry Smith `SNESVISetComputeVariableBounds()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESConvergedReason`, `SNESGetConvergedReason()` 1374936397dSBarry Smith @*/ 138d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionDomainError(SNES snes) 139d71ae5a4SJacob Faibussowitsch { 1404936397dSBarry Smith PetscFunctionBegin; 1410700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1425f80ce2aSJacob Faibussowitsch PetscCheck(!snes->errorifnotconverged, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "User code indicates input vector is not in the function domain"); 1434936397dSBarry Smith snes->domainerror = PETSC_TRUE; 1443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1454936397dSBarry Smith } 1464936397dSBarry Smith 1476a388c36SPeter Brune /*@ 148f6dfbefdSBarry Smith SNESSetJacobianDomainError - tells `SNES` that the function you provided to `SNESSetJacobian()` at the proposed step. For example there is a negative element transformation. 14907b62357SFande Kong 150c3339decSBarry Smith Logically Collective 15107b62357SFande Kong 1522fe279fdSBarry Smith Input Parameter: 153f6dfbefdSBarry Smith . snes - the `SNES` context 15407b62357SFande Kong 15507b62357SFande Kong Level: advanced 15607b62357SFande Kong 157ced0f3aeSBarry Smith Notes: 158ced0f3aeSBarry Smith If this is called the `SNESSolve()` stops iterating and returns with a `SNESConvergedReason` of `SNES_DIVERGED_FUNCTION_DOMAIN` 159ced0f3aeSBarry Smith 160ced0f3aeSBarry Smith You should always call `SNESGetConvergedReason()` after each `SNESSolve()` and verify if the iteration converged (positive result) or diverged (negative result). 161ced0f3aeSBarry Smith 162f0b84518SBarry Smith You can direct `SNES` to avoid certain steps by using `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()` or 163f0b84518SBarry Smith `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()` 164f0b84518SBarry Smith 1658434afd1SBarry Smith .seealso: [](ch_snes), `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetFunctionDomainError()`, `SNESVISetVariableBounds()`, 166ced0f3aeSBarry Smith `SNESVISetComputeVariableBounds()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESConvergedReason`, `SNESGetConvergedReason()` 16707b62357SFande Kong @*/ 168d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetJacobianDomainError(SNES snes) 169d71ae5a4SJacob Faibussowitsch { 17007b62357SFande Kong PetscFunctionBegin; 17107b62357SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1725f80ce2aSJacob Faibussowitsch PetscCheck(!snes->errorifnotconverged, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "User code indicates computeJacobian does not make sense"); 17307b62357SFande Kong snes->jacobiandomainerror = PETSC_TRUE; 1743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17507b62357SFande Kong } 17607b62357SFande Kong 17707b62357SFande Kong /*@ 178f6dfbefdSBarry Smith SNESSetCheckJacobianDomainError - tells `SNESSolve()` whether to check if the user called `SNESSetJacobianDomainError()` Jacobian domain error after 179420bcc1bSBarry Smith each Jacobian evaluation. By default, it checks for the Jacobian domain error in the debug mode, and does not check it in the optimized mode. 180b351a90bSFande Kong 181c3339decSBarry Smith Logically Collective 182b351a90bSFande Kong 183b351a90bSFande Kong Input Parameters: 18420f4b53cSBarry Smith + snes - the `SNES` context 185f6dfbefdSBarry Smith - flg - indicates if or not to check Jacobian domain error after each Jacobian evaluation 186b351a90bSFande Kong 187b351a90bSFande Kong Level: advanced 188b351a90bSFande Kong 189f6dfbefdSBarry Smith Note: 190f6dfbefdSBarry Smith Checks require one extra parallel synchronization for each Jacobian evaluation 191f6dfbefdSBarry Smith 1928434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetFunctionDomainError()`, `SNESGetCheckJacobianDomainError()` 193b351a90bSFande Kong @*/ 194d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCheckJacobianDomainError(SNES snes, PetscBool flg) 195d71ae5a4SJacob Faibussowitsch { 196b351a90bSFande Kong PetscFunctionBegin; 197b351a90bSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 198b351a90bSFande Kong snes->checkjacdomainerror = flg; 1993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 200b351a90bSFande Kong } 201b351a90bSFande Kong 202b351a90bSFande Kong /*@ 203420bcc1bSBarry Smith SNESGetCheckJacobianDomainError - Get an indicator whether or not `SNES` is checking Jacobian domain errors after each Jacobian evaluation. 2048383d7d7SFande Kong 205c3339decSBarry Smith Logically Collective 2068383d7d7SFande Kong 2072fe279fdSBarry Smith Input Parameter: 208f6dfbefdSBarry Smith . snes - the `SNES` context 2098383d7d7SFande Kong 2102fe279fdSBarry Smith Output Parameter: 211420bcc1bSBarry Smith . flg - `PETSC_FALSE` indicates that it is not checking Jacobian domain errors after each Jacobian evaluation 2128383d7d7SFande Kong 2138383d7d7SFande Kong Level: advanced 2148383d7d7SFande Kong 2158434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetFunctionDomainError()`, `SNESSetCheckJacobianDomainError()` 2168383d7d7SFande Kong @*/ 217d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetCheckJacobianDomainError(SNES snes, PetscBool *flg) 218d71ae5a4SJacob Faibussowitsch { 2198383d7d7SFande Kong PetscFunctionBegin; 2208383d7d7SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2214f572ea9SToby Isaac PetscAssertPointer(flg, 2); 2228383d7d7SFande Kong *flg = snes->checkjacdomainerror; 2233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2248383d7d7SFande Kong } 2258383d7d7SFande Kong 2268383d7d7SFande Kong /*@ 227420bcc1bSBarry Smith SNESGetFunctionDomainError - Gets the status of the domain error after a call to `SNESComputeFunction()` 2286a388c36SPeter Brune 229f6dfbefdSBarry Smith Logically Collective 2306a388c36SPeter Brune 2312fe279fdSBarry Smith Input Parameter: 232f6dfbefdSBarry Smith . snes - the `SNES` context 2336a388c36SPeter Brune 2342fe279fdSBarry Smith Output Parameter: 235f6dfbefdSBarry Smith . domainerror - Set to `PETSC_TRUE` if there's a domain error; `PETSC_FALSE` otherwise. 2366a388c36SPeter Brune 237f6dfbefdSBarry Smith Level: developer 2386a388c36SPeter Brune 2391cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunctionDomainError()`, `SNESComputeFunction()` 2406a388c36SPeter Brune @*/ 241d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionDomainError(SNES snes, PetscBool *domainerror) 242d71ae5a4SJacob Faibussowitsch { 2436a388c36SPeter Brune PetscFunctionBegin; 2446a388c36SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2454f572ea9SToby Isaac PetscAssertPointer(domainerror, 2); 2466a388c36SPeter Brune *domainerror = snes->domainerror; 2473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2486a388c36SPeter Brune } 2496a388c36SPeter Brune 25007b62357SFande Kong /*@ 251420bcc1bSBarry Smith SNESGetJacobianDomainError - Gets the status of the Jacobian domain error after a call to `SNESComputeJacobian()` 25207b62357SFande Kong 253c3339decSBarry Smith Logically Collective 25407b62357SFande Kong 2552fe279fdSBarry Smith Input Parameter: 256f6dfbefdSBarry Smith . snes - the `SNES` context 25707b62357SFande Kong 2582fe279fdSBarry Smith Output Parameter: 259f6dfbefdSBarry Smith . domainerror - Set to `PETSC_TRUE` if there's a Jacobian domain error; `PETSC_FALSE` otherwise. 26007b62357SFande Kong 26107b62357SFande Kong Level: advanced 26207b62357SFande Kong 2631cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunctionDomainError()`, `SNESComputeFunction()`, `SNESGetFunctionDomainError()` 26407b62357SFande Kong @*/ 265d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetJacobianDomainError(SNES snes, PetscBool *domainerror) 266d71ae5a4SJacob Faibussowitsch { 26707b62357SFande Kong PetscFunctionBegin; 26807b62357SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2694f572ea9SToby Isaac PetscAssertPointer(domainerror, 2); 27007b62357SFande Kong *domainerror = snes->jacobiandomainerror; 2713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 27207b62357SFande Kong } 27307b62357SFande Kong 274ffeef943SBarry Smith /*@ 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 324ffeef943SBarry Smith /*@ 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 348ffeef943SBarry Smith /*@ 349dc4c0fb0SBarry Smith SNESView - Prints or visualizes the `SNES` data structure. 3509b94acceSBarry Smith 351c3339decSBarry Smith Collective 352fee21e36SBarry Smith 353c7afd0dbSLois Curfman McInnes Input Parameters: 354f6dfbefdSBarry Smith + snes - the `SNES` context 355f6dfbefdSBarry Smith - viewer - the `PetscViewer` 356c7afd0dbSLois Curfman McInnes 3579b94acceSBarry Smith Options Database Key: 358f6dfbefdSBarry Smith . -snes_view - Calls `SNESView()` at end of `SNESSolve()` 3599b94acceSBarry Smith 360dc4c0fb0SBarry Smith Level: beginner 361dc4c0fb0SBarry Smith 3629b94acceSBarry Smith Notes: 3639b94acceSBarry Smith The available visualization contexts include 364f6dfbefdSBarry Smith + `PETSC_VIEWER_STDOUT_SELF` - standard output (default) 365f6dfbefdSBarry Smith - `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard 366c8a8ba5cSLois Curfman McInnes output where only the first processor opens 367c8a8ba5cSLois Curfman McInnes the file. All other processors send their 368c8a8ba5cSLois Curfman McInnes data to the first processor to print. 3699b94acceSBarry Smith 370052bf0daSPierre Jolivet The available formats include 371f6dfbefdSBarry Smith + `PETSC_VIEWER_DEFAULT` - standard output (default) 372f6dfbefdSBarry Smith - `PETSC_VIEWER_ASCII_INFO_DETAIL` - more verbose output for `SNESNASM` 373052bf0daSPierre Jolivet 3743e081fefSLois Curfman McInnes The user can open an alternative visualization context with 375f6dfbefdSBarry Smith `PetscViewerASCIIOpen()` - output to a specified file. 3769b94acceSBarry Smith 377f6dfbefdSBarry Smith In the debugger you can do "call `SNESView`(snes,0)" to display the `SNES` solver. (The same holds for any PETSc object viewer). 378595c91d4SBarry Smith 3791cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESLoad()`, `SNESCreate()`, `PetscViewerASCIIOpen()` 3809b94acceSBarry Smith @*/ 381d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESView(SNES snes, PetscViewer viewer) 382d71ae5a4SJacob Faibussowitsch { 383fa9f3622SBarry Smith SNESKSPEW *kctx; 38494b7f48cSBarry Smith KSP ksp; 3857f1410a3SPeter Brune SNESLineSearch linesearch; 38672a02f06SBarry Smith PetscBool iascii, isstring, isbinary, isdraw; 3872d53ad75SBarry Smith DMSNES dmsnes; 388e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS) 389536b137fSBarry Smith PetscBool issaws; 390bfb97211SBarry Smith #endif 3919b94acceSBarry Smith 3923a40ed3dSBarry Smith PetscFunctionBegin; 3930700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 39448a46eb9SPierre Jolivet if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &viewer)); 3950700a824SBarry Smith PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 396c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, viewer, 2); 39774679c65SBarry Smith 3989566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 3999566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 4009566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 4019566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 402e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS) 4039566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 404bfb97211SBarry Smith #endif 40532077d6dSBarry Smith if (iascii) { 406dc0571f2SMatthew G. Knepley SNESNormSchedule normschedule; 4078404b7f3SBarry Smith DM dm; 4088434afd1SBarry Smith SNESJacobianFn *cJ; 4098404b7f3SBarry Smith void *ctx; 410789d8953SBarry Smith const char *pre = ""; 411dc0571f2SMatthew G. Knepley 4129566063dSJacob Faibussowitsch PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)snes, viewer)); 41348a46eb9SPierre Jolivet if (!snes->setupcalled) PetscCall(PetscViewerASCIIPrintf(viewer, " SNES has not been set up so information may be incomplete\n")); 414e7788613SBarry Smith if (snes->ops->view) { 4159566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 416dbbe0bcdSBarry Smith PetscUseTypeMethod(snes, view, viewer); 4179566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 4180ef38995SBarry Smith } 41963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " maximum iterations=%" PetscInt_FMT ", maximum function evaluations=%" PetscInt_FMT "\n", snes->max_its, snes->max_funcs)); 4209566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " tolerances: relative=%g, absolute=%g, solution=%g\n", (double)snes->rtol, (double)snes->abstol, (double)snes->stol)); 42148a46eb9SPierre Jolivet if (snes->usesksp) PetscCall(PetscViewerASCIIPrintf(viewer, " total number of linear solver iterations=%" PetscInt_FMT "\n", snes->linear_its)); 42263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " total number of function evaluations=%" PetscInt_FMT "\n", snes->nfuncs)); 4239566063dSJacob Faibussowitsch PetscCall(SNESGetNormSchedule(snes, &normschedule)); 4249566063dSJacob Faibussowitsch if (normschedule > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " norm schedule %s\n", SNESNormSchedules[normschedule])); 42548a46eb9SPierre Jolivet if (snes->gridsequence) PetscCall(PetscViewerASCIIPrintf(viewer, " total number of grid sequence refinements=%" PetscInt_FMT "\n", snes->gridsequence)); 4269b94acceSBarry Smith if (snes->ksp_ewconv) { 427fa9f3622SBarry Smith kctx = (SNESKSPEW *)snes->kspconvctx; 4289b94acceSBarry Smith if (kctx) { 42963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Eisenstat-Walker computation of KSP relative tolerance (version %" PetscInt_FMT ")\n", kctx->version)); 4309566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " rtol_0=%g, rtol_max=%g, threshold=%g\n", (double)kctx->rtol_0, (double)kctx->rtol_max, (double)kctx->threshold)); 4319566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " gamma=%g, alpha=%g, alpha2=%g\n", (double)kctx->gamma, (double)kctx->alpha, (double)kctx->alpha2)); 4329b94acceSBarry Smith } 4339b94acceSBarry Smith } 434eb1f6c34SBarry Smith if (snes->lagpreconditioner == -1) { 4359566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Preconditioned is never rebuilt\n")); 436eb1f6c34SBarry Smith } else if (snes->lagpreconditioner > 1) { 43763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Preconditioned is rebuilt every %" PetscInt_FMT " new Jacobians\n", snes->lagpreconditioner)); 438eb1f6c34SBarry Smith } 439eb1f6c34SBarry Smith if (snes->lagjacobian == -1) { 4409566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Jacobian is never rebuilt\n")); 441eb1f6c34SBarry Smith } else if (snes->lagjacobian > 1) { 44263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Jacobian is rebuilt every %" PetscInt_FMT " SNES iterations\n", snes->lagjacobian)); 443eb1f6c34SBarry Smith } 4449566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 4459566063dSJacob Faibussowitsch PetscCall(DMSNESGetJacobian(dm, &cJ, &ctx)); 446789d8953SBarry Smith if (snes->mf_operator) { 4479566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Jacobian is applied matrix-free with differencing\n")); 448789d8953SBarry Smith pre = "Preconditioning "; 449789d8953SBarry Smith } 4508404b7f3SBarry Smith if (cJ == SNESComputeJacobianDefault) { 4519566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %sJacobian is built using finite differences one column at a time\n", pre)); 4528404b7f3SBarry Smith } else if (cJ == SNESComputeJacobianDefaultColor) { 4539566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %sJacobian is built using finite differences with coloring\n", pre)); 454789d8953SBarry Smith /* it slightly breaks data encapsulation for access the DMDA information directly */ 455789d8953SBarry Smith } else if (cJ == SNESComputeJacobian_DMDA) { 456789d8953SBarry Smith MatFDColoring fdcoloring; 4579566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)dm, "DMDASNES_FDCOLORING", (PetscObject *)&fdcoloring)); 458789d8953SBarry Smith if (fdcoloring) { 4599566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %sJacobian is built using colored finite differences on a DMDA\n", pre)); 460789d8953SBarry Smith } else { 4619566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %sJacobian is built using a DMDA local Jacobian\n", pre)); 462789d8953SBarry Smith } 463996e1cbcSBarry Smith } else if (snes->mf && !snes->mf_operator) { 4649566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Jacobian is applied matrix-free with differencing, no explicit Jacobian\n")); 4658404b7f3SBarry Smith } 4660f5bd95cSBarry Smith } else if (isstring) { 467317d6ea6SBarry Smith const char *type; 4689566063dSJacob Faibussowitsch PetscCall(SNESGetType(snes, &type)); 4699566063dSJacob Faibussowitsch PetscCall(PetscViewerStringSPrintf(viewer, " SNESType: %-7.7s", type)); 470dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, view, viewer); 47155849f57SBarry Smith } else if (isbinary) { 47255849f57SBarry Smith PetscInt classid = SNES_FILE_CLASSID; 47355849f57SBarry Smith MPI_Comm comm; 47455849f57SBarry Smith PetscMPIInt rank; 47555849f57SBarry Smith char type[256]; 47655849f57SBarry Smith 4779566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 4789566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 479dd400576SPatrick Sanan if (rank == 0) { 4809566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryWrite(viewer, &classid, 1, PETSC_INT)); 4819566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(type, ((PetscObject)snes)->type_name, sizeof(type))); 4829566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryWrite(viewer, type, sizeof(type), PETSC_CHAR)); 48355849f57SBarry Smith } 484dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, view, viewer); 48572a02f06SBarry Smith } else if (isdraw) { 48672a02f06SBarry Smith PetscDraw draw; 48772a02f06SBarry Smith char str[36]; 48889fd9fafSBarry Smith PetscReal x, y, bottom, h; 48972a02f06SBarry Smith 4909566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 4919566063dSJacob Faibussowitsch PetscCall(PetscDrawGetCurrentPoint(draw, &x, &y)); 4929566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(str, "SNES: ", sizeof(str))); 4939566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(str, ((PetscObject)snes)->type_name, sizeof(str))); 4949566063dSJacob Faibussowitsch PetscCall(PetscDrawStringBoxed(draw, x, y, PETSC_DRAW_BLUE, PETSC_DRAW_BLACK, str, NULL, &h)); 49589fd9fafSBarry Smith bottom = y - h; 4969566063dSJacob Faibussowitsch PetscCall(PetscDrawPushCurrentPoint(draw, x, bottom)); 497dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, view, viewer); 498e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS) 499536b137fSBarry Smith } else if (issaws) { 500d45a07a7SBarry Smith PetscMPIInt rank; 5012657e9d9SBarry Smith const char *name; 502d45a07a7SBarry Smith 5039566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)snes, &name)); 5049566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 505dd400576SPatrick Sanan if (!((PetscObject)snes)->amsmem && rank == 0) { 506d45a07a7SBarry Smith char dir[1024]; 507d45a07a7SBarry Smith 5089566063dSJacob Faibussowitsch PetscCall(PetscObjectViewSAWs((PetscObject)snes, viewer)); 5099566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/its", name)); 510792fecdfSBarry Smith PetscCallSAWs(SAWs_Register, (dir, &snes->iter, 1, SAWs_READ, SAWs_INT)); 51148a46eb9SPierre Jolivet if (!snes->conv_hist) PetscCall(SNESSetConvergenceHistory(snes, NULL, NULL, PETSC_DECIDE, PETSC_TRUE)); 5129566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/conv_hist", name)); 513792fecdfSBarry Smith PetscCallSAWs(SAWs_Register, (dir, snes->conv_hist, 10, SAWs_READ, SAWs_DOUBLE)); 514f05ece33SBarry Smith } 515bfb97211SBarry Smith #endif 51672a02f06SBarry Smith } 51772a02f06SBarry Smith if (snes->linesearch) { 5189566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &linesearch)); 5199566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 5209566063dSJacob Faibussowitsch PetscCall(SNESLineSearchView(linesearch, viewer)); 5219566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 52219bcc07fSBarry Smith } 523efd4aadfSBarry Smith if (snes->npc && snes->usesnpc) { 5249566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 5259566063dSJacob Faibussowitsch PetscCall(SNESView(snes->npc, viewer)); 5269566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 5274a0c5b0cSMatthew G Knepley } 5289566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 5299566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(snes->dm, &dmsnes)); 5309566063dSJacob Faibussowitsch PetscCall(DMSNESView(dmsnes, viewer)); 5319566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 5322c155ee1SBarry Smith if (snes->usesksp) { 5339566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 5349566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 5359566063dSJacob Faibussowitsch PetscCall(KSPView(ksp, viewer)); 5369566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 5372c155ee1SBarry Smith } 53872a02f06SBarry Smith if (isdraw) { 53972a02f06SBarry Smith PetscDraw draw; 5409566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 5419566063dSJacob Faibussowitsch PetscCall(PetscDrawPopCurrentPoint(draw)); 5427f1410a3SPeter Brune } 5433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5449b94acceSBarry Smith } 5459b94acceSBarry Smith 54676b2cf59SMatthew Knepley /* 54776b2cf59SMatthew Knepley We retain a list of functions that also take SNES command 54876b2cf59SMatthew Knepley line options. These are called at the end SNESSetFromOptions() 54976b2cf59SMatthew Knepley */ 55076b2cf59SMatthew Knepley #define MAXSETFROMOPTIONS 5 551a7cc72afSBarry Smith static PetscInt numberofsetfromoptions; 5526849ba73SBarry Smith static PetscErrorCode (*othersetfromoptions[MAXSETFROMOPTIONS])(SNES); 55376b2cf59SMatthew Knepley 554ac226902SBarry Smith /*@C 555f6dfbefdSBarry Smith SNESAddOptionsChecker - Adds an additional function to check for `SNES` options. 55676b2cf59SMatthew Knepley 55776b2cf59SMatthew Knepley Not Collective 55876b2cf59SMatthew Knepley 55976b2cf59SMatthew Knepley Input Parameter: 56076b2cf59SMatthew Knepley . snescheck - function that checks for options 56176b2cf59SMatthew Knepley 562420bcc1bSBarry Smith Calling sequence of `snescheck`: 563420bcc1bSBarry Smith . snes - the `SNES` object for which it is checking options 564420bcc1bSBarry Smith 56576b2cf59SMatthew Knepley Level: developer 56676b2cf59SMatthew Knepley 5671cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()` 56876b2cf59SMatthew Knepley @*/ 569420bcc1bSBarry Smith PetscErrorCode SNESAddOptionsChecker(PetscErrorCode (*snescheck)(SNES snes)) 570d71ae5a4SJacob Faibussowitsch { 57176b2cf59SMatthew Knepley PetscFunctionBegin; 57263a3b9bcSJacob Faibussowitsch PetscCheck(numberofsetfromoptions < MAXSETFROMOPTIONS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many options checkers, only %d allowed", MAXSETFROMOPTIONS); 57376b2cf59SMatthew Knepley othersetfromoptions[numberofsetfromoptions++] = snescheck; 5743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 57576b2cf59SMatthew Knepley } 57676b2cf59SMatthew Knepley 577d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetUpMatrixFree_Private(SNES snes, PetscBool hasOperator, PetscInt version) 578d71ae5a4SJacob Faibussowitsch { 579aa3661deSLisandro Dalcin Mat J; 580895c21f2SBarry Smith MatNullSpace nullsp; 581aa3661deSLisandro Dalcin 582aa3661deSLisandro Dalcin PetscFunctionBegin; 5830700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 584aa3661deSLisandro Dalcin 58598613b67SLisandro Dalcin if (!snes->vec_func && (snes->jacobian || snes->jacobian_pre)) { 58698613b67SLisandro Dalcin Mat A = snes->jacobian, B = snes->jacobian_pre; 5879566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A ? A : B, NULL, &snes->vec_func)); 58898613b67SLisandro Dalcin } 58998613b67SLisandro Dalcin 5900fdf79fbSJacob Faibussowitsch PetscCheck(version == 1 || version == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "matrix-free operator routines, only version 1 and 2"); 591aa3661deSLisandro Dalcin if (version == 1) { 5929566063dSJacob Faibussowitsch PetscCall(MatCreateSNESMF(snes, &J)); 5939566063dSJacob Faibussowitsch PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix)); 5949566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(J)); 5951e2ae407SBarry Smith /* TODO: the version 2 code should be merged into the MatCreateSNESMF() and MatCreateMFFD() infrastructure and then removed */ 5960fdf79fbSJacob Faibussowitsch } else /* if (version == 2) */ { 5975f80ce2aSJacob Faibussowitsch PetscCheck(snes->vec_func, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "SNESSetFunction() must be called first"); 598570b7f6dSBarry Smith #if !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_REAL_SINGLE) && !defined(PETSC_USE_REAL___FLOAT128) && !defined(PETSC_USE_REAL___FP16) 599f6dfbefdSBarry Smith PetscCall(MatCreateSNESMFMore(snes, snes->vec_func, &J)); 600aa3661deSLisandro Dalcin #else 6012479783cSJose E. Roman SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "matrix-free operator routines (version 2)"); 602aa3661deSLisandro Dalcin #endif 6030fdf79fbSJacob Faibussowitsch } 604aa3661deSLisandro Dalcin 60501c1178eSBarry Smith /* attach any user provided null space that was on Amat to the newly created matrix-free matrix */ 606895c21f2SBarry Smith if (snes->jacobian) { 6079566063dSJacob Faibussowitsch PetscCall(MatGetNullSpace(snes->jacobian, &nullsp)); 6081baa6e33SBarry Smith if (nullsp) PetscCall(MatSetNullSpace(J, nullsp)); 609895c21f2SBarry Smith } 610895c21f2SBarry Smith 61163a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Setting default matrix-free operator routines (version %" PetscInt_FMT ")\n", version)); 612d3462f78SMatthew Knepley if (hasOperator) { 613aa3661deSLisandro Dalcin /* This version replaces the user provided Jacobian matrix with a 614aa3661deSLisandro Dalcin matrix-free version but still employs the user-provided preconditioner matrix. */ 6159566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL)); 616aa3661deSLisandro Dalcin } else { 617aa3661deSLisandro Dalcin /* This version replaces both the user-provided Jacobian and the user- 61801c1178eSBarry Smith provided preconditioner Jacobian with the default matrix-free version. */ 619b552625fSStefano Zampini if (snes->npcside == PC_LEFT && snes->npc) { 6209566063dSJacob Faibussowitsch if (!snes->jacobian) PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL)); 621172a4300SPeter Brune } else { 622789d8953SBarry Smith KSP ksp; 623789d8953SBarry Smith PC pc; 624789d8953SBarry Smith PetscBool match; 625789d8953SBarry Smith 6269566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J, J, MatMFFDComputeJacobian, NULL)); 627aa3661deSLisandro Dalcin /* Force no preconditioner */ 6289566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 6299566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksp, &pc)); 6302698c518SLisandro Dalcin PetscCall(PetscObjectTypeCompareAny((PetscObject)pc, &match, PCSHELL, PCH2OPUS, "")); 631aa3661deSLisandro Dalcin if (!match) { 6329566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Setting default matrix-free preconditioner routines\nThat is no preconditioner is being used\n")); 6339566063dSJacob Faibussowitsch PetscCall(PCSetType(pc, PCNONE)); 634aa3661deSLisandro Dalcin } 635aa3661deSLisandro Dalcin } 636789d8953SBarry Smith } 6379566063dSJacob Faibussowitsch PetscCall(MatDestroy(&J)); 6383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 639aa3661deSLisandro Dalcin } 640aa3661deSLisandro Dalcin 641d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMRestrictHook_SNESVecSol(DM dmfine, Mat Restrict, Vec Rscale, Mat Inject, DM dmcoarse, void *ctx) 642d71ae5a4SJacob Faibussowitsch { 643dfe15315SJed Brown SNES snes = (SNES)ctx; 6440298fd71SBarry Smith Vec Xfine, Xfine_named = NULL, Xcoarse; 645dfe15315SJed Brown 646dfe15315SJed Brown PetscFunctionBegin; 64716ebb321SJed Brown if (PetscLogPrintInfo) { 64816ebb321SJed Brown PetscInt finelevel, coarselevel, fineclevel, coarseclevel; 6499566063dSJacob Faibussowitsch PetscCall(DMGetRefineLevel(dmfine, &finelevel)); 6509566063dSJacob Faibussowitsch PetscCall(DMGetCoarsenLevel(dmfine, &fineclevel)); 6519566063dSJacob Faibussowitsch PetscCall(DMGetRefineLevel(dmcoarse, &coarselevel)); 6529566063dSJacob Faibussowitsch PetscCall(DMGetCoarsenLevel(dmcoarse, &coarseclevel)); 65363a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dmfine, "Restricting SNES solution vector from level %" PetscInt_FMT "-%" PetscInt_FMT " to level %" PetscInt_FMT "-%" PetscInt_FMT "\n", finelevel, fineclevel, coarselevel, coarseclevel)); 65416ebb321SJed Brown } 655dfe15315SJed Brown if (dmfine == snes->dm) Xfine = snes->vec_sol; 656dfe15315SJed Brown else { 6579566063dSJacob Faibussowitsch PetscCall(DMGetNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named)); 658dfe15315SJed Brown Xfine = Xfine_named; 659dfe15315SJed Brown } 6609566063dSJacob Faibussowitsch PetscCall(DMGetNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse)); 661907f5c5aSLawrence Mitchell if (Inject) { 6629566063dSJacob Faibussowitsch PetscCall(MatRestrict(Inject, Xfine, Xcoarse)); 663907f5c5aSLawrence Mitchell } else { 6649566063dSJacob Faibussowitsch PetscCall(MatRestrict(Restrict, Xfine, Xcoarse)); 6659566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(Xcoarse, Xcoarse, Rscale)); 666907f5c5aSLawrence Mitchell } 6679566063dSJacob Faibussowitsch PetscCall(DMRestoreNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse)); 6689566063dSJacob Faibussowitsch if (Xfine_named) PetscCall(DMRestoreNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named)); 6693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 670dfe15315SJed Brown } 671dfe15315SJed Brown 672d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCoarsenHook_SNESVecSol(DM dm, DM dmc, void *ctx) 673d71ae5a4SJacob Faibussowitsch { 67416ebb321SJed Brown PetscFunctionBegin; 6759566063dSJacob Faibussowitsch PetscCall(DMCoarsenHookAdd(dmc, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, ctx)); 6763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 67716ebb321SJed Brown } 67816ebb321SJed Brown 679a6950cb2SJed Brown /* This may be called to rediscretize the operator on levels of linear multigrid. The DM shuffle is so the user can 680a6950cb2SJed Brown * safely call SNESGetDM() in their residual evaluation routine. */ 681d71ae5a4SJacob Faibussowitsch static PetscErrorCode KSPComputeOperators_SNES(KSP ksp, Mat A, Mat B, void *ctx) 682d71ae5a4SJacob Faibussowitsch { 683caa4e7f2SJed Brown SNES snes = (SNES)ctx; 68497d931d1SStefano Zampini DMSNES sdm; 6850298fd71SBarry Smith Vec X, Xnamed = NULL; 686dfe15315SJed Brown DM dmsave; 6874e269d77SPeter Brune void *ctxsave; 6888434afd1SBarry Smith SNESJacobianFn *jac = NULL; 689caa4e7f2SJed Brown 690caa4e7f2SJed Brown PetscFunctionBegin; 691dfe15315SJed Brown dmsave = snes->dm; 6929566063dSJacob Faibussowitsch PetscCall(KSPGetDM(ksp, &snes->dm)); 693dfe15315SJed Brown if (dmsave == snes->dm) X = snes->vec_sol; /* We are on the finest level */ 69497d931d1SStefano Zampini else { 695309d62e6SStefano Zampini PetscBool has; 696309d62e6SStefano Zampini 69797d931d1SStefano Zampini /* We are on a coarser level, this vec was initialized using a DM restrict hook */ 698309d62e6SStefano Zampini PetscCall(DMHasNamedGlobalVector(snes->dm, "SNESVecSol", &has)); 699309d62e6SStefano Zampini PetscCheck(has, PetscObjectComm((PetscObject)snes->dm), PETSC_ERR_PLIB, "Missing SNESVecSol"); 70097d931d1SStefano Zampini PetscCall(DMGetNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed)); 701dfe15315SJed Brown X = Xnamed; 7029566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, NULL, NULL, &jac, &ctxsave)); 7034e269d77SPeter Brune /* If the DM's don't match up, the MatFDColoring context needed for the jacobian won't match up either -- fixit. */ 70448a46eb9SPierre Jolivet if (jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, SNESComputeJacobianDefaultColor, NULL)); 7054e269d77SPeter Brune } 7064e269d77SPeter Brune 7072b93b426SMatthew G. Knepley /* Compute the operators */ 70897d931d1SStefano Zampini PetscCall(DMGetDMSNES(snes->dm, &sdm)); 70997d931d1SStefano Zampini if (Xnamed && sdm->ops->computefunction) { 71097d931d1SStefano Zampini /* The SNES contract with the user is that ComputeFunction is always called before ComputeJacobian. 71197d931d1SStefano Zampini We make sure of this here. Disable affine shift since it is for the finest level */ 71297d931d1SStefano Zampini Vec F, saverhs = snes->vec_rhs; 71397d931d1SStefano Zampini 71497d931d1SStefano Zampini snes->vec_rhs = NULL; 71597d931d1SStefano Zampini PetscCall(DMGetGlobalVector(snes->dm, &F)); 71697d931d1SStefano Zampini PetscCall(SNESComputeFunction(snes, X, F)); 71797d931d1SStefano Zampini PetscCall(DMRestoreGlobalVector(snes->dm, &F)); 71897d931d1SStefano Zampini snes->vec_rhs = saverhs; 71997d931d1SStefano Zampini snes->nfuncs--; /* Do not log coarser level evaluations */ 72097d931d1SStefano Zampini } 72197d931d1SStefano Zampini /* Make sure KSP DM has the Jacobian computation routine */ 72297d931d1SStefano Zampini if (!sdm->ops->computejacobian) PetscCall(DMCopyDMSNES(dmsave, snes->dm)); 7239566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobian(snes, X, A, B)); 72497d931d1SStefano Zampini 7252b93b426SMatthew G. Knepley /* Put the previous context back */ 72648a46eb9SPierre Jolivet if (snes->dm != dmsave && jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, jac, ctxsave)); 7274e269d77SPeter Brune 7289566063dSJacob Faibussowitsch if (Xnamed) PetscCall(DMRestoreNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed)); 729dfe15315SJed Brown snes->dm = dmsave; 7303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 731caa4e7f2SJed Brown } 732caa4e7f2SJed Brown 7336cab3a1bSJed Brown /*@ 734dc4c0fb0SBarry Smith SNESSetUpMatrices - ensures that matrices are available for `SNES` Newton-like methods, this is called by `SNESSetUp_XXX()` 7356cab3a1bSJed Brown 7366cab3a1bSJed Brown Collective 7376cab3a1bSJed Brown 7384165533cSJose E. Roman Input Parameter: 73920f4b53cSBarry Smith . snes - `SNES` object to configure 7406cab3a1bSJed Brown 7416cab3a1bSJed Brown Level: developer 7426cab3a1bSJed Brown 743dc4c0fb0SBarry Smith Note: 744dc4c0fb0SBarry 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` 745dc4c0fb0SBarry Smith 74673a84a35SBarry Smith Developer Note: 74773a84a35SBarry Smith The functionality of this routine overlaps in a confusing way with the functionality of `SNESSetUpMatrixFree_Private()` which is called by 74873a84a35SBarry Smith `SNESSetUp()` but sometimes `SNESSetUpMatrices()` is called without `SNESSetUp()` being called. A refactorization to simplify the 74973a84a35SBarry Smith logic that handles the matrix-free case is desirable. 75073a84a35SBarry Smith 7511cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUp()` 7526cab3a1bSJed Brown @*/ 753d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUpMatrices(SNES snes) 754d71ae5a4SJacob Faibussowitsch { 7556cab3a1bSJed Brown DM dm; 756942e3340SBarry Smith DMSNES sdm; 7576cab3a1bSJed Brown 7586cab3a1bSJed Brown PetscFunctionBegin; 7599566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 7609566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 76173a84a35SBarry Smith if (!snes->jacobian && snes->mf && !snes->mf_operator && !snes->jacobian_pre) { 7626cab3a1bSJed Brown Mat J; 7636cab3a1bSJed Brown void *functx; 7649566063dSJacob Faibussowitsch PetscCall(MatCreateSNESMF(snes, &J)); 7659566063dSJacob Faibussowitsch PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix)); 7669566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(J)); 7679566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, NULL, &functx)); 7689566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J, J, NULL, NULL)); 7699566063dSJacob Faibussowitsch PetscCall(MatDestroy(&J)); 770caa4e7f2SJed Brown } else if (snes->mf_operator && !snes->jacobian_pre && !snes->jacobian) { 7716cab3a1bSJed Brown Mat J, B; 7729566063dSJacob Faibussowitsch PetscCall(MatCreateSNESMF(snes, &J)); 7739566063dSJacob Faibussowitsch PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix)); 7749566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(J)); 7759566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(snes->dm, &B)); 77606f20277SJed Brown /* sdm->computejacobian was already set to reach here */ 7779566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J, B, NULL, NULL)); 7789566063dSJacob Faibussowitsch PetscCall(MatDestroy(&J)); 7799566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 780caa4e7f2SJed Brown } else if (!snes->jacobian_pre) { 7811ba9b98eSMatthew G. Knepley PetscDS prob; 7826cab3a1bSJed Brown Mat J, B; 7831ba9b98eSMatthew G. Knepley PetscBool hasPrec = PETSC_FALSE; 7841ba9b98eSMatthew G. Knepley 7856cab3a1bSJed Brown J = snes->jacobian; 7869566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob)); 7879566063dSJacob Faibussowitsch if (prob) PetscCall(PetscDSHasJacobianPreconditioner(prob, &hasPrec)); 7889566063dSJacob Faibussowitsch if (J) PetscCall(PetscObjectReference((PetscObject)J)); 7899566063dSJacob Faibussowitsch else if (hasPrec) PetscCall(DMCreateMatrix(snes->dm, &J)); 7909566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(snes->dm, &B)); 7919566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J ? J : B, B, NULL, NULL)); 7929566063dSJacob Faibussowitsch PetscCall(MatDestroy(&J)); 7939566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 7946cab3a1bSJed Brown } 795caa4e7f2SJed Brown { 796caa4e7f2SJed Brown KSP ksp; 7979566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 7989566063dSJacob Faibussowitsch PetscCall(KSPSetComputeOperators(ksp, KSPComputeOperators_SNES, snes)); 7999566063dSJacob Faibussowitsch PetscCall(DMCoarsenHookAdd(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes)); 800caa4e7f2SJed Brown } 8013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8026cab3a1bSJed Brown } 8036cab3a1bSJed Brown 804d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESMonitorPauseFinal_Internal(SNES snes) 805d71ae5a4SJacob Faibussowitsch { 8065e7c47f3SMatthew G. Knepley PetscInt i; 8075e7c47f3SMatthew G. Knepley 8085e7c47f3SMatthew G. Knepley PetscFunctionBegin; 8093ba16761SJacob Faibussowitsch if (!snes->pauseFinal) PetscFunctionReturn(PETSC_SUCCESS); 8105e7c47f3SMatthew G. Knepley for (i = 0; i < snes->numbermonitors; ++i) { 8115e7c47f3SMatthew G. Knepley PetscViewerAndFormat *vf = (PetscViewerAndFormat *)snes->monitorcontext[i]; 8125e7c47f3SMatthew G. Knepley PetscDraw draw; 8135e7c47f3SMatthew G. Knepley PetscReal lpause; 8145e7c47f3SMatthew G. Knepley 8155e7c47f3SMatthew G. Knepley if (!vf) continue; 8165e7c47f3SMatthew G. Knepley if (vf->lg) { 8175e7c47f3SMatthew G. Knepley if (!PetscCheckPointer(vf->lg, PETSC_OBJECT)) continue; 8185e7c47f3SMatthew G. Knepley if (((PetscObject)vf->lg)->classid != PETSC_DRAWLG_CLASSID) continue; 8199566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(vf->lg, &draw)); 8209566063dSJacob Faibussowitsch PetscCall(PetscDrawGetPause(draw, &lpause)); 8219566063dSJacob Faibussowitsch PetscCall(PetscDrawSetPause(draw, -1.0)); 8229566063dSJacob Faibussowitsch PetscCall(PetscDrawPause(draw)); 8239566063dSJacob Faibussowitsch PetscCall(PetscDrawSetPause(draw, lpause)); 8245e7c47f3SMatthew G. Knepley } else { 8255e7c47f3SMatthew G. Knepley PetscBool isdraw; 8265e7c47f3SMatthew G. Knepley 8275e7c47f3SMatthew G. Knepley if (!PetscCheckPointer(vf->viewer, PETSC_OBJECT)) continue; 8285e7c47f3SMatthew G. Knepley if (((PetscObject)vf->viewer)->classid != PETSC_VIEWER_CLASSID) continue; 8299566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)vf->viewer, PETSCVIEWERDRAW, &isdraw)); 8305e7c47f3SMatthew G. Knepley if (!isdraw) continue; 8319566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(vf->viewer, 0, &draw)); 8329566063dSJacob Faibussowitsch PetscCall(PetscDrawGetPause(draw, &lpause)); 8339566063dSJacob Faibussowitsch PetscCall(PetscDrawSetPause(draw, -1.0)); 8349566063dSJacob Faibussowitsch PetscCall(PetscDrawPause(draw)); 8359566063dSJacob Faibussowitsch PetscCall(PetscDrawSetPause(draw, lpause)); 8365e7c47f3SMatthew G. Knepley } 8375e7c47f3SMatthew G. Knepley } 8383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8395e7c47f3SMatthew G. Knepley } 8405e7c47f3SMatthew G. Knepley 841fde5950dSBarry Smith /*@C 842fde5950dSBarry Smith SNESMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user 843fde5950dSBarry Smith 844c3339decSBarry Smith Collective 845fde5950dSBarry Smith 846fde5950dSBarry Smith Input Parameters: 847dc4c0fb0SBarry Smith + snes - `SNES` object you wish to monitor 848fde5950dSBarry Smith . name - the monitor type one is seeking 849fde5950dSBarry Smith . help - message indicating what monitoring is done 850fde5950dSBarry Smith . manual - manual page for the monitor 851fde5950dSBarry Smith . monitor - the monitor function 852f6dfbefdSBarry 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 853fde5950dSBarry Smith 854420bcc1bSBarry Smith Calling sequence of `monitor`: 855420bcc1bSBarry Smith + snes - the nonlinear solver context 856420bcc1bSBarry Smith . it - the current iteration 857420bcc1bSBarry Smith . r - the current function norm 858420bcc1bSBarry Smith - vf - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use 859420bcc1bSBarry Smith 860420bcc1bSBarry Smith Calling sequence of `monitorsetup`: 861420bcc1bSBarry Smith + snes - the nonlinear solver context 862420bcc1bSBarry Smith - vf - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use 863420bcc1bSBarry Smith 864f6dfbefdSBarry Smith Options Database Key: 865f6dfbefdSBarry Smith . -name - trigger the use of this monitor in `SNESSetFromOptions()` 866f6dfbefdSBarry Smith 867f6dfbefdSBarry Smith Level: advanced 868fde5950dSBarry Smith 8691cc06b55SBarry Smith .seealso: [](ch_snes), `PetscOptionsGetViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, 870db781477SPatrick Sanan `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()` 871e4094ef1SJacob Faibussowitsch `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, 872db781477SPatrick Sanan `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`, 873c2e3fba1SPatrick Sanan `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`, 874db781477SPatrick Sanan `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`, 875db781477SPatrick Sanan `PetscOptionsFList()`, `PetscOptionsEList()` 876fde5950dSBarry Smith @*/ 877420bcc1bSBarry 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)) 878d71ae5a4SJacob Faibussowitsch { 879fde5950dSBarry Smith PetscViewer viewer; 880fde5950dSBarry Smith PetscViewerFormat format; 881fde5950dSBarry Smith PetscBool flg; 882fde5950dSBarry Smith 883fde5950dSBarry Smith PetscFunctionBegin; 8849566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, name, &viewer, &format, &flg)); 885fde5950dSBarry Smith if (flg) { 886d43b4f6eSBarry Smith PetscViewerAndFormat *vf; 8879566063dSJacob Faibussowitsch PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf)); 888cd791dc2SBarry Smith PetscCall(PetscOptionsRestoreViewer(&viewer)); 8891baa6e33SBarry Smith if (monitorsetup) PetscCall((*monitorsetup)(snes, vf)); 8909566063dSJacob Faibussowitsch PetscCall(SNESMonitorSet(snes, (PetscErrorCode(*)(SNES, PetscInt, PetscReal, void *))monitor, vf, (PetscErrorCode(*)(void **))PetscViewerAndFormatDestroy)); 891fde5950dSBarry Smith } 8923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 893fde5950dSBarry Smith } 894fde5950dSBarry Smith 895a4598233SStefano Zampini PetscErrorCode SNESEWSetFromOptions_Private(SNESKSPEW *kctx, PetscBool print_api, MPI_Comm comm, const char *prefix) 896d71ae5a4SJacob Faibussowitsch { 897a4598233SStefano Zampini const char *api = print_api ? "SNESKSPSetParametersEW" : NULL; 898a4598233SStefano Zampini 8990f0abf79SStefano Zampini PetscFunctionBegin; 9000f0abf79SStefano Zampini PetscOptionsBegin(comm, prefix, "Eisenstat and Walker type forcing options", "KSP"); 901a4598233SStefano Zampini PetscCall(PetscOptionsInt("-ksp_ew_version", "Version 1, 2 or 3", api, kctx->version, &kctx->version, NULL)); 902a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_rtol0", "0 <= rtol0 < 1", api, kctx->rtol_0, &kctx->rtol_0, NULL)); 903a4598233SStefano Zampini kctx->rtol_max = PetscMax(kctx->rtol_0, kctx->rtol_max); 904a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_rtolmax", "0 <= rtolmax < 1", api, kctx->rtol_max, &kctx->rtol_max, NULL)); 905a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_gamma", "0 <= gamma <= 1", api, kctx->gamma, &kctx->gamma, NULL)); 906a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_alpha", "1 < alpha <= 2", api, kctx->alpha, &kctx->alpha, NULL)); 9070f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_alpha2", "alpha2", NULL, kctx->alpha2, &kctx->alpha2, NULL)); 908a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_threshold", "0 < threshold < 1", api, kctx->threshold, &kctx->threshold, NULL)); 9090f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_p1", "p1", NULL, kctx->v4_p1, &kctx->v4_p1, NULL)); 9100f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_p2", "p2", NULL, kctx->v4_p2, &kctx->v4_p2, NULL)); 9110f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_p3", "p3", NULL, kctx->v4_p3, &kctx->v4_p3, NULL)); 9120f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_m1", "Scaling when rk-1 in [p2,p3)", NULL, kctx->v4_m1, &kctx->v4_m1, NULL)); 9130f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_m2", "Scaling when rk-1 in [p3,+infty)", NULL, kctx->v4_m2, &kctx->v4_m2, NULL)); 9140f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_m3", "Threshold for successive rtol (0.1 in Eq.7)", NULL, kctx->v4_m3, &kctx->v4_m3, NULL)); 9150f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_m4", "Adaptation scaling (0.5 in Eq.7)", NULL, kctx->v4_m4, &kctx->v4_m4, NULL)); 9160f0abf79SStefano Zampini PetscOptionsEnd(); 9173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9180f0abf79SStefano Zampini } 9190f0abf79SStefano Zampini 9209b94acceSBarry Smith /*@ 921f6dfbefdSBarry Smith SNESSetFromOptions - Sets various `SNES` and `KSP` parameters from user options. 9229b94acceSBarry Smith 923c3339decSBarry Smith Collective 924c7afd0dbSLois Curfman McInnes 9259b94acceSBarry Smith Input Parameter: 926f6dfbefdSBarry Smith . snes - the `SNES` context 9279b94acceSBarry Smith 92836851e7fSLois Curfman McInnes Options Database Keys: 929f6dfbefdSBarry Smith + -snes_type <type> - newtonls, newtontr, ngmres, ncg, nrichardson, qn, vi, fas, `SNESType` for complete list 930ceaaa498SBarry Smith . -snes_stol <stol> - convergence tolerance in terms of the norm of the change in the solution between steps 93170441072SBarry Smith . -snes_atol <abstol> - absolute tolerance of residual norm 932b39c3a46SLois Curfman McInnes . -snes_rtol <rtol> - relative decrease in tolerance norm from initial 933e4d06f11SPatrick Farrell . -snes_divergence_tolerance <divtol> - if the residual goes above divtol*rnorm0, exit with divergence 934ceaaa498SBarry Smith . -snes_force_iteration <force> - force `SNESSolve()` to take at least one iteration 935b39c3a46SLois Curfman McInnes . -snes_max_it <max_it> - maximum number of iterations 936b39c3a46SLois Curfman McInnes . -snes_max_funcs <max_funcs> - maximum number of function evaluations 9374839bfe8SBarry Smith . -snes_max_fail <max_fail> - maximum number of line search failures allowed before stopping, default is none 938ddf469c8SBarry Smith . -snes_max_linear_solve_fail - number of linear solver failures before SNESSolve() stops 939a8054027SBarry Smith . -snes_lag_preconditioner <lag> - how often preconditioner is rebuilt (use -1 to never rebuild) 9403d5a8a6aSBarry Smith . -snes_lag_preconditioner_persists <true,false> - retains the -snes_lag_preconditioner information across multiple SNESSolve() 941e35cf81dSBarry Smith . -snes_lag_jacobian <lag> - how often Jacobian is rebuilt (use -1 to never rebuild) 9423d5a8a6aSBarry Smith . -snes_lag_jacobian_persists <true,false> - retains the -snes_lag_jacobian information across multiple SNESSolve() 9434a221d59SStefano Zampini . -snes_tr_tol <trtol> - trust region tolerance 944ceaaa498SBarry 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. 945fde5950dSBarry Smith . -snes_monitor [ascii][:filename][:viewer format] - prints residual norm at each iteration. if no filename given prints to stdout 946fde5950dSBarry Smith . -snes_monitor_solution [ascii binary draw][:filename][:viewer format] - plots solution at each iteration 947fde5950dSBarry Smith . -snes_monitor_residual [ascii binary draw][:filename][:viewer format] - plots residual (not its norm) at each iteration 948fde5950dSBarry Smith . -snes_monitor_solution_update [ascii binary draw][:filename][:viewer format] - plots update to solution at each iteration 9494619e776SBarry Smith . -snes_monitor_lg_residualnorm - plots residual norm at each iteration 950459f5d12SBarry Smith . -snes_monitor_lg_range - plots residual norm at each iteration 9515e7c47f3SMatthew G. Knepley . -snes_monitor_pause_final - Pauses all monitor drawing after the solver ends 952e24b481bSBarry Smith . -snes_fd - use finite differences to compute Jacobian; very slow, only for testing 953e2e60de9SPeter Brune . -snes_fd_color - use finite differences with coloring to compute Jacobian 954ceaaa498SBarry Smith . -snes_mf_ksp_monitor - if using matrix-free multiply then print h at each `KSP` iteration 955b5badacbSBarry Smith . -snes_converged_reason - print the reason for convergence/divergence after each solve 956ceaaa498SBarry Smith . -npc_snes_type <type> - the `SNES` type to use as a nonlinear preconditioner 957e62ac41dSBarry 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. 958e62ac41dSBarry 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. 95982738288SBarry Smith 960f6dfbefdSBarry Smith Options Database Keys for Eisenstat-Walker method: 961fa9f3622SBarry Smith + -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence 9624b27c08aSLois Curfman McInnes . -snes_ksp_ew_version ver - version of Eisenstat-Walker method 96336851e7fSLois Curfman McInnes . -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0 96436851e7fSLois Curfman McInnes . -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax 96536851e7fSLois Curfman McInnes . -snes_ksp_ew_gamma <gamma> - Sets gamma 96636851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha <alpha> - Sets alpha 96736851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2 96836851e7fSLois Curfman McInnes - -snes_ksp_ew_threshold <threshold> - Sets threshold 96982738288SBarry Smith 970dc4c0fb0SBarry Smith Level: beginner 971dc4c0fb0SBarry Smith 97211ca99fdSLois Curfman McInnes Notes: 973ec5066bdSBarry Smith To see all options, run your program with the -help option or consult the users manual 974ec5066bdSBarry Smith 975420bcc1bSBarry Smith `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`, 976420bcc1bSBarry Smith and computing explicitly with 977f6dfbefdSBarry Smith finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object. 97883e2fdc7SBarry Smith 979420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESType`, `SNESSetOptionsPrefix()`, `SNESResetFromOptions()`, `SNES`, `SNESCreate()`, `MatCreateSNESMF()`, `MatFDColoring` 9809b94acceSBarry Smith @*/ 981d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFromOptions(SNES snes) 982d71ae5a4SJacob Faibussowitsch { 9838afaa268SBarry Smith PetscBool flg, pcset, persist, set; 984d8f46077SPeter Brune PetscInt i, indx, lag, grids; 98504d7464bSBarry Smith const char *deft = SNESNEWTONLS; 986649ef022SMatthew Knepley const char *convtests[] = {"default", "skip", "correct_pressure"}; 98785385478SLisandro Dalcin SNESKSPEW *kctx = NULL; 9880f0abf79SStefano Zampini char type[256], monfilename[PETSC_MAX_PATH_LEN], ewprefix[256]; 989c40d0f55SPeter Brune PCSide pcside; 990a64e098fSPeter Brune const char *optionsprefix; 9919b94acceSBarry Smith 9923a40ed3dSBarry Smith PetscFunctionBegin; 9930700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 9949566063dSJacob Faibussowitsch PetscCall(SNESRegisterAll()); 995d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)snes); 996639ff905SBarry Smith if (((PetscObject)snes)->type_name) deft = ((PetscObject)snes)->type_name; 9979566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-snes_type", "Nonlinear solver method", "SNESSetType", SNESList, deft, type, 256, &flg)); 998d64ed03dSBarry Smith if (flg) { 9999566063dSJacob Faibussowitsch PetscCall(SNESSetType(snes, type)); 10007adad957SLisandro Dalcin } else if (!((PetscObject)snes)->type_name) { 10019566063dSJacob Faibussowitsch PetscCall(SNESSetType(snes, deft)); 1002d64ed03dSBarry Smith } 10039566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-snes_stol", "Stop if step length less than", "SNESSetTolerances", snes->stol, &snes->stol, NULL)); 10049566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-snes_atol", "Stop if function norm less than", "SNESSetTolerances", snes->abstol, &snes->abstol, NULL)); 1005186905e3SBarry Smith 10069566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-snes_rtol", "Stop if decrease in function norm less than", "SNESSetTolerances", snes->rtol, &snes->rtol, NULL)); 10079566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-snes_divergence_tolerance", "Stop if residual norm increases by this factor", "SNESSetDivergenceTolerance", snes->divtol, &snes->divtol, NULL)); 10089566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_max_it", "Maximum iterations", "SNESSetTolerances", snes->max_its, &snes->max_its, NULL)); 10099566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_max_funcs", "Maximum function evaluations", "SNESSetTolerances", snes->max_funcs, &snes->max_funcs, NULL)); 10109566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_max_fail", "Maximum nonlinear step failures", "SNESSetMaxNonlinearStepFailures", snes->maxFailures, &snes->maxFailures, NULL)); 10119566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_max_linear_solve_fail", "Maximum failures in linear solves allowed", "SNESSetMaxLinearSolveFailures", snes->maxLinearSolveFailures, &snes->maxLinearSolveFailures, NULL)); 10129566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_error_if_not_converged", "Generate error if solver does not converge", "SNESSetErrorIfNotConverged", snes->errorifnotconverged, &snes->errorifnotconverged, NULL)); 10139566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_force_iteration", "Force SNESSolve() to take at least one iteration", "SNESSetForceIteration", snes->forceiteration, &snes->forceiteration, NULL)); 10149566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_check_jacobian_domain_error", "Check Jacobian domain error after Jacobian evaluation", "SNESCheckJacobianDomainError", snes->checkjacdomainerror, &snes->checkjacdomainerror, NULL)); 101585385478SLisandro Dalcin 10169566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_lag_preconditioner", "How often to rebuild preconditioner", "SNESSetLagPreconditioner", snes->lagpreconditioner, &lag, &flg)); 1017a8054027SBarry Smith if (flg) { 10185f80ce2aSJacob 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"); 10199566063dSJacob Faibussowitsch PetscCall(SNESSetLagPreconditioner(snes, lag)); 1020a8054027SBarry Smith } 10219566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_lag_preconditioner_persists", "Preconditioner lagging through multiple SNES solves", "SNESSetLagPreconditionerPersists", snes->lagjac_persist, &persist, &flg)); 10221baa6e33SBarry Smith if (flg) PetscCall(SNESSetLagPreconditionerPersists(snes, persist)); 10239566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_lag_jacobian", "How often to rebuild Jacobian", "SNESSetLagJacobian", snes->lagjacobian, &lag, &flg)); 1024e35cf81dSBarry Smith if (flg) { 10255f80ce2aSJacob Faibussowitsch PetscCheck(lag != -1, PetscObjectComm((PetscObject)snes), PETSC_ERR_USER, "Cannot set the lag to -1 from the command line since the Jacobian must be built as least once, perhaps you mean -2"); 10269566063dSJacob Faibussowitsch PetscCall(SNESSetLagJacobian(snes, lag)); 1027e35cf81dSBarry Smith } 10289566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_lag_jacobian_persists", "Jacobian lagging through multiple SNES solves", "SNESSetLagJacobianPersists", snes->lagjac_persist, &persist, &flg)); 10291baa6e33SBarry Smith if (flg) PetscCall(SNESSetLagJacobianPersists(snes, persist)); 103037ec4e1aSPeter Brune 10319566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_grid_sequence", "Use grid sequencing to generate initial guess", "SNESSetGridSequence", snes->gridsequence, &grids, &flg)); 10321baa6e33SBarry Smith if (flg) PetscCall(SNESSetGridSequence(snes, grids)); 1033a8054027SBarry Smith 1034400f6f02SBarry Smith PetscCall(PetscOptionsEList("-snes_convergence_test", "Convergence test", "SNESSetConvergenceTest", convtests, PETSC_STATIC_ARRAY_LENGTH(convtests), "default", &indx, &flg)); 103585385478SLisandro Dalcin if (flg) { 103685385478SLisandro Dalcin switch (indx) { 1037d71ae5a4SJacob Faibussowitsch case 0: 1038d71ae5a4SJacob Faibussowitsch PetscCall(SNESSetConvergenceTest(snes, SNESConvergedDefault, NULL, NULL)); 1039d71ae5a4SJacob Faibussowitsch break; 1040d71ae5a4SJacob Faibussowitsch case 1: 1041d71ae5a4SJacob Faibussowitsch PetscCall(SNESSetConvergenceTest(snes, SNESConvergedSkip, NULL, NULL)); 1042d71ae5a4SJacob Faibussowitsch break; 1043d71ae5a4SJacob Faibussowitsch case 2: 1044d71ae5a4SJacob Faibussowitsch PetscCall(SNESSetConvergenceTest(snes, SNESConvergedCorrectPressure, NULL, NULL)); 1045d71ae5a4SJacob Faibussowitsch break; 104685385478SLisandro Dalcin } 104785385478SLisandro Dalcin } 104885385478SLisandro Dalcin 10499566063dSJacob Faibussowitsch PetscCall(PetscOptionsEList("-snes_norm_schedule", "SNES Norm schedule", "SNESSetNormSchedule", SNESNormSchedules, 5, "function", &indx, &flg)); 10509566063dSJacob Faibussowitsch if (flg) PetscCall(SNESSetNormSchedule(snes, (SNESNormSchedule)indx)); 1051fdacfa88SPeter Brune 10529566063dSJacob Faibussowitsch PetscCall(PetscOptionsEList("-snes_function_type", "SNES Norm schedule", "SNESSetFunctionType", SNESFunctionTypes, 2, "unpreconditioned", &indx, &flg)); 10539566063dSJacob Faibussowitsch if (flg) PetscCall(SNESSetFunctionType(snes, (SNESFunctionType)indx)); 1054186905e3SBarry Smith 105585385478SLisandro Dalcin kctx = (SNESKSPEW *)snes->kspconvctx; 105685385478SLisandro Dalcin 10579566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_ksp_ew", "Use Eisentat-Walker linear system convergence test", "SNESKSPSetUseEW", snes->ksp_ewconv, &snes->ksp_ewconv, NULL)); 1058186905e3SBarry Smith 10590f0abf79SStefano Zampini PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 10600f0abf79SStefano Zampini PetscCall(PetscSNPrintf(ewprefix, sizeof(ewprefix), "%s%s", optionsprefix ? optionsprefix : "", "snes_")); 1061a4598233SStefano Zampini PetscCall(SNESEWSetFromOptions_Private(kctx, PETSC_TRUE, PetscObjectComm((PetscObject)snes), ewprefix)); 1062186905e3SBarry Smith 106390d69ab7SBarry Smith flg = PETSC_FALSE; 10649566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_monitor_cancel", "Remove all monitors", "SNESMonitorCancel", flg, &flg, &set)); 10659566063dSJacob Faibussowitsch if (set && flg) PetscCall(SNESMonitorCancel(snes)); 1066eabae89aSBarry Smith 10679566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor", "Monitor norm of function", "SNESMonitorDefault", SNESMonitorDefault, SNESMonitorDefaultSetUp)); 10689566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_short", "Monitor norm of function with fewer digits", "SNESMonitorDefaultShort", SNESMonitorDefaultShort, NULL)); 10699566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_range", "Monitor range of elements of function", "SNESMonitorRange", SNESMonitorRange, NULL)); 1070eabae89aSBarry Smith 10719566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_ratio", "Monitor ratios of the norm of function for consecutive steps", "SNESMonitorRatio", SNESMonitorRatio, SNESMonitorRatioSetUp)); 10729566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_field", "Monitor norm of function (split into fields)", "SNESMonitorDefaultField", SNESMonitorDefaultField, NULL)); 10739566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution", "View solution at each iteration", "SNESMonitorSolution", SNESMonitorSolution, NULL)); 10749566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution_update", "View correction at each iteration", "SNESMonitorSolutionUpdate", SNESMonitorSolutionUpdate, NULL)); 10759566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_residual", "View residual at each iteration", "SNESMonitorResidual", SNESMonitorResidual, NULL)); 10769566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_jacupdate_spectrum", "Print the change in the spectrum of the Jacobian", "SNESMonitorJacUpdateSpectrum", SNESMonitorJacUpdateSpectrum, NULL)); 10779566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_fields", "Monitor norm of function per field", "SNESMonitorSet", SNESMonitorFields, NULL)); 10789566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_monitor_pause_final", "Pauses all draw monitors at the final iterate", "SNESMonitorPauseFinal_Internal", PETSC_FALSE, &snes->pauseFinal, NULL)); 10792db13446SMatthew G. Knepley 10809566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-snes_monitor_python", "Use Python function", "SNESMonitorSet", NULL, monfilename, sizeof(monfilename), &flg)); 10819566063dSJacob Faibussowitsch if (flg) PetscCall(PetscPythonMonitorSet((PetscObject)snes, monfilename)); 10825180491cSLisandro Dalcin 108390d69ab7SBarry Smith flg = PETSC_FALSE; 10849566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_monitor_lg_range", "Plot function range at each iteration", "SNESMonitorLGRange", flg, &flg, NULL)); 1085459f5d12SBarry Smith if (flg) { 1086459f5d12SBarry Smith PetscViewer ctx; 1087e24b481bSBarry Smith 10889566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &ctx)); 10899566063dSJacob Faibussowitsch PetscCall(SNESMonitorSet(snes, SNESMonitorLGRange, ctx, (PetscErrorCode(*)(void **))PetscViewerDestroy)); 1090459f5d12SBarry Smith } 10912e7541e6SPeter Brune 109290d69ab7SBarry Smith flg = PETSC_FALSE; 10939566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_converged_reason_view_cancel", "Remove all converged reason viewers", "SNESConvergedReasonViewCancel", flg, &flg, &set)); 10949566063dSJacob Faibussowitsch if (set && flg) PetscCall(SNESConvergedReasonViewCancel(snes)); 1095c4421ceaSFande Kong 1096c4421ceaSFande Kong flg = PETSC_FALSE; 10979566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_fd", "Use finite differences (slow) to compute Jacobian", "SNESComputeJacobianDefault", flg, &flg, NULL)); 10984b27c08aSLois Curfman McInnes if (flg) { 10996cab3a1bSJed Brown void *functx; 1100b1f624c7SBarry Smith DM dm; 11019566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 1102800f99ffSJeremy L Thompson PetscCall(DMSNESUnsetJacobianContext_Internal(dm)); 11039566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, NULL, &functx)); 11049566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefault, functx)); 11059566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Setting default finite difference Jacobian matrix\n")); 11069b94acceSBarry Smith } 1107639f9d9dSBarry Smith 110844848bc4SPeter Brune flg = PETSC_FALSE; 11099566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_fd_function", "Use finite differences (slow) to compute function from user objective", "SNESObjectiveComputeFunctionDefaultFD", flg, &flg, NULL)); 11101baa6e33SBarry Smith if (flg) PetscCall(SNESSetFunction(snes, NULL, SNESObjectiveComputeFunctionDefaultFD, NULL)); 111197584545SPeter Brune 111297584545SPeter Brune flg = PETSC_FALSE; 11139566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_fd_color", "Use finite differences with coloring to compute Jacobian", "SNESComputeJacobianDefaultColor", flg, &flg, NULL)); 111444848bc4SPeter Brune if (flg) { 1115c52e227fSPeter Brune DM dm; 11169566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 1117800f99ffSJeremy L Thompson PetscCall(DMSNESUnsetJacobianContext_Internal(dm)); 11189566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefaultColor, NULL)); 11199566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Setting default finite difference coloring Jacobian matrix\n")); 112044848bc4SPeter Brune } 112144848bc4SPeter Brune 1122aa3661deSLisandro Dalcin flg = PETSC_FALSE; 11239566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_mf_operator", "Use a Matrix-Free Jacobian with user-provided preconditioner matrix", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf_operator, &flg)); 1124d8f46077SPeter Brune if (flg && snes->mf_operator) { 1125a8248277SBarry Smith snes->mf_operator = PETSC_TRUE; 1126d8f46077SPeter Brune snes->mf = PETSC_TRUE; 1127a8248277SBarry Smith } 1128aa3661deSLisandro Dalcin flg = PETSC_FALSE; 11299566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_mf", "Use a Matrix-Free Jacobian with no preconditioner matrix", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf, &flg)); 1130d8f46077SPeter Brune if (!flg && snes->mf_operator) snes->mf = PETSC_TRUE; 11319566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_mf_version", "Matrix-Free routines version 1 or 2", "None", snes->mf_version, &snes->mf_version, NULL)); 1132d28543b3SPeter Brune 1133c40d0f55SPeter Brune flg = PETSC_FALSE; 11349566063dSJacob Faibussowitsch PetscCall(SNESGetNPCSide(snes, &pcside)); 11359566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-snes_npc_side", "SNES nonlinear preconditioner side", "SNESSetNPCSide", PCSides, (PetscEnum)pcside, (PetscEnum *)&pcside, &flg)); 11369566063dSJacob Faibussowitsch if (flg) PetscCall(SNESSetNPCSide(snes, pcside)); 1137c40d0f55SPeter Brune 1138e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS) 11398a70d858SHong Zhang /* 11408a70d858SHong Zhang Publish convergence information using SAWs 11418a70d858SHong Zhang */ 11428a70d858SHong Zhang flg = PETSC_FALSE; 11439566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_monitor_saws", "Publish SNES progress using SAWs", "SNESMonitorSet", flg, &flg, NULL)); 11448a70d858SHong Zhang if (flg) { 11458a70d858SHong Zhang void *ctx; 11469566063dSJacob Faibussowitsch PetscCall(SNESMonitorSAWsCreate(snes, &ctx)); 11479566063dSJacob Faibussowitsch PetscCall(SNESMonitorSet(snes, SNESMonitorSAWs, ctx, SNESMonitorSAWsDestroy)); 11488a70d858SHong Zhang } 11498a70d858SHong Zhang #endif 11508a70d858SHong Zhang #if defined(PETSC_HAVE_SAWS) 1151b90c6cbeSBarry Smith { 1152b90c6cbeSBarry Smith PetscBool set; 1153b90c6cbeSBarry Smith flg = PETSC_FALSE; 11549566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_saws_block", "Block for SAWs at end of SNESSolve", "PetscObjectSAWsBlock", ((PetscObject)snes)->amspublishblock, &flg, &set)); 11551baa6e33SBarry Smith if (set) PetscCall(PetscObjectSAWsSetBlock((PetscObject)snes, flg)); 1156b90c6cbeSBarry Smith } 1157b90c6cbeSBarry Smith #endif 1158b90c6cbeSBarry Smith 115948a46eb9SPierre Jolivet for (i = 0; i < numberofsetfromoptions; i++) PetscCall((*othersetfromoptions[i])(snes)); 116076b2cf59SMatthew Knepley 1161dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, setfromoptions, PetscOptionsObject); 11625d973c19SBarry Smith 11635d973c19SBarry Smith /* process any options handlers added with PetscObjectAddOptionsHandler() */ 1164dbbe0bcdSBarry Smith PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)snes, PetscOptionsObject)); 1165d0609cedSBarry Smith PetscOptionsEnd(); 11664bbc92c1SBarry Smith 1167d8d34be6SBarry Smith if (snes->linesearch) { 11689566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 11699566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetFromOptions(snes->linesearch)); 1170d8d34be6SBarry Smith } 11719e764e56SPeter Brune 11726aa5e7e9SBarry Smith if (snes->usesksp) { 11739566063dSJacob Faibussowitsch if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 11749566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(snes->ksp, snes->jacobian, snes->jacobian_pre)); 11759566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(snes->ksp)); 11766aa5e7e9SBarry Smith } 11776991f827SBarry Smith 1178b5badacbSBarry Smith /* if user has set the SNES NPC type via options database, create it. */ 11799566063dSJacob Faibussowitsch PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 11809566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)snes)->options, optionsprefix, "-npc_snes_type", &pcset)); 118148a46eb9SPierre Jolivet if (pcset && (!snes->npc)) PetscCall(SNESGetNPC(snes, &snes->npc)); 11821baa6e33SBarry Smith if (snes->npc) PetscCall(SNESSetFromOptions(snes->npc)); 1183b3cd9a81SMatthew G. Knepley snes->setfromoptionscalled++; 11843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1185b3cd9a81SMatthew G. Knepley } 1186b3cd9a81SMatthew G. Knepley 1187b3cd9a81SMatthew G. Knepley /*@ 1188420bcc1bSBarry Smith SNESResetFromOptions - Sets various `SNES` and `KSP` parameters from user options ONLY if the `SNESSetFromOptions()` was previously called 1189b3cd9a81SMatthew G. Knepley 1190c3339decSBarry Smith Collective 1191b3cd9a81SMatthew G. Knepley 1192b3cd9a81SMatthew G. Knepley Input Parameter: 1193f6dfbefdSBarry Smith . snes - the `SNES` context 1194b3cd9a81SMatthew G. Knepley 1195420bcc1bSBarry Smith Level: advanced 1196b3cd9a81SMatthew G. Knepley 11971cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESSetOptionsPrefix()` 1198b3cd9a81SMatthew G. Knepley @*/ 1199d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESResetFromOptions(SNES snes) 1200d71ae5a4SJacob Faibussowitsch { 1201b3cd9a81SMatthew G. Knepley PetscFunctionBegin; 12029566063dSJacob Faibussowitsch if (snes->setfromoptionscalled) PetscCall(SNESSetFromOptions(snes)); 12033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12049b94acceSBarry Smith } 12059b94acceSBarry Smith 1206bb9467b5SJed Brown /*@C 1207d25893d9SBarry Smith SNESSetComputeApplicationContext - Sets an optional function to compute a user-defined context for 1208d25893d9SBarry Smith the nonlinear solvers. 1209d25893d9SBarry Smith 1210dc4c0fb0SBarry Smith Logically Collective; No Fortran Support 1211d25893d9SBarry Smith 1212d25893d9SBarry Smith Input Parameters: 1213f6dfbefdSBarry Smith + snes - the `SNES` context 1214d25893d9SBarry Smith . compute - function to compute the context 1215d25893d9SBarry Smith - destroy - function to destroy the context 1216d25893d9SBarry Smith 1217420bcc1bSBarry Smith Calling sequence of `compute`: 1218420bcc1bSBarry Smith + snes - the `SNES` context 1219420bcc1bSBarry Smith - ctx - context to be computed 1220420bcc1bSBarry Smith 1221420bcc1bSBarry Smith Calling sequence of `destroy`: 1222420bcc1bSBarry Smith . ctx - context to be computed by `compute()` 1223420bcc1bSBarry Smith 1224d25893d9SBarry Smith Level: intermediate 1225d25893d9SBarry Smith 1226f6dfbefdSBarry Smith Note: 1227f6dfbefdSBarry Smith This routine is useful if you are performing grid sequencing or using `SNESFAS` and need the appropriate context generated for each level. 1228f6dfbefdSBarry Smith 1229f6dfbefdSBarry Smith Use `SNESSetApplicationContext()` to see the context immediately 1230f6dfbefdSBarry Smith 123142747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNESGetApplicationContext()`, `SNESSetApplicationContext()` 1232d25893d9SBarry Smith @*/ 1233420bcc1bSBarry Smith PetscErrorCode SNESSetComputeApplicationContext(SNES snes, PetscErrorCode (*compute)(SNES snes, void **ctx), PetscErrorCode (*destroy)(void **ctx)) 1234d71ae5a4SJacob Faibussowitsch { 1235d25893d9SBarry Smith PetscFunctionBegin; 1236d25893d9SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1237d25893d9SBarry Smith snes->ops->usercompute = compute; 1238d25893d9SBarry Smith snes->ops->userdestroy = destroy; 12393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1240d25893d9SBarry Smith } 1241a847f771SSatish Balay 1242b07ff414SBarry Smith /*@ 1243f6dfbefdSBarry Smith SNESSetApplicationContext - Sets the optional user-defined context for the nonlinear solvers. 12449b94acceSBarry Smith 1245c3339decSBarry Smith Logically Collective 1246fee21e36SBarry Smith 1247c7afd0dbSLois Curfman McInnes Input Parameters: 1248f6dfbefdSBarry Smith + snes - the `SNES` context 1249c7afd0dbSLois Curfman McInnes - usrP - optional user context 1250c7afd0dbSLois Curfman McInnes 125136851e7fSLois Curfman McInnes Level: intermediate 125236851e7fSLois Curfman McInnes 1253f6dfbefdSBarry Smith Notes: 1254f6dfbefdSBarry Smith Users can provide a context when constructing the `SNES` options and then access it inside their function, Jacobian, or other evaluation function 1255f6dfbefdSBarry Smith with `SNESGetApplicationContext()` 1256f6dfbefdSBarry Smith 1257f6dfbefdSBarry Smith To provide a function that computes the context for you use `SNESSetComputeApplicationContext()` 1258f6dfbefdSBarry Smith 1259420bcc1bSBarry Smith Fortran Note: 1260dc4c0fb0SBarry Smith You must write a Fortran interface definition for this 1261420bcc1bSBarry Smith function that tells Fortran the Fortran derived data type that you are passing in as the `usrP` argument. 1262daf670e6SBarry Smith 12631cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetComputeApplicationContext()`, `SNESGetApplicationContext()` 12649b94acceSBarry Smith @*/ 1265d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetApplicationContext(SNES snes, void *usrP) 1266d71ae5a4SJacob Faibussowitsch { 1267b07ff414SBarry Smith KSP ksp; 12681b2093e4SBarry Smith 12693a40ed3dSBarry Smith PetscFunctionBegin; 12700700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 12719566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 12729566063dSJacob Faibussowitsch PetscCall(KSPSetApplicationContext(ksp, usrP)); 12739b94acceSBarry Smith snes->user = usrP; 12743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12759b94acceSBarry Smith } 127674679c65SBarry Smith 1277b07ff414SBarry Smith /*@ 12789b94acceSBarry Smith SNESGetApplicationContext - Gets the user-defined context for the 1279420bcc1bSBarry Smith nonlinear solvers set with `SNESGetApplicationContext()` or `SNESSetComputeApplicationContext()` 12809b94acceSBarry Smith 1281c7afd0dbSLois Curfman McInnes Not Collective 1282c7afd0dbSLois Curfman McInnes 12839b94acceSBarry Smith Input Parameter: 1284f6dfbefdSBarry Smith . snes - `SNES` context 12859b94acceSBarry Smith 12869b94acceSBarry Smith Output Parameter: 12879b94acceSBarry Smith . usrP - user context 12889b94acceSBarry Smith 128936851e7fSLois Curfman McInnes Level: intermediate 129036851e7fSLois Curfman McInnes 1291420bcc1bSBarry Smith Fortran Note: 1292dc4c0fb0SBarry Smith You must write a Fortran interface definition for this 1293420bcc1bSBarry Smith function that tells Fortran the Fortran derived data type that you are passing in as the `usrP` argument. 1294dc4c0fb0SBarry Smith 1295420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESSetApplicationContext()`, `SNESSetComputeApplicationContext()` 12969b94acceSBarry Smith @*/ 1297d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetApplicationContext(SNES snes, void *usrP) 1298d71ae5a4SJacob Faibussowitsch { 12993a40ed3dSBarry Smith PetscFunctionBegin; 13000700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1301e71120c6SJed Brown *(void **)usrP = snes->user; 13023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13039b94acceSBarry Smith } 130474679c65SBarry Smith 13059b94acceSBarry Smith /*@ 1306420bcc1bSBarry Smith SNESSetUseMatrixFree - indicates that `SNES` should use matrix-free finite difference matrix-vector products to apply the Jacobian. 13073565c898SBarry Smith 1308dc4c0fb0SBarry Smith Logically Collective 13093565c898SBarry Smith 13103565c898SBarry Smith Input Parameters: 1311f6dfbefdSBarry Smith + snes - `SNES` context 1312f6dfbefdSBarry Smith . mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used 1313f6dfbefdSBarry 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 1314420bcc1bSBarry Smith this option no matrix-element based preconditioners can be used in the linear solve since the matrix won't be explicitly available 13153565c898SBarry Smith 1316f6dfbefdSBarry Smith Options Database Keys: 131701c1178eSBarry Smith + -snes_mf_operator - use matrix-free only for the mat operator 1318f6dfbefdSBarry Smith . -snes_mf - use matrix-free for both the mat and pmat operator 1319ec5066bdSBarry Smith . -snes_fd_color - compute the Jacobian via coloring and finite differences. 1320ec5066bdSBarry Smith - -snes_fd - compute the Jacobian via finite differences (slow) 13213565c898SBarry Smith 13223565c898SBarry Smith Level: intermediate 13233565c898SBarry Smith 1324f6dfbefdSBarry Smith Note: 1325420bcc1bSBarry Smith `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`, 1326420bcc1bSBarry Smith and computing explicitly with 1327f6dfbefdSBarry Smith finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object. 1328ec5066bdSBarry Smith 1329420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetUseMatrixFree()`, `MatCreateSNESMF()`, `SNESComputeJacobianDefaultColor()`, `MatFDColoring` 13303565c898SBarry Smith @*/ 1331d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUseMatrixFree(SNES snes, PetscBool mf_operator, PetscBool mf) 1332d71ae5a4SJacob Faibussowitsch { 13333565c898SBarry Smith PetscFunctionBegin; 13343565c898SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 133588b4c220SStefano Zampini PetscValidLogicalCollectiveBool(snes, mf_operator, 2); 133688b4c220SStefano Zampini PetscValidLogicalCollectiveBool(snes, mf, 3); 13374ddffce6SLisandro Dalcin snes->mf = mf_operator ? PETSC_TRUE : mf; 13383565c898SBarry Smith snes->mf_operator = mf_operator; 13393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13403565c898SBarry Smith } 13413565c898SBarry Smith 13423565c898SBarry Smith /*@ 1343dc4c0fb0SBarry Smith SNESGetUseMatrixFree - indicates if the `SNES` uses matrix-free finite difference matrix vector products to apply the Jacobian. 13443565c898SBarry Smith 1345420bcc1bSBarry Smith Not Collective, but the resulting flags will be the same on all MPI processes 13463565c898SBarry Smith 13473565c898SBarry Smith Input Parameter: 1348f6dfbefdSBarry Smith . snes - `SNES` context 13493565c898SBarry Smith 13503565c898SBarry Smith Output Parameters: 1351f6dfbefdSBarry Smith + mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used 1352f6dfbefdSBarry 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 13533565c898SBarry Smith 13543565c898SBarry Smith Level: intermediate 13553565c898SBarry Smith 13561cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUseMatrixFree()`, `MatCreateSNESMF()` 13573565c898SBarry Smith @*/ 1358d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUseMatrixFree(SNES snes, PetscBool *mf_operator, PetscBool *mf) 1359d71ae5a4SJacob Faibussowitsch { 13603565c898SBarry Smith PetscFunctionBegin; 13613565c898SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 13623565c898SBarry Smith if (mf) *mf = snes->mf; 13633565c898SBarry Smith if (mf_operator) *mf_operator = snes->mf_operator; 13643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13653565c898SBarry Smith } 13663565c898SBarry Smith 13673565c898SBarry Smith /*@ 1368420bcc1bSBarry Smith SNESGetIterationNumber - Gets the number of nonlinear iterations completed in the current or most recent `SNESSolve()` 13699b94acceSBarry Smith 1370c7afd0dbSLois Curfman McInnes Not Collective 1371c7afd0dbSLois Curfman McInnes 13729b94acceSBarry Smith Input Parameter: 1373f6dfbefdSBarry Smith . snes - `SNES` context 13749b94acceSBarry Smith 13759b94acceSBarry Smith Output Parameter: 13769b94acceSBarry Smith . iter - iteration number 13779b94acceSBarry Smith 1378dc4c0fb0SBarry Smith Level: intermediate 1379dc4c0fb0SBarry Smith 1380c8228a4eSBarry Smith Notes: 1381c8228a4eSBarry Smith For example, during the computation of iteration 2 this would return 1. 1382c8228a4eSBarry Smith 1383c8228a4eSBarry Smith This is useful for using lagged Jacobians (where one does not recompute the 1384f6dfbefdSBarry Smith Jacobian at each `SNES` iteration). For example, the code 138508405cd6SLois Curfman McInnes .vb 138608405cd6SLois Curfman McInnes ierr = SNESGetIterationNumber(snes,&it); 138708405cd6SLois Curfman McInnes if (!(it % 2)) { 138808405cd6SLois Curfman McInnes [compute Jacobian here] 138908405cd6SLois Curfman McInnes } 139008405cd6SLois Curfman McInnes .ve 1391f6dfbefdSBarry Smith can be used in your function that computes the Jacobian to cause the Jacobian to be 1392f6dfbefdSBarry Smith recomputed every second `SNES` iteration. See also `SNESSetLagJacobian()` 1393c8228a4eSBarry Smith 1394f6dfbefdSBarry Smith After the `SNES` solve is complete this will return the number of nonlinear iterations used. 1395c04deec6SBarry Smith 1396420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetLagJacobian()`, `SNESGetLinearSolveIterations()`, `SNESSetMonitor()` 13979b94acceSBarry Smith @*/ 1398d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetIterationNumber(SNES snes, PetscInt *iter) 1399d71ae5a4SJacob Faibussowitsch { 14003a40ed3dSBarry Smith PetscFunctionBegin; 14010700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 14024f572ea9SToby Isaac PetscAssertPointer(iter, 2); 14039b94acceSBarry Smith *iter = snes->iter; 14043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14059b94acceSBarry Smith } 140674679c65SBarry Smith 1407360c497dSPeter Brune /*@ 1408360c497dSPeter Brune SNESSetIterationNumber - Sets the current iteration number. 1409360c497dSPeter Brune 1410360c497dSPeter Brune Not Collective 1411360c497dSPeter Brune 1412d8d19677SJose E. Roman Input Parameters: 1413f6dfbefdSBarry Smith + snes - `SNES` context 1414a2b725a8SWilliam Gropp - iter - iteration number 1415360c497dSPeter Brune 1416360c497dSPeter Brune Level: developer 1417360c497dSPeter Brune 1418420bcc1bSBarry Smith Note: 1419420bcc1bSBarry Smith This should only be called inside a `SNES` nonlinear solver. 1420420bcc1bSBarry Smith 14211cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetLinearSolveIterations()` 1422360c497dSPeter Brune @*/ 1423d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetIterationNumber(SNES snes, PetscInt iter) 1424d71ae5a4SJacob Faibussowitsch { 1425360c497dSPeter Brune PetscFunctionBegin; 1426360c497dSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 14279566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes)); 1428360c497dSPeter Brune snes->iter = iter; 14299566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes)); 14303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1431360c497dSPeter Brune } 1432360c497dSPeter Brune 14339b94acceSBarry Smith /*@ 1434b850b91aSLisandro Dalcin SNESGetNonlinearStepFailures - Gets the number of unsuccessful steps 1435420bcc1bSBarry Smith attempted by the nonlinear solver in the current or most recent `SNESSolve()` . 14369b94acceSBarry Smith 1437c7afd0dbSLois Curfman McInnes Not Collective 1438c7afd0dbSLois Curfman McInnes 14399b94acceSBarry Smith Input Parameter: 1440f6dfbefdSBarry Smith . snes - `SNES` context 14419b94acceSBarry Smith 14429b94acceSBarry Smith Output Parameter: 14439b94acceSBarry Smith . nfails - number of unsuccessful steps attempted 14449b94acceSBarry Smith 1445dc4c0fb0SBarry Smith Level: intermediate 1446dc4c0fb0SBarry Smith 1447f6dfbefdSBarry Smith Note: 1448f6dfbefdSBarry Smith This counter is reset to zero for each successive call to `SNESSolve()`. 1449c96a6f78SLois Curfman McInnes 14501cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, 1451db781477SPatrick Sanan `SNESSetMaxNonlinearStepFailures()`, `SNESGetMaxNonlinearStepFailures()` 14529b94acceSBarry Smith @*/ 1453d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNonlinearStepFailures(SNES snes, PetscInt *nfails) 1454d71ae5a4SJacob Faibussowitsch { 14553a40ed3dSBarry Smith PetscFunctionBegin; 14560700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 14574f572ea9SToby Isaac PetscAssertPointer(nfails, 2); 145850ffb88aSMatthew Knepley *nfails = snes->numFailures; 14593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 146050ffb88aSMatthew Knepley } 146150ffb88aSMatthew Knepley 146250ffb88aSMatthew Knepley /*@ 1463b850b91aSLisandro Dalcin SNESSetMaxNonlinearStepFailures - Sets the maximum number of unsuccessful steps 1464420bcc1bSBarry Smith attempted by the nonlinear solver before it gives up and returns unconverged or generates an error 146550ffb88aSMatthew Knepley 146650ffb88aSMatthew Knepley Not Collective 146750ffb88aSMatthew Knepley 146850ffb88aSMatthew Knepley Input Parameters: 1469f6dfbefdSBarry Smith + snes - `SNES` context 147050ffb88aSMatthew Knepley - maxFails - maximum of unsuccessful steps 147150ffb88aSMatthew Knepley 1472420bcc1bSBarry Smith Options Database Key: 1473420bcc1bSBarry Smith . -snes_max_fail <n> - maximum number of unsuccessful steps allowed 1474420bcc1bSBarry Smith 147550ffb88aSMatthew Knepley Level: intermediate 147650ffb88aSMatthew Knepley 1477420bcc1bSBarry Smith Developer Note: 1478420bcc1bSBarry Smith The options database key is wrong for this function name 1479420bcc1bSBarry Smith 14801cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, 1481db781477SPatrick Sanan `SNESGetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()` 148250ffb88aSMatthew Knepley @*/ 1483d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxNonlinearStepFailures(SNES snes, PetscInt maxFails) 1484d71ae5a4SJacob Faibussowitsch { 148550ffb88aSMatthew Knepley PetscFunctionBegin; 14860700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 148750ffb88aSMatthew Knepley snes->maxFailures = maxFails; 14883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 148950ffb88aSMatthew Knepley } 149050ffb88aSMatthew Knepley 149150ffb88aSMatthew Knepley /*@ 1492b850b91aSLisandro Dalcin SNESGetMaxNonlinearStepFailures - Gets the maximum number of unsuccessful steps 1493420bcc1bSBarry Smith attempted by the nonlinear solver before it gives up and returns unconverged or generates an error 149450ffb88aSMatthew Knepley 149550ffb88aSMatthew Knepley Not Collective 149650ffb88aSMatthew Knepley 149750ffb88aSMatthew Knepley Input Parameter: 149820f4b53cSBarry Smith . snes - `SNES` context 149950ffb88aSMatthew Knepley 150050ffb88aSMatthew Knepley Output Parameter: 150150ffb88aSMatthew Knepley . maxFails - maximum of unsuccessful steps 150250ffb88aSMatthew Knepley 150350ffb88aSMatthew Knepley Level: intermediate 150450ffb88aSMatthew Knepley 15051cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, 1506db781477SPatrick Sanan `SNESSetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()` 150750ffb88aSMatthew Knepley @*/ 1508d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxNonlinearStepFailures(SNES snes, PetscInt *maxFails) 1509d71ae5a4SJacob Faibussowitsch { 151050ffb88aSMatthew Knepley PetscFunctionBegin; 15110700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 15124f572ea9SToby Isaac PetscAssertPointer(maxFails, 2); 151350ffb88aSMatthew Knepley *maxFails = snes->maxFailures; 15143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15159b94acceSBarry Smith } 1516a847f771SSatish Balay 15172541af92SBarry Smith /*@ 15182541af92SBarry Smith SNESGetNumberFunctionEvals - Gets the number of user provided function evaluations 1519420bcc1bSBarry Smith done by the `SNES` object in the current or most recent `SNESSolve()` 15202541af92SBarry Smith 15212541af92SBarry Smith Not Collective 15222541af92SBarry Smith 15232541af92SBarry Smith Input Parameter: 1524f6dfbefdSBarry Smith . snes - `SNES` context 15252541af92SBarry Smith 15262541af92SBarry Smith Output Parameter: 15272541af92SBarry Smith . nfuncs - number of evaluations 15282541af92SBarry Smith 15292541af92SBarry Smith Level: intermediate 15302541af92SBarry Smith 1531f6dfbefdSBarry Smith Note: 1532f6dfbefdSBarry Smith Reset every time `SNESSolve()` is called unless `SNESSetCountersReset()` is used. 1533971e163fSPeter Brune 15341cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, `SNESSetCountersReset()` 15352541af92SBarry Smith @*/ 1536d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNumberFunctionEvals(SNES snes, PetscInt *nfuncs) 1537d71ae5a4SJacob Faibussowitsch { 15382541af92SBarry Smith PetscFunctionBegin; 15390700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 15404f572ea9SToby Isaac PetscAssertPointer(nfuncs, 2); 15412541af92SBarry Smith *nfuncs = snes->nfuncs; 15423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15432541af92SBarry Smith } 15442541af92SBarry Smith 15453d4c4710SBarry Smith /*@ 15463d4c4710SBarry Smith SNESGetLinearSolveFailures - Gets the number of failed (non-converged) 1547420bcc1bSBarry Smith linear solvers in the current or most recent `SNESSolve()` 15483d4c4710SBarry Smith 15493d4c4710SBarry Smith Not Collective 15503d4c4710SBarry Smith 15513d4c4710SBarry Smith Input Parameter: 1552f6dfbefdSBarry Smith . snes - `SNES` context 15533d4c4710SBarry Smith 15543d4c4710SBarry Smith Output Parameter: 15553d4c4710SBarry Smith . nfails - number of failed solves 15563d4c4710SBarry Smith 1557f6dfbefdSBarry Smith Options Database Key: 15589d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated 15599d85da0cSMatthew G. Knepley 1560f6dfbefdSBarry Smith Level: intermediate 1561f6dfbefdSBarry Smith 1562f6dfbefdSBarry Smith Note: 1563f6dfbefdSBarry Smith This counter is reset to zero for each successive call to `SNESSolve()`. 15643d4c4710SBarry Smith 15651cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()` 15663d4c4710SBarry Smith @*/ 1567d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveFailures(SNES snes, PetscInt *nfails) 1568d71ae5a4SJacob Faibussowitsch { 15693d4c4710SBarry Smith PetscFunctionBegin; 15700700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 15714f572ea9SToby Isaac PetscAssertPointer(nfails, 2); 15723d4c4710SBarry Smith *nfails = snes->numLinearSolveFailures; 15733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15743d4c4710SBarry Smith } 15753d4c4710SBarry Smith 15763d4c4710SBarry Smith /*@ 15773d4c4710SBarry Smith SNESSetMaxLinearSolveFailures - the number of failed linear solve attempts 1578f6dfbefdSBarry Smith allowed before `SNES` returns with a diverged reason of `SNES_DIVERGED_LINEAR_SOLVE` 15793d4c4710SBarry Smith 1580c3339decSBarry Smith Logically Collective 15813d4c4710SBarry Smith 15823d4c4710SBarry Smith Input Parameters: 1583f6dfbefdSBarry Smith + snes - `SNES` context 15843d4c4710SBarry Smith - maxFails - maximum allowed linear solve failures 15853d4c4710SBarry Smith 1586f6dfbefdSBarry Smith Options Database Key: 15879d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated 15889d85da0cSMatthew G. Knepley 1589dc4c0fb0SBarry Smith Level: intermediate 1590dc4c0fb0SBarry Smith 1591f6dfbefdSBarry Smith Note: 1592f6dfbefdSBarry Smith By default this is 0; that is `SNES` returns on the first failed linear solve 15933d4c4710SBarry Smith 1594420bcc1bSBarry Smith Developer Note: 1595420bcc1bSBarry Smith The options database key is wrong for this function name 1596420bcc1bSBarry Smith 15971cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()` 15983d4c4710SBarry Smith @*/ 1599d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxLinearSolveFailures(SNES snes, PetscInt maxFails) 1600d71ae5a4SJacob Faibussowitsch { 16013d4c4710SBarry Smith PetscFunctionBegin; 16020700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1603c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, maxFails, 2); 16043d4c4710SBarry Smith snes->maxLinearSolveFailures = maxFails; 16053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16063d4c4710SBarry Smith } 16073d4c4710SBarry Smith 16083d4c4710SBarry Smith /*@ 16093d4c4710SBarry Smith SNESGetMaxLinearSolveFailures - gets the maximum number of linear solve failures that 1610f6dfbefdSBarry Smith are allowed before `SNES` returns as unsuccessful 16113d4c4710SBarry Smith 16123d4c4710SBarry Smith Not Collective 16133d4c4710SBarry Smith 16143d4c4710SBarry Smith Input Parameter: 1615f6dfbefdSBarry Smith . snes - `SNES` context 16163d4c4710SBarry Smith 16173d4c4710SBarry Smith Output Parameter: 16183d4c4710SBarry Smith . maxFails - maximum of unsuccessful solves allowed 16193d4c4710SBarry Smith 16203d4c4710SBarry Smith Level: intermediate 16213d4c4710SBarry Smith 1622f6dfbefdSBarry Smith Note: 1623f6dfbefdSBarry Smith By default this is 1; that is `SNES` returns on the first failed linear solve 16243d4c4710SBarry Smith 16251cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, 16263d4c4710SBarry Smith @*/ 1627d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxLinearSolveFailures(SNES snes, PetscInt *maxFails) 1628d71ae5a4SJacob Faibussowitsch { 16293d4c4710SBarry Smith PetscFunctionBegin; 16300700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 16314f572ea9SToby Isaac PetscAssertPointer(maxFails, 2); 16323d4c4710SBarry Smith *maxFails = snes->maxLinearSolveFailures; 16333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16343d4c4710SBarry Smith } 16353d4c4710SBarry Smith 1636c96a6f78SLois Curfman McInnes /*@ 1637b850b91aSLisandro Dalcin SNESGetLinearSolveIterations - Gets the total number of linear iterations 1638420bcc1bSBarry Smith used by the nonlinear solver in the most recent `SNESSolve()` 1639c96a6f78SLois Curfman McInnes 1640c7afd0dbSLois Curfman McInnes Not Collective 1641c7afd0dbSLois Curfman McInnes 1642c96a6f78SLois Curfman McInnes Input Parameter: 1643f6dfbefdSBarry Smith . snes - `SNES` context 1644c96a6f78SLois Curfman McInnes 1645c96a6f78SLois Curfman McInnes Output Parameter: 1646c96a6f78SLois Curfman McInnes . lits - number of linear iterations 1647c96a6f78SLois Curfman McInnes 1648dc4c0fb0SBarry Smith Level: intermediate 1649dc4c0fb0SBarry Smith 1650c96a6f78SLois Curfman McInnes Notes: 1651f6dfbefdSBarry Smith This counter is reset to zero for each successive call to `SNESSolve()` unless `SNESSetCountersReset()` is used. 1652c96a6f78SLois Curfman McInnes 1653f6dfbefdSBarry 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 1654f6dfbefdSBarry Smith then call `KSPGetIterationNumber()` after the failed solve. 1655010be392SBarry Smith 16561cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetIterationNumber()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESSetCountersReset()` 1657c96a6f78SLois Curfman McInnes @*/ 1658d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveIterations(SNES snes, PetscInt *lits) 1659d71ae5a4SJacob Faibussowitsch { 16603a40ed3dSBarry Smith PetscFunctionBegin; 16610700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 16624f572ea9SToby Isaac PetscAssertPointer(lits, 2); 1663c96a6f78SLois Curfman McInnes *lits = snes->linear_its; 16643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1665c96a6f78SLois Curfman McInnes } 1666c96a6f78SLois Curfman McInnes 1667971e163fSPeter Brune /*@ 1668971e163fSPeter Brune SNESSetCountersReset - Sets whether or not the counters for linear iterations and function evaluations 1669f6dfbefdSBarry Smith are reset every time `SNESSolve()` is called. 1670971e163fSPeter Brune 1671c3339decSBarry Smith Logically Collective 1672971e163fSPeter Brune 1673d8d19677SJose E. Roman Input Parameters: 1674f6dfbefdSBarry Smith + snes - `SNES` context 1675f6dfbefdSBarry Smith - reset - whether to reset the counters or not, defaults to `PETSC_TRUE` 1676971e163fSPeter Brune 1677971e163fSPeter Brune Level: developer 1678971e163fSPeter Brune 16791cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()` 1680971e163fSPeter Brune @*/ 1681d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCountersReset(SNES snes, PetscBool reset) 1682d71ae5a4SJacob Faibussowitsch { 1683971e163fSPeter Brune PetscFunctionBegin; 1684971e163fSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1685971e163fSPeter Brune PetscValidLogicalCollectiveBool(snes, reset, 2); 1686971e163fSPeter Brune snes->counters_reset = reset; 16873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1688971e163fSPeter Brune } 1689971e163fSPeter Brune 16902999313aSBarry Smith /*@ 1691f6dfbefdSBarry Smith SNESSetKSP - Sets a `KSP` context for the `SNES` object to use 16922999313aSBarry Smith 1693420bcc1bSBarry Smith Not Collective, but the `SNES` and `KSP` objects must live on the same `MPI_Comm` 16942999313aSBarry Smith 16952999313aSBarry Smith Input Parameters: 1696f6dfbefdSBarry Smith + snes - the `SNES` context 1697f6dfbefdSBarry Smith - ksp - the `KSP` context 16982999313aSBarry Smith 1699dc4c0fb0SBarry Smith Level: developer 1700dc4c0fb0SBarry Smith 17012999313aSBarry Smith Notes: 1702f6dfbefdSBarry Smith The `SNES` object already has its `KSP` object, you can obtain with `SNESGetKSP()` 17032999313aSBarry Smith so this routine is rarely needed. 17042999313aSBarry Smith 1705f6dfbefdSBarry Smith The `KSP` object that is already in the `SNES` object has its reference count 1706420bcc1bSBarry Smith decreased by one when this is called. 17072999313aSBarry Smith 170842747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `KSP`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()` 17092999313aSBarry Smith @*/ 1710d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetKSP(SNES snes, KSP ksp) 1711d71ae5a4SJacob Faibussowitsch { 17122999313aSBarry Smith PetscFunctionBegin; 17130700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 17140700a824SBarry Smith PetscValidHeaderSpecific(ksp, KSP_CLASSID, 2); 17152999313aSBarry Smith PetscCheckSameComm(snes, 1, ksp, 2); 17169566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)ksp)); 17179566063dSJacob Faibussowitsch if (snes->ksp) PetscCall(PetscObjectDereference((PetscObject)snes->ksp)); 17182999313aSBarry Smith snes->ksp = ksp; 17193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17202999313aSBarry Smith } 17212999313aSBarry Smith 172252baeb72SSatish Balay /*@ 1723dc4c0fb0SBarry Smith SNESCreate - Creates a nonlinear solver context used to manage a set of nonlinear solves 17249b94acceSBarry Smith 1725d083f849SBarry Smith Collective 1726c7afd0dbSLois Curfman McInnes 1727f6dfbefdSBarry Smith Input Parameter: 1728906ed7ccSBarry Smith . comm - MPI communicator 17299b94acceSBarry Smith 17309b94acceSBarry Smith Output Parameter: 173120f4b53cSBarry Smith . outsnes - the new `SNES` context 17329b94acceSBarry Smith 1733c7afd0dbSLois Curfman McInnes Options Database Keys: 1734dc4c0fb0SBarry Smith + -snes_mf - Activates default matrix-free Jacobian-vector products, and no preconditioning matrix 1735dc4c0fb0SBarry Smith . -snes_mf_operator - Activates default matrix-free Jacobian-vector products, and a user-provided preconditioning matrix 1736dc4c0fb0SBarry Smith as set by `SNESSetJacobian()` 1737dc4c0fb0SBarry Smith . -snes_fd_coloring - uses a relative fast computation of the Jacobian using finite differences and a graph coloring 1738c7afd0dbSLois Curfman McInnes - -snes_fd - Uses (slow!) finite differences to compute Jacobian 1739c1f60f51SBarry Smith 174036851e7fSLois Curfman McInnes Level: beginner 174136851e7fSLois Curfman McInnes 174295452b02SPatrick Sanan Developer Notes: 1743f6dfbefdSBarry Smith `SNES` always creates a `KSP` object even though many `SNES` methods do not use it. This is 1744efd4aadfSBarry Smith unfortunate and should be fixed at some point. The flag snes->usesksp indicates if the 1745f6dfbefdSBarry Smith particular method does use `KSP` and regulates if the information about the `KSP` is printed 1746f6dfbefdSBarry Smith in `SNESView()`. 1747efd4aadfSBarry Smith 1748f6dfbefdSBarry Smith `TSSetFromOptions()` does call `SNESSetFromOptions()` which can lead to users being confused 1749f6dfbefdSBarry Smith by help messages about meaningless `SNES` options. 1750f6dfbefdSBarry Smith 1751dc4c0fb0SBarry Smith `SNES` always creates the snes->kspconvctx even though it is used by only one type. This should be fixed. 1752efd4aadfSBarry Smith 1753e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()` 17549b94acceSBarry Smith @*/ 1755d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESCreate(MPI_Comm comm, SNES *outsnes) 1756d71ae5a4SJacob Faibussowitsch { 17579b94acceSBarry Smith SNES snes; 1758fa9f3622SBarry Smith SNESKSPEW *kctx; 175937fcc0dbSBarry Smith 17603a40ed3dSBarry Smith PetscFunctionBegin; 17614f572ea9SToby Isaac PetscAssertPointer(outsnes, 2); 17620298fd71SBarry Smith *outsnes = NULL; 17639566063dSJacob Faibussowitsch PetscCall(SNESInitializePackage()); 17648ba1e511SMatthew Knepley 17659566063dSJacob Faibussowitsch PetscCall(PetscHeaderCreate(snes, SNES_CLASSID, "SNES", "Nonlinear solver", "SNES", comm, SNESDestroy, SNESView)); 17667adad957SLisandro Dalcin 17678d359177SBarry Smith snes->ops->converged = SNESConvergedDefault; 17682c155ee1SBarry Smith snes->usesksp = PETSC_TRUE; 176988976e71SPeter Brune snes->tolerancesset = PETSC_FALSE; 17709b94acceSBarry Smith snes->max_its = 50; 17719750a799SBarry Smith snes->max_funcs = 10000; 17729b94acceSBarry Smith snes->norm = 0.0; 1773c1e67a49SFande Kong snes->xnorm = 0.0; 1774c1e67a49SFande Kong snes->ynorm = 0.0; 1775365a6726SPeter Brune snes->normschedule = SNES_NORM_ALWAYS; 17766c67d002SPeter Brune snes->functype = SNES_FUNCTION_DEFAULT; 17778ca48ce9SPierre Jolivet snes->rtol = PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8; 1778b4874afaSBarry Smith snes->ttol = 0.0; 17798ca48ce9SPierre Jolivet snes->abstol = PetscDefined(USE_REAL_SINGLE) ? 1.e-25 : 1.e-50; 17808ca48ce9SPierre Jolivet snes->stol = PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8; 17818ca48ce9SPierre Jolivet snes->deltatol = PetscDefined(USE_REAL_SINGLE) ? 1.e-6 : 1.e-12; 1782e37c518bSBarry Smith snes->divtol = 1.e4; 1783e37c518bSBarry Smith snes->rnorm0 = 0; 17849b94acceSBarry Smith snes->nfuncs = 0; 178550ffb88aSMatthew Knepley snes->numFailures = 0; 178650ffb88aSMatthew Knepley snes->maxFailures = 1; 17877a00f4a9SLois Curfman McInnes snes->linear_its = 0; 1788e35cf81dSBarry Smith snes->lagjacobian = 1; 178937ec4e1aSPeter Brune snes->jac_iter = 0; 179037ec4e1aSPeter Brune snes->lagjac_persist = PETSC_FALSE; 1791a8054027SBarry Smith snes->lagpreconditioner = 1; 179237ec4e1aSPeter Brune snes->pre_iter = 0; 179337ec4e1aSPeter Brune snes->lagpre_persist = PETSC_FALSE; 1794639f9d9dSBarry Smith snes->numbermonitors = 0; 1795c4421ceaSFande Kong snes->numberreasonviews = 0; 17969e5d0892SLisandro Dalcin snes->data = NULL; 17974dc4c822SBarry Smith snes->setupcalled = PETSC_FALSE; 1798186905e3SBarry Smith snes->ksp_ewconv = PETSC_FALSE; 17996f24a144SLois Curfman McInnes snes->nwork = 0; 18009e5d0892SLisandro Dalcin snes->work = NULL; 180158c9b817SLisandro Dalcin snes->nvwork = 0; 18029e5d0892SLisandro Dalcin snes->vwork = NULL; 1803758f92a0SBarry Smith snes->conv_hist_len = 0; 1804758f92a0SBarry Smith snes->conv_hist_max = 0; 18050298fd71SBarry Smith snes->conv_hist = NULL; 18060298fd71SBarry Smith snes->conv_hist_its = NULL; 1807758f92a0SBarry Smith snes->conv_hist_reset = PETSC_TRUE; 1808971e163fSPeter Brune snes->counters_reset = PETSC_TRUE; 1809e4ed7901SPeter Brune snes->vec_func_init_set = PETSC_FALSE; 1810184914b5SBarry Smith snes->reason = SNES_CONVERGED_ITERATING; 1811efd4aadfSBarry Smith snes->npcside = PC_RIGHT; 1812b3cd9a81SMatthew G. Knepley snes->setfromoptionscalled = 0; 1813c40d0f55SPeter Brune 1814d8f46077SPeter Brune snes->mf = PETSC_FALSE; 1815d8f46077SPeter Brune snes->mf_operator = PETSC_FALSE; 1816d8f46077SPeter Brune snes->mf_version = 1; 1817d8f46077SPeter Brune 18183d4c4710SBarry Smith snes->numLinearSolveFailures = 0; 18193d4c4710SBarry Smith snes->maxLinearSolveFailures = 1; 18203d4c4710SBarry Smith 1821349187a7SBarry Smith snes->vizerotolerance = 1.e-8; 182276bd3646SJed Brown snes->checkjacdomainerror = PetscDefined(USE_DEBUG) ? PETSC_TRUE : PETSC_FALSE; 1823349187a7SBarry Smith 18244fc747eaSLawrence Mitchell /* Set this to true if the implementation of SNESSolve_XXX does compute the residual at the final solution. */ 18254fc747eaSLawrence Mitchell snes->alwayscomputesfinalresidual = PETSC_FALSE; 18264fc747eaSLawrence Mitchell 18279b94acceSBarry Smith /* Create context to compute Eisenstat-Walker relative tolerance for KSP */ 18284dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&kctx)); 1829f5af7f23SKarl Rupp 18309b94acceSBarry Smith snes->kspconvctx = (void *)kctx; 18319b94acceSBarry Smith kctx->version = 2; 18320f0abf79SStefano Zampini kctx->rtol_0 = 0.3; /* Eisenstat and Walker suggest rtol_0=.5, but 18339b94acceSBarry Smith this was too large for some test cases */ 183475567043SBarry Smith kctx->rtol_last = 0.0; 18350f0abf79SStefano Zampini kctx->rtol_max = 0.9; 18369b94acceSBarry Smith kctx->gamma = 1.0; 18370f0abf79SStefano Zampini kctx->alpha = 0.5 * (1.0 + PetscSqrtReal(5.0)); 183871f87433Sdalcinl kctx->alpha2 = kctx->alpha; 18390f0abf79SStefano Zampini kctx->threshold = 0.1; 184075567043SBarry Smith kctx->lresid_last = 0.0; 184175567043SBarry Smith kctx->norm_last = 0.0; 18429b94acceSBarry Smith 18430f0abf79SStefano Zampini kctx->rk_last = 0.0; 18440f0abf79SStefano Zampini kctx->rk_last_2 = 0.0; 18450f0abf79SStefano Zampini kctx->rtol_last_2 = 0.0; 18460f0abf79SStefano Zampini kctx->v4_p1 = 0.1; 18470f0abf79SStefano Zampini kctx->v4_p2 = 0.4; 18480f0abf79SStefano Zampini kctx->v4_p3 = 0.7; 18490f0abf79SStefano Zampini kctx->v4_m1 = 0.8; 18500f0abf79SStefano Zampini kctx->v4_m2 = 0.5; 18510f0abf79SStefano Zampini kctx->v4_m3 = 0.1; 18520f0abf79SStefano Zampini kctx->v4_m4 = 0.5; 18530f0abf79SStefano Zampini 18549b94acceSBarry Smith *outsnes = snes; 18553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18569b94acceSBarry Smith } 18579b94acceSBarry 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` 18688434afd1SBarry Smith . f - function evaluation routine; for calling sequence see `SNESFunctionFn` 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 18748434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetPicard()`, `SNESFunctionFn` 18759b94acceSBarry Smith @*/ 18768434afd1SBarry Smith PetscErrorCode SNESSetFunction(SNES snes, Vec r, SNESFunctionFn *f, 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 2084cc4c1da9SBarry Smith /*@ 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 2114cc4c1da9SBarry Smith /*@ 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: 21419bcc50f1SBarry Smith + snes - the `SNES` context, usually of the `SNESType` `SNESNGS` 21428434afd1SBarry Smith . f - function evaluation routine to apply Gauss-Seidel, see `SNESNGSFn` for calling sequence 2143c79ef259SPeter Brune - ctx - [optional] user-defined context for private data for the 2144dc4c0fb0SBarry Smith smoother evaluation routine (may be `NULL`) 2145c79ef259SPeter Brune 2146dc4c0fb0SBarry Smith Level: intermediate 2147dc4c0fb0SBarry Smith 2148f6dfbefdSBarry Smith Note: 2149f6dfbefdSBarry Smith The `SNESNGS` routines are used by the composed nonlinear solver to generate 2150f6dfbefdSBarry Smith a problem appropriate update to the solution, particularly `SNESFAS`. 2151c79ef259SPeter Brune 21528434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGS`, `SNESGetNGS()`, `SNESNCG`, `SNESGetFunction()`, `SNESComputeNGS()`, `SNESNGSFn` 2153c79ef259SPeter Brune @*/ 21548434afd1SBarry Smith PetscErrorCode SNESSetNGS(SNES snes, SNESNGSFn *f, void *ctx) 2155d71ae5a4SJacob Faibussowitsch { 21566cab3a1bSJed Brown DM dm; 21576cab3a1bSJed Brown 2158646217ecSPeter Brune PetscFunctionBegin; 21596cab3a1bSJed Brown PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 21609566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 21619566063dSJacob Faibussowitsch PetscCall(DMSNESSetNGS(dm, f, ctx)); 21623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2163646217ecSPeter Brune } 2164646217ecSPeter Brune 2165bbc1464cSBarry Smith /* 2166bbc1464cSBarry Smith This is used for -snes_mf_operator; it uses a duplicate of snes->jacobian_pre because snes->jacobian_pre cannot be 2167bbc1464cSBarry Smith changed during the KSPSolve() 2168bbc1464cSBarry Smith */ 2169d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeMFFunction(SNES snes, Vec x, Vec f, void *ctx) 2170d71ae5a4SJacob Faibussowitsch { 2171bbc1464cSBarry Smith DM dm; 2172bbc1464cSBarry Smith DMSNES sdm; 2173bbc1464cSBarry Smith 2174bbc1464cSBarry Smith PetscFunctionBegin; 21759566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 21769566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 2177bbc1464cSBarry Smith /* A(x)*x - b(x) */ 2178bbc1464cSBarry Smith if (sdm->ops->computepfunction) { 2179792fecdfSBarry Smith PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx)); 21809566063dSJacob Faibussowitsch PetscCall(VecScale(f, -1.0)); 21810df40c35SBarry Smith /* Cannot share nonzero pattern because of the possible use of SNESComputeJacobianDefault() */ 2182ef1023bdSBarry Smith if (!snes->picard) PetscCall(MatDuplicate(snes->jacobian_pre, MAT_DO_NOT_COPY_VALUES, &snes->picard)); 2183792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx)); 21849566063dSJacob Faibussowitsch PetscCall(MatMultAdd(snes->picard, x, f, f)); 2185bbc1464cSBarry Smith } else { 2186792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx)); 21879566063dSJacob Faibussowitsch PetscCall(MatMult(snes->picard, x, f)); 2188bbc1464cSBarry Smith } 21893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2190bbc1464cSBarry Smith } 2191bbc1464cSBarry Smith 2192d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeFunction(SNES snes, Vec x, Vec f, void *ctx) 2193d71ae5a4SJacob Faibussowitsch { 2194e03ab78fSPeter Brune DM dm; 2195942e3340SBarry Smith DMSNES sdm; 21966cab3a1bSJed Brown 21978b0a5094SBarry Smith PetscFunctionBegin; 21989566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 21999566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 22008b0a5094SBarry Smith /* A(x)*x - b(x) */ 2201bbc1464cSBarry Smith if (sdm->ops->computepfunction) { 2202792fecdfSBarry Smith PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx)); 22039566063dSJacob Faibussowitsch PetscCall(VecScale(f, -1.0)); 2204792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx)); 22059566063dSJacob Faibussowitsch PetscCall(MatMultAdd(snes->jacobian_pre, x, f, f)); 2206bbc1464cSBarry Smith } else { 2207792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx)); 22089566063dSJacob Faibussowitsch PetscCall(MatMult(snes->jacobian_pre, x, f)); 2209bbc1464cSBarry Smith } 22103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22118b0a5094SBarry Smith } 22128b0a5094SBarry Smith 2213d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeJacobian(SNES snes, Vec x1, Mat J, Mat B, void *ctx) 2214d71ae5a4SJacob Faibussowitsch { 22158b0a5094SBarry Smith PetscFunctionBegin; 2216e03ab78fSPeter Brune /* the jacobian matrix should be pre-filled in SNESPicardComputeFunction */ 2217bbc1464cSBarry Smith /* must assembly if matrix-free to get the last SNES solution */ 22189566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 22199566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 22203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22218b0a5094SBarry Smith } 22228b0a5094SBarry Smith 22238b0a5094SBarry Smith /*@C 22241d27aa22SBarry Smith SNESSetPicard - Use `SNES` to solve the system $A(x) x = bp(x) + b $ via a Picard type iteration (Picard linearization) 22258b0a5094SBarry Smith 2226c3339decSBarry Smith Logically Collective 22278b0a5094SBarry Smith 22288b0a5094SBarry Smith Input Parameters: 2229f6dfbefdSBarry Smith + snes - the `SNES` context 2230dc4c0fb0SBarry Smith . r - vector to store function values, may be `NULL` 22318434afd1SBarry Smith . bp - function evaluation routine, may be `NULL`, for the calling sequence see `SNESFunctionFn` 22326b7fb656SBarry Smith . Amat - matrix with which A(x) x - bp(x) - b is to be computed 2233dc4c0fb0SBarry Smith . Pmat - matrix from which preconditioner is computed (usually the same as `Amat`) 22348434afd1SBarry Smith . J - function to compute matrix values, for the calling sequence see `SNESJacobianFn` 2235dc4c0fb0SBarry Smith - ctx - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`) 2236dc4c0fb0SBarry Smith 2237dc4c0fb0SBarry Smith Level: intermediate 22388b0a5094SBarry Smith 22398b0a5094SBarry Smith Notes: 22406b7fb656SBarry Smith It is often better to provide the nonlinear function F() and some approximation to its Jacobian directly and use 2241f450aa47SBarry 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. 2242f450aa47SBarry Smith 2243f6dfbefdSBarry Smith One can call `SNESSetPicard()` or `SNESSetFunction()` (and possibly `SNESSetJacobian()`) but cannot call both 22448b0a5094SBarry Smith 22451d27aa22SBarry 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}$. 22461d27aa22SBarry Smith When an exact solver is used this corresponds to the "classic" Picard $A(x^{n}) x^{n+1} = bp(x^{n}) + b$ iteration. 22478b0a5094SBarry Smith 2248dc4c0fb0SBarry Smith Run with `-snes_mf_operator` to solve the system with Newton's method using A(x^{n}) to construct the preconditioner. 22498b0a5094SBarry Smith 22500d04baf8SBarry Smith We implement the defect correction form of the Picard iteration because it converges much more generally when inexact linear solvers are used then 22511d27aa22SBarry Smith the direct Picard iteration $A(x^n) x^{n+1} = bp(x^n) + b$ 22528b0a5094SBarry Smith 22538b0a5094SBarry 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 22541d27aa22SBarry 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 22551d27aa22SBarry Smith different please contact us at petsc-dev@mcs.anl.gov and we'll have an entirely new argument \:-). 22568b0a5094SBarry Smith 22571d27aa22SBarry 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 2258f6dfbefdSBarry Smith A(x^{n}) is used to build the preconditioner 22596b7fb656SBarry Smith 226015229ffcSPierre Jolivet When used with `-snes_fd` this will compute the true Jacobian (very slowly one column at a time) and thus represent Newton's method. 22616b7fb656SBarry Smith 2262dc4c0fb0SBarry 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 22636b7fb656SBarry 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 2264f6dfbefdSBarry 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`. 2265aaa8cc7dSPierre Jolivet See the comment in src/snes/tutorials/ex15.c. 2266bbc1464cSBarry Smith 22679bcc50f1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESGetPicard()`, `SNESLineSearchPreCheckPicard()`, 22688434afd1SBarry Smith `SNESFunctionFn`, `SNESJacobianFn` 22698b0a5094SBarry Smith @*/ 22708434afd1SBarry Smith PetscErrorCode SNESSetPicard(SNES snes, Vec r, SNESFunctionFn *bp, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx) 2271d71ae5a4SJacob Faibussowitsch { 2272e03ab78fSPeter Brune DM dm; 2273e03ab78fSPeter Brune 22748b0a5094SBarry Smith PetscFunctionBegin; 22758b0a5094SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 22769566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 22779566063dSJacob Faibussowitsch PetscCall(DMSNESSetPicard(dm, bp, J, ctx)); 22789566063dSJacob Faibussowitsch PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx)); 22799566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes, r, SNESPicardComputeFunction, ctx)); 22809566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESPicardComputeJacobian, ctx)); 22813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22828b0a5094SBarry Smith } 22838b0a5094SBarry Smith 22847971a8bfSPeter Brune /*@C 22857971a8bfSPeter Brune SNESGetPicard - Returns the context for the Picard iteration 22867971a8bfSPeter Brune 2287f6dfbefdSBarry Smith Not Collective, but `Vec` is parallel if `SNES` is parallel. Collective if `Vec` is requested, but has not been created yet. 22887971a8bfSPeter Brune 22897971a8bfSPeter Brune Input Parameter: 2290f6dfbefdSBarry Smith . snes - the `SNES` context 22917971a8bfSPeter Brune 2292d8d19677SJose E. Roman Output Parameters: 2293dc4c0fb0SBarry Smith + r - the function (or `NULL`) 22948434afd1SBarry Smith . f - the function (or `NULL`); for calling sequence see `SNESFunctionFn` 2295dc4c0fb0SBarry Smith . Amat - the matrix used to defined the operation A(x) x - b(x) (or `NULL`) 2296dc4c0fb0SBarry Smith . Pmat - the matrix from which the preconditioner will be constructed (or `NULL`) 22978434afd1SBarry Smith . J - the function for matrix evaluation (or `NULL`); for calling sequence see `SNESJacobianFn` 2298dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`) 22997971a8bfSPeter Brune 23007971a8bfSPeter Brune Level: advanced 23017971a8bfSPeter Brune 23028434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetFunction()`, `SNESSetPicard()`, `SNESGetFunction()`, `SNESGetJacobian()`, `SNESGetDM()`, `SNESFunctionFn`, `SNESJacobianFn` 23037971a8bfSPeter Brune @*/ 23048434afd1SBarry Smith PetscErrorCode SNESGetPicard(SNES snes, Vec *r, SNESFunctionFn **f, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx) 2305d71ae5a4SJacob Faibussowitsch { 23067971a8bfSPeter Brune DM dm; 23077971a8bfSPeter Brune 23087971a8bfSPeter Brune PetscFunctionBegin; 23097971a8bfSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 23109566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, r, NULL, NULL)); 23119566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL)); 23129566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 23139566063dSJacob Faibussowitsch PetscCall(DMSNESGetPicard(dm, f, J, ctx)); 23143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23157971a8bfSPeter Brune } 23167971a8bfSPeter Brune 2317d25893d9SBarry Smith /*@C 2318dc4c0fb0SBarry Smith SNESSetComputeInitialGuess - Sets a routine used to compute an initial guess for the nonlinear problem 2319d25893d9SBarry Smith 2320c3339decSBarry Smith Logically Collective 2321d25893d9SBarry Smith 2322d25893d9SBarry Smith Input Parameters: 2323f6dfbefdSBarry Smith + snes - the `SNES` context 23248434afd1SBarry Smith . func - function evaluation routine, see `SNESInitialGuessFn` for the calling sequence 2325d25893d9SBarry Smith - ctx - [optional] user-defined context for private data for the 2326dc4c0fb0SBarry Smith function evaluation routine (may be `NULL`) 2327d25893d9SBarry Smith 2328d25893d9SBarry Smith Level: intermediate 2329d25893d9SBarry Smith 23308434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESInitialGuessFn` 2331d25893d9SBarry Smith @*/ 23328434afd1SBarry Smith PetscErrorCode SNESSetComputeInitialGuess(SNES snes, SNESInitialGuessFn *func, void *ctx) 2333d71ae5a4SJacob Faibussowitsch { 2334d25893d9SBarry Smith PetscFunctionBegin; 2335d25893d9SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2336d25893d9SBarry Smith if (func) snes->ops->computeinitialguess = func; 2337d25893d9SBarry Smith if (ctx) snes->initialguessP = ctx; 23383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2339d25893d9SBarry Smith } 2340d25893d9SBarry Smith 23411096aae1SMatthew Knepley /*@C 2342dc4c0fb0SBarry Smith SNESGetRhs - Gets the vector for solving F(x) = `rhs`. If `rhs` is not set 2343dd8e379bSPierre Jolivet it assumes a zero right-hand side. 23441096aae1SMatthew Knepley 2345c3339decSBarry Smith Logically Collective 23461096aae1SMatthew Knepley 23471096aae1SMatthew Knepley Input Parameter: 2348f6dfbefdSBarry Smith . snes - the `SNES` context 23491096aae1SMatthew Knepley 23501096aae1SMatthew Knepley Output Parameter: 2351dd8e379bSPierre Jolivet . rhs - the right-hand side vector or `NULL` if there is no right-hand side vector 23521096aae1SMatthew Knepley 23531096aae1SMatthew Knepley Level: intermediate 23541096aae1SMatthew Knepley 23551cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetFunction()` 23561096aae1SMatthew Knepley @*/ 2357d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetRhs(SNES snes, Vec *rhs) 2358d71ae5a4SJacob Faibussowitsch { 23591096aae1SMatthew Knepley PetscFunctionBegin; 23600700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 23614f572ea9SToby Isaac PetscAssertPointer(rhs, 2); 236285385478SLisandro Dalcin *rhs = snes->vec_rhs; 23633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23641096aae1SMatthew Knepley } 23651096aae1SMatthew Knepley 23669b94acceSBarry Smith /*@ 2367f6dfbefdSBarry Smith SNESComputeFunction - Calls the function that has been set with `SNESSetFunction()`. 23689b94acceSBarry Smith 2369c3339decSBarry Smith Collective 2370c7afd0dbSLois Curfman McInnes 23719b94acceSBarry Smith Input Parameters: 2372f6dfbefdSBarry Smith + snes - the `SNES` context 2373c7afd0dbSLois Curfman McInnes - x - input vector 23749b94acceSBarry Smith 23759b94acceSBarry Smith Output Parameter: 2376f6dfbefdSBarry Smith . y - function vector, as set by `SNESSetFunction()` 23779b94acceSBarry Smith 2378dc4c0fb0SBarry Smith Level: developer 2379dc4c0fb0SBarry Smith 238000677de2SStefano Zampini Notes: 2381f6dfbefdSBarry Smith `SNESComputeFunction()` is typically used within nonlinear solvers 2382bbc1464cSBarry Smith implementations, so users would not generally call this routine themselves. 238336851e7fSLois Curfman McInnes 238400677de2SStefano Zampini When solving for $F(x) = b$, this routine computes $y = F(x) - b$. 238500677de2SStefano Zampini 23861cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeMFFunction()` 23879b94acceSBarry Smith @*/ 2388d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeFunction(SNES snes, Vec x, Vec y) 2389d71ae5a4SJacob Faibussowitsch { 23906cab3a1bSJed Brown DM dm; 2391942e3340SBarry Smith DMSNES sdm; 23929b94acceSBarry Smith 23933a40ed3dSBarry Smith PetscFunctionBegin; 23940700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 23950700a824SBarry Smith PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 23960700a824SBarry Smith PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2397c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, x, 2); 2398c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, y, 3); 2399e0f629ddSJacob Faibussowitsch PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2400184914b5SBarry Smith 24019566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 24029566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 24030fdf79fbSJacob 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()."); 240432f3f7c2SPeter Brune if (sdm->ops->computefunction) { 240548a46eb9SPierre Jolivet if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0)); 24069566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(x)); 24078ddeebeaSSteve Benbow /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */ 24088ddeebeaSSteve Benbow snes->domainerror = PETSC_FALSE; 2409800f99ffSJeremy L Thompson { 2410800f99ffSJeremy L Thompson void *ctx; 24118434afd1SBarry Smith SNESFunctionFn *computefunction; 2412800f99ffSJeremy L Thompson PetscCall(DMSNESGetFunction(dm, &computefunction, &ctx)); 2413800f99ffSJeremy L Thompson PetscCallBack("SNES callback function", (*computefunction)(snes, x, y, ctx)); 2414800f99ffSJeremy L Thompson } 24159566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(x)); 241648a46eb9SPierre Jolivet if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0)); 24170fdf79fbSJacob Faibussowitsch } else /* if (snes->vec_rhs) */ { 24189566063dSJacob Faibussowitsch PetscCall(MatMult(snes->jacobian, x, y)); 24190fdf79fbSJacob Faibussowitsch } 24201baa6e33SBarry Smith if (snes->vec_rhs) PetscCall(VecAXPY(y, -1.0, snes->vec_rhs)); 2421ae3c334cSLois Curfman McInnes snes->nfuncs++; 2422422a814eSBarry Smith /* 2423422a814eSBarry Smith domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will 2424422a814eSBarry Smith propagate the value to all processes 2425422a814eSBarry Smith */ 24261baa6e33SBarry Smith if (snes->domainerror) PetscCall(VecSetInf(y)); 24273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24289b94acceSBarry Smith } 24299b94acceSBarry Smith 2430c79ef259SPeter Brune /*@ 2431f6dfbefdSBarry Smith SNESComputeMFFunction - Calls the function that has been set with `SNESSetMFFunction()`. 2432bbc1464cSBarry Smith 2433c3339decSBarry Smith Collective 2434bbc1464cSBarry Smith 2435bbc1464cSBarry Smith Input Parameters: 2436f6dfbefdSBarry Smith + snes - the `SNES` context 2437bbc1464cSBarry Smith - x - input vector 2438bbc1464cSBarry Smith 2439bbc1464cSBarry Smith Output Parameter: 2440f6dfbefdSBarry Smith . y - function vector, as set by `SNESSetMFFunction()` 2441bbc1464cSBarry Smith 2442dc4c0fb0SBarry Smith Level: developer 2443dc4c0fb0SBarry Smith 2444bbc1464cSBarry Smith Notes: 2445420bcc1bSBarry Smith `SNESComputeMFFunction()` is used within the matrix-vector products called by the matrix created with `MatCreateSNESMF()` 2446bbc1464cSBarry Smith so users would not generally call this routine themselves. 2447bbc1464cSBarry Smith 2448dd8e379bSPierre Jolivet Since this function is intended for use with finite differencing it does not subtract the right-hand side vector provided with `SNESSolve()` 2449f6dfbefdSBarry Smith while `SNESComputeFunction()` does. As such, this routine cannot be used with `MatMFFDSetBase()` with a provided F function value even if it applies the 2450dd8e379bSPierre Jolivet same function as `SNESComputeFunction()` if a `SNESSolve()` right-hand side vector is use because the two functions difference would include this right hand side function. 2451bbc1464cSBarry Smith 24521cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `MatCreateSNESMF` 2453bbc1464cSBarry Smith @*/ 2454d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeMFFunction(SNES snes, Vec x, Vec y) 2455d71ae5a4SJacob Faibussowitsch { 2456bbc1464cSBarry Smith DM dm; 2457bbc1464cSBarry Smith DMSNES sdm; 2458bbc1464cSBarry Smith 2459bbc1464cSBarry Smith PetscFunctionBegin; 2460bbc1464cSBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2461bbc1464cSBarry Smith PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2462bbc1464cSBarry Smith PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2463bbc1464cSBarry Smith PetscCheckSameComm(snes, 1, x, 2); 2464bbc1464cSBarry Smith PetscCheckSameComm(snes, 1, y, 3); 2465e0f629ddSJacob Faibussowitsch PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2466bbc1464cSBarry Smith 24679566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 24689566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 24699566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0)); 24709566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(x)); 2471bbc1464cSBarry Smith /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */ 2472bbc1464cSBarry Smith snes->domainerror = PETSC_FALSE; 2473792fecdfSBarry Smith PetscCallBack("SNES callback function", (*sdm->ops->computemffunction)(snes, x, y, sdm->mffunctionctx)); 24749566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(x)); 24759566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0)); 2476bbc1464cSBarry Smith snes->nfuncs++; 2477bbc1464cSBarry Smith /* 2478bbc1464cSBarry Smith domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will 2479bbc1464cSBarry Smith propagate the value to all processes 2480bbc1464cSBarry Smith */ 24811baa6e33SBarry Smith if (snes->domainerror) PetscCall(VecSetInf(y)); 24823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2483bbc1464cSBarry Smith } 2484bbc1464cSBarry Smith 2485bbc1464cSBarry Smith /*@ 2486f6dfbefdSBarry Smith SNESComputeNGS - Calls the Gauss-Seidel function that has been set with `SNESSetNGS()`. 2487c79ef259SPeter Brune 2488c3339decSBarry Smith Collective 2489c79ef259SPeter Brune 2490c79ef259SPeter Brune Input Parameters: 2491f6dfbefdSBarry Smith + snes - the `SNES` context 2492c79ef259SPeter Brune . x - input vector 2493c79ef259SPeter Brune - b - rhs vector 2494c79ef259SPeter Brune 2495c79ef259SPeter Brune Output Parameter: 2496c79ef259SPeter Brune . x - new solution vector 2497c79ef259SPeter Brune 2498dc4c0fb0SBarry Smith Level: developer 2499dc4c0fb0SBarry Smith 2500f6dfbefdSBarry Smith Note: 2501f6dfbefdSBarry Smith `SNESComputeNGS()` is typically used within composed nonlinear solver 2502c79ef259SPeter Brune implementations, so most users would not generally call this routine 2503c79ef259SPeter Brune themselves. 2504c79ef259SPeter Brune 25058434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGSFn`, `SNESSetNGS()`, `SNESComputeFunction()`, `SNESNGS` 2506c79ef259SPeter Brune @*/ 2507d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeNGS(SNES snes, Vec b, Vec x) 2508d71ae5a4SJacob Faibussowitsch { 25096cab3a1bSJed Brown DM dm; 2510942e3340SBarry Smith DMSNES sdm; 2511646217ecSPeter Brune 2512646217ecSPeter Brune PetscFunctionBegin; 2513646217ecSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2514064a246eSJacob Faibussowitsch PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 2515064a246eSJacob Faibussowitsch if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 2516064a246eSJacob Faibussowitsch PetscCheckSameComm(snes, 1, x, 3); 2517064a246eSJacob Faibussowitsch if (b) PetscCheckSameComm(snes, 1, b, 2); 2518e0f629ddSJacob Faibussowitsch if (b) PetscCall(VecValidValues_Internal(b, 2, PETSC_TRUE)); 25199566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_NGSEval, snes, x, b, 0)); 25209566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 25219566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 25220fdf79fbSJacob Faibussowitsch PetscCheck(sdm->ops->computegs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetNGS() before SNESComputeNGS(), likely called from SNESSolve()."); 25239566063dSJacob Faibussowitsch if (b) PetscCall(VecLockReadPush(b)); 2524792fecdfSBarry Smith PetscCallBack("SNES callback NGS", (*sdm->ops->computegs)(snes, x, b, sdm->gsctx)); 25259566063dSJacob Faibussowitsch if (b) PetscCall(VecLockReadPop(b)); 25269566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_NGSEval, snes, x, b, 0)); 25273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2528646217ecSPeter Brune } 2529646217ecSPeter Brune 2530494a190aSStefano Zampini static PetscErrorCode SNESComputeFunction_FD(SNES snes, Vec Xin, Vec G) 2531494a190aSStefano Zampini { 2532494a190aSStefano Zampini Vec X; 2533494a190aSStefano Zampini PetscScalar *g; 2534494a190aSStefano Zampini PetscReal f, f2; 2535494a190aSStefano Zampini PetscInt low, high, N, i; 2536494a190aSStefano Zampini PetscBool flg; 2537494a190aSStefano Zampini PetscReal h = .5 * PETSC_SQRT_MACHINE_EPSILON; 2538494a190aSStefano Zampini 2539494a190aSStefano Zampini PetscFunctionBegin; 2540494a190aSStefano Zampini PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_fd_delta", &h, &flg)); 2541494a190aSStefano Zampini PetscCall(VecDuplicate(Xin, &X)); 2542494a190aSStefano Zampini PetscCall(VecCopy(Xin, X)); 2543494a190aSStefano Zampini PetscCall(VecGetSize(X, &N)); 2544494a190aSStefano Zampini PetscCall(VecGetOwnershipRange(X, &low, &high)); 2545494a190aSStefano Zampini PetscCall(VecSetOption(X, VEC_IGNORE_OFF_PROC_ENTRIES, PETSC_TRUE)); 2546494a190aSStefano Zampini PetscCall(VecGetArray(G, &g)); 2547494a190aSStefano Zampini for (i = 0; i < N; i++) { 2548494a190aSStefano Zampini PetscCall(VecSetValue(X, i, -h, ADD_VALUES)); 2549494a190aSStefano Zampini PetscCall(VecAssemblyBegin(X)); 2550494a190aSStefano Zampini PetscCall(VecAssemblyEnd(X)); 2551494a190aSStefano Zampini PetscCall(SNESComputeObjective(snes, X, &f)); 2552494a190aSStefano Zampini PetscCall(VecSetValue(X, i, 2.0 * h, ADD_VALUES)); 2553494a190aSStefano Zampini PetscCall(VecAssemblyBegin(X)); 2554494a190aSStefano Zampini PetscCall(VecAssemblyEnd(X)); 2555494a190aSStefano Zampini PetscCall(SNESComputeObjective(snes, X, &f2)); 2556494a190aSStefano Zampini PetscCall(VecSetValue(X, i, -h, ADD_VALUES)); 2557494a190aSStefano Zampini PetscCall(VecAssemblyBegin(X)); 2558494a190aSStefano Zampini PetscCall(VecAssemblyEnd(X)); 2559494a190aSStefano Zampini if (i >= low && i < high) g[i - low] = (f2 - f) / (2.0 * h); 2560494a190aSStefano Zampini } 2561494a190aSStefano Zampini PetscCall(VecRestoreArray(G, &g)); 2562494a190aSStefano Zampini PetscCall(VecDestroy(&X)); 2563494a190aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2564494a190aSStefano Zampini } 2565494a190aSStefano Zampini 2566494a190aSStefano Zampini PetscErrorCode SNESTestFunction(SNES snes) 2567494a190aSStefano Zampini { 2568494a190aSStefano Zampini Vec x, g1, g2, g3; 2569494a190aSStefano Zampini PetscBool complete_print = PETSC_FALSE, test = PETSC_FALSE; 2570494a190aSStefano Zampini PetscReal hcnorm, fdnorm, hcmax, fdmax, diffmax, diffnorm; 2571494a190aSStefano Zampini PetscScalar dot; 2572494a190aSStefano Zampini MPI_Comm comm; 2573494a190aSStefano Zampini PetscViewer viewer, mviewer; 2574494a190aSStefano Zampini PetscViewerFormat format; 2575494a190aSStefano Zampini PetscInt tabs; 2576494a190aSStefano Zampini static PetscBool directionsprinted = PETSC_FALSE; 25778434afd1SBarry Smith SNESObjectiveFn *objective; 2578494a190aSStefano Zampini 2579494a190aSStefano Zampini PetscFunctionBegin; 2580494a190aSStefano Zampini PetscCall(SNESGetObjective(snes, &objective, NULL)); 2581494a190aSStefano Zampini if (!objective) PetscFunctionReturn(PETSC_SUCCESS); 2582494a190aSStefano Zampini 2583494a190aSStefano Zampini PetscObjectOptionsBegin((PetscObject)snes); 2584494a190aSStefano Zampini PetscCall(PetscOptionsName("-snes_test_function", "Compare hand-coded and finite difference function", "None", &test)); 2585494a190aSStefano Zampini PetscCall(PetscOptionsViewer("-snes_test_function_view", "View difference between hand-coded and finite difference function element entries", "None", &mviewer, &format, &complete_print)); 2586494a190aSStefano Zampini PetscOptionsEnd(); 2587494a190aSStefano Zampini if (!test) { 2588494a190aSStefano Zampini if (complete_print) PetscCall(PetscViewerDestroy(&mviewer)); 2589494a190aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2590494a190aSStefano Zampini } 2591494a190aSStefano Zampini 2592494a190aSStefano Zampini PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 2593494a190aSStefano Zampini PetscCall(PetscViewerASCIIGetStdout(comm, &viewer)); 2594494a190aSStefano Zampini PetscCall(PetscViewerASCIIGetTab(viewer, &tabs)); 2595494a190aSStefano Zampini PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel)); 2596494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Function -------------\n")); 2597494a190aSStefano Zampini if (!complete_print && !directionsprinted) { 2598494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Run with -snes_test_function_view and optionally -snes_test_function <threshold> to show difference\n")); 2599494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " of hand-coded and finite difference function entries greater than <threshold>.\n")); 2600494a190aSStefano Zampini } 2601494a190aSStefano Zampini if (!directionsprinted) { 2602494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Testing hand-coded Function, if (for double precision runs) ||F - Ffd||/||F|| is\n")); 2603494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " O(1.e-8), the hand-coded Function is probably correct.\n")); 2604494a190aSStefano Zampini directionsprinted = PETSC_TRUE; 2605494a190aSStefano Zampini } 2606494a190aSStefano Zampini if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format)); 2607494a190aSStefano Zampini 2608494a190aSStefano Zampini PetscCall(SNESGetSolution(snes, &x)); 2609494a190aSStefano Zampini PetscCall(VecDuplicate(x, &g1)); 2610494a190aSStefano Zampini PetscCall(VecDuplicate(x, &g2)); 2611494a190aSStefano Zampini PetscCall(VecDuplicate(x, &g3)); 2612494a190aSStefano Zampini PetscCall(SNESComputeFunction(snes, x, g1)); 2613494a190aSStefano Zampini PetscCall(SNESComputeFunction_FD(snes, x, g2)); 2614494a190aSStefano Zampini 2615494a190aSStefano Zampini PetscCall(VecNorm(g2, NORM_2, &fdnorm)); 2616494a190aSStefano Zampini PetscCall(VecNorm(g1, NORM_2, &hcnorm)); 2617494a190aSStefano Zampini PetscCall(VecNorm(g2, NORM_INFINITY, &fdmax)); 2618494a190aSStefano Zampini PetscCall(VecNorm(g1, NORM_INFINITY, &hcmax)); 2619494a190aSStefano Zampini PetscCall(VecDot(g1, g2, &dot)); 2620494a190aSStefano Zampini PetscCall(VecCopy(g1, g3)); 2621494a190aSStefano Zampini PetscCall(VecAXPY(g3, -1.0, g2)); 2622494a190aSStefano Zampini PetscCall(VecNorm(g3, NORM_2, &diffnorm)); 2623494a190aSStefano Zampini PetscCall(VecNorm(g3, NORM_INFINITY, &diffmax)); 2624494a190aSStefano 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)))); 2625494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " 2-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffnorm / PetscMax(hcnorm, fdnorm)), (double)diffnorm)); 2626494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " max-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffmax / PetscMax(hcmax, fdmax)), (double)diffmax)); 2627494a190aSStefano Zampini 2628494a190aSStefano Zampini if (complete_print) { 2629494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded function ----------\n")); 2630494a190aSStefano Zampini PetscCall(VecView(g1, mviewer)); 2631494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Finite difference function ----------\n")); 2632494a190aSStefano Zampini PetscCall(VecView(g2, mviewer)); 2633494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded minus finite-difference function ----------\n")); 2634494a190aSStefano Zampini PetscCall(VecView(g3, mviewer)); 2635494a190aSStefano Zampini } 2636494a190aSStefano Zampini PetscCall(VecDestroy(&g1)); 2637494a190aSStefano Zampini PetscCall(VecDestroy(&g2)); 2638494a190aSStefano Zampini PetscCall(VecDestroy(&g3)); 2639494a190aSStefano Zampini 2640494a190aSStefano Zampini if (complete_print) { 2641494a190aSStefano Zampini PetscCall(PetscViewerPopFormat(mviewer)); 2642494a190aSStefano Zampini PetscCall(PetscViewerDestroy(&mviewer)); 2643494a190aSStefano Zampini } 2644494a190aSStefano Zampini PetscCall(PetscViewerASCIISetTab(viewer, tabs)); 2645494a190aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2646494a190aSStefano Zampini } 2647494a190aSStefano Zampini 2648d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestJacobian(SNES snes) 2649d71ae5a4SJacob Faibussowitsch { 265012837594SBarry Smith Mat A, B, C, D, jacobian; 26514df93895SStefano Zampini Vec x = snes->vec_sol, f; 2652e885f1abSBarry Smith PetscReal nrm, gnorm; 265381e7118cSBarry Smith PetscReal threshold = 1.e-5; 26540e276705SLisandro Dalcin MatType mattype; 2655e885f1abSBarry Smith PetscInt m, n, M, N; 2656e885f1abSBarry Smith void *functx; 26572cd624f9SStefano Zampini PetscBool complete_print = PETSC_FALSE, threshold_print = PETSC_FALSE, test = PETSC_FALSE, flg, istranspose; 26583325ff46SBarry Smith PetscViewer viewer, mviewer; 2659e885f1abSBarry Smith MPI_Comm comm; 2660e885f1abSBarry Smith PetscInt tabs; 266112837594SBarry Smith static PetscBool directionsprinted = PETSC_FALSE; 26623325ff46SBarry Smith PetscViewerFormat format; 2663e885f1abSBarry Smith 2664e885f1abSBarry Smith PetscFunctionBegin; 2665d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)snes); 26669566063dSJacob Faibussowitsch PetscCall(PetscOptionsName("-snes_test_jacobian", "Compare hand-coded and finite difference Jacobians", "None", &test)); 26679566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-snes_test_jacobian", "Threshold for element difference between hand-coded and finite difference being meaningful", "None", threshold, &threshold, NULL)); 26689566063dSJacob Faibussowitsch PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display", "-snes_test_jacobian_view", "3.13", NULL)); 26694ead3382SBarry Smith PetscCall(PetscOptionsViewer("-snes_test_jacobian_view", "View difference between hand-coded and finite difference Jacobians element entries", "None", &mviewer, &format, &complete_print)); 26709566063dSJacob Faibussowitsch PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display_threshold", "-snes_test_jacobian", "3.13", "-snes_test_jacobian accepts an optional threshold (since v3.10)")); 26719566063dSJacob 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)); 2672d0609cedSBarry Smith PetscOptionsEnd(); 26733ba16761SJacob Faibussowitsch if (!test) PetscFunctionReturn(PETSC_SUCCESS); 2674e885f1abSBarry Smith 26759566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 26769566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(comm, &viewer)); 26779566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetTab(viewer, &tabs)); 26789566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel)); 26799566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Jacobian -------------\n")); 268012837594SBarry Smith if (!complete_print && !directionsprinted) { 26819566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Run with -snes_test_jacobian_view and optionally -snes_test_jacobian <threshold> to show difference\n")); 26829566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " of hand-coded and finite difference Jacobian entries greater than <threshold>.\n")); 268312837594SBarry Smith } 268412837594SBarry Smith if (!directionsprinted) { 26859566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Testing hand-coded Jacobian, if (for double precision runs) ||J - Jfd||_F/||J||_F is\n")); 26869566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " O(1.e-8), the hand-coded Jacobian is probably correct.\n")); 268712837594SBarry Smith directionsprinted = PETSC_TRUE; 2688e885f1abSBarry Smith } 26891baa6e33SBarry Smith if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format)); 2690e885f1abSBarry Smith 26919566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes->jacobian, MATMFFD, &flg)); 269212837594SBarry Smith if (!flg) jacobian = snes->jacobian; 269312837594SBarry Smith else jacobian = snes->jacobian_pre; 269412837594SBarry Smith 26954df93895SStefano Zampini if (!x) PetscCall(MatCreateVecs(jacobian, &x, NULL)); 26964df93895SStefano Zampini else PetscCall(PetscObjectReference((PetscObject)x)); 26979566063dSJacob Faibussowitsch PetscCall(VecDuplicate(x, &f)); 26984df93895SStefano Zampini 2699a82339d0SMatthew G. Knepley /* evaluate the function at this point because SNESComputeJacobianDefault() assumes that the function has been evaluated and put into snes->vec_func */ 27009566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, x, f)); 27019566063dSJacob Faibussowitsch PetscCall(VecDestroy(&f)); 27029566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESKSPTRANSPOSEONLY, &istranspose)); 270312837594SBarry Smith while (jacobian) { 27042cd624f9SStefano Zampini Mat JT = NULL, Jsave = NULL; 27052cd624f9SStefano Zampini 27062cd624f9SStefano Zampini if (istranspose) { 27079566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(jacobian, &JT)); 27082cd624f9SStefano Zampini Jsave = jacobian; 27092cd624f9SStefano Zampini jacobian = JT; 27102cd624f9SStefano Zampini } 27119566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)jacobian, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, "")); 271212837594SBarry Smith if (flg) { 271312837594SBarry Smith A = jacobian; 27149566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 271512837594SBarry Smith } else { 27169566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(jacobian, MATAIJ, &A)); 271712837594SBarry Smith } 2718e885f1abSBarry Smith 27199566063dSJacob Faibussowitsch PetscCall(MatGetType(A, &mattype)); 27209566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &M, &N)); 27219566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &m, &n)); 27229566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B)); 27239566063dSJacob Faibussowitsch PetscCall(MatSetType(B, mattype)); 27249566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, m, n, M, N)); 27259566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(B, A, A)); 27269566063dSJacob Faibussowitsch PetscCall(MatSetUp(B)); 27279566063dSJacob Faibussowitsch PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 2728e885f1abSBarry Smith 27299566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, NULL, &functx)); 27309566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobianDefault(snes, x, B, B, functx)); 273112837594SBarry Smith 27329566063dSJacob Faibussowitsch PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &D)); 27339566063dSJacob Faibussowitsch PetscCall(MatAYPX(D, -1.0, A, DIFFERENT_NONZERO_PATTERN)); 27349566063dSJacob Faibussowitsch PetscCall(MatNorm(D, NORM_FROBENIUS, &nrm)); 27359566063dSJacob Faibussowitsch PetscCall(MatNorm(A, NORM_FROBENIUS, &gnorm)); 27369566063dSJacob Faibussowitsch PetscCall(MatDestroy(&D)); 273712837594SBarry Smith if (!gnorm) gnorm = 1; /* just in case */ 27389566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " ||J - Jfd||_F/||J||_F = %g, ||J - Jfd||_F = %g\n", (double)(nrm / gnorm), (double)nrm)); 273912837594SBarry Smith 2740e885f1abSBarry Smith if (complete_print) { 27419566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded Jacobian ----------\n")); 27429566063dSJacob Faibussowitsch PetscCall(MatView(A, mviewer)); 27439566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Finite difference Jacobian ----------\n")); 27449566063dSJacob Faibussowitsch PetscCall(MatView(B, mviewer)); 2745e885f1abSBarry Smith } 2746e885f1abSBarry Smith 2747df10fb39SFande Kong if (threshold_print || complete_print) { 2748e885f1abSBarry Smith PetscInt Istart, Iend, *ccols, bncols, cncols, j, row; 2749e885f1abSBarry Smith PetscScalar *cvals; 2750e885f1abSBarry Smith const PetscInt *bcols; 2751e885f1abSBarry Smith const PetscScalar *bvals; 2752e885f1abSBarry Smith 27539566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C)); 27549566063dSJacob Faibussowitsch PetscCall(MatSetType(C, mattype)); 27559566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, m, n, M, N)); 27569566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(C, A, A)); 27579566063dSJacob Faibussowitsch PetscCall(MatSetUp(C)); 27589566063dSJacob Faibussowitsch PetscCall(MatSetOption(C, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 27590e276705SLisandro Dalcin 27609566063dSJacob Faibussowitsch PetscCall(MatAYPX(B, -1.0, A, DIFFERENT_NONZERO_PATTERN)); 27619566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(B, &Istart, &Iend)); 2762e885f1abSBarry Smith 2763e885f1abSBarry Smith for (row = Istart; row < Iend; row++) { 27649566063dSJacob Faibussowitsch PetscCall(MatGetRow(B, row, &bncols, &bcols, &bvals)); 27659566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(bncols, &ccols, bncols, &cvals)); 2766e885f1abSBarry Smith for (j = 0, cncols = 0; j < bncols; j++) { 276723a52b1dSBarry Smith if (PetscAbsScalar(bvals[j]) > threshold) { 2768e885f1abSBarry Smith ccols[cncols] = bcols[j]; 2769e885f1abSBarry Smith cvals[cncols] = bvals[j]; 2770e885f1abSBarry Smith cncols += 1; 2771e885f1abSBarry Smith } 2772e885f1abSBarry Smith } 277348a46eb9SPierre Jolivet if (cncols) PetscCall(MatSetValues(C, 1, &row, cncols, ccols, cvals, INSERT_VALUES)); 27749566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(B, row, &bncols, &bcols, &bvals)); 27759566063dSJacob Faibussowitsch PetscCall(PetscFree2(ccols, cvals)); 2776e885f1abSBarry Smith } 27779566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 27789566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 27799566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded minus finite-difference Jacobian with tolerance %g ----------\n", (double)threshold)); 27809566063dSJacob Faibussowitsch PetscCall(MatView(C, complete_print ? mviewer : viewer)); 27819566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C)); 2782e885f1abSBarry Smith } 27839566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A)); 27849566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 27859566063dSJacob Faibussowitsch PetscCall(MatDestroy(&JT)); 27862cd624f9SStefano Zampini if (Jsave) jacobian = Jsave; 278712837594SBarry Smith if (jacobian != snes->jacobian_pre) { 278812837594SBarry Smith jacobian = snes->jacobian_pre; 27899566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Jacobian for preconditioner -------------\n")); 27909371c9d4SSatish Balay } else jacobian = NULL; 279112837594SBarry Smith } 27929566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); 27931baa6e33SBarry Smith if (complete_print) PetscCall(PetscViewerPopFormat(mviewer)); 2794cd791dc2SBarry Smith if (mviewer) PetscCall(PetscOptionsRestoreViewer(&mviewer)); 27959566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISetTab(viewer, tabs)); 27963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2797e885f1abSBarry Smith } 2798e885f1abSBarry Smith 279962fef451SLois Curfman McInnes /*@ 2800f6dfbefdSBarry Smith SNESComputeJacobian - Computes the Jacobian matrix that has been set with `SNESSetJacobian()`. 280162fef451SLois Curfman McInnes 2802c3339decSBarry Smith Collective 2803c7afd0dbSLois Curfman McInnes 280462fef451SLois Curfman McInnes Input Parameters: 2805f6dfbefdSBarry Smith + snes - the `SNES` context 2806e4094ef1SJacob Faibussowitsch - X - input vector 280762fef451SLois Curfman McInnes 280862fef451SLois Curfman McInnes Output Parameters: 2809c7afd0dbSLois Curfman McInnes + A - Jacobian matrix 2810420bcc1bSBarry Smith - B - optional matrix for building the preconditioner, usually the same as `A` 2811fee21e36SBarry Smith 2812e35cf81dSBarry Smith Options Database Keys: 281367b8a455SSatish Balay + -snes_lag_preconditioner <lag> - how often to rebuild preconditioner 281467b8a455SSatish Balay . -snes_lag_jacobian <lag> - how often to rebuild Jacobian 2815455a5933SJed 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. 2816455a5933SJed 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 2817693365a8SJed Brown . -snes_compare_explicit - Compare the computed Jacobian to the finite difference Jacobian and output the differences 2818693365a8SJed Brown . -snes_compare_explicit_draw - Compare the computed Jacobian to the finite difference Jacobian and draw the result 2819693365a8SJed Brown . -snes_compare_explicit_contour - Compare the computed Jacobian to the finite difference Jacobian and draw a contour plot with the result 28204c30e9fbSJed Brown . -snes_compare_operator - Make the comparison options above use the operator instead of the preconditioning matrix 282194d6a431SBarry Smith . -snes_compare_coloring - Compute the finite difference Jacobian using coloring and display norms of difference 2822a5b23f4aSJose E. Roman . -snes_compare_coloring_display - Compute the finite difference Jacobian using coloring and display verbose differences 2823c01495d3SJed Brown . -snes_compare_coloring_threshold - Display only those matrix entries that differ by more than a given threshold 2824dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_atol - Absolute tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold` 2825dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_rtol - Relative tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold` 2826a5b23f4aSJose E. Roman . -snes_compare_coloring_draw - Compute the finite difference Jacobian using coloring and draw differences 2827a5b23f4aSJose E. Roman - -snes_compare_coloring_draw_contour - Compute the finite difference Jacobian using coloring and show contours of matrices and differences 2828c01495d3SJed Brown 2829dc4c0fb0SBarry Smith Level: developer 2830dc4c0fb0SBarry Smith 2831f6dfbefdSBarry Smith Note: 283262fef451SLois Curfman McInnes Most users should not need to explicitly call this routine, as it 283362fef451SLois Curfman McInnes is used internally within the nonlinear solvers. 283462fef451SLois Curfman McInnes 2835420bcc1bSBarry Smith Developer Note: 2836dc4c0fb0SBarry 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 2837420bcc1bSBarry Smith with the `SNESType` of test that has been removed. 2838e885f1abSBarry Smith 28391cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetJacobian()`, `KSPSetOperators()`, `MatStructure`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()` 284062fef451SLois Curfman McInnes @*/ 2841d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeJacobian(SNES snes, Vec X, Mat A, Mat B) 2842d71ae5a4SJacob Faibussowitsch { 2843ace3abfcSBarry Smith PetscBool flag; 28446cab3a1bSJed Brown DM dm; 2845942e3340SBarry Smith DMSNES sdm; 2846e0e3a89bSBarry Smith KSP ksp; 28473a40ed3dSBarry Smith 28483a40ed3dSBarry Smith PetscFunctionBegin; 28490700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 28500700a824SBarry Smith PetscValidHeaderSpecific(X, VEC_CLASSID, 2); 2851c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, X, 2); 2852e0f629ddSJacob Faibussowitsch PetscCall(VecValidValues_Internal(X, 2, PETSC_TRUE)); 28539566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 28549566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 28553232da50SPeter Brune 285601c1178eSBarry Smith /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix-free */ 2857fe3ffe1eSBarry Smith if (snes->lagjacobian == -2) { 2858fe3ffe1eSBarry Smith snes->lagjacobian = -1; 2859f5af7f23SKarl Rupp 28609566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n")); 2861fe3ffe1eSBarry Smith } else if (snes->lagjacobian == -1) { 28629566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is -1\n")); 28639566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag)); 2864ebd3b9afSBarry Smith if (flag) { 28659566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 28669566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 2867ebd3b9afSBarry Smith } 28683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 286937ec4e1aSPeter Brune } else if (snes->lagjacobian > 1 && (snes->iter + snes->jac_iter) % snes->lagjacobian) { 287063a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagjacobian, snes->iter)); 28719566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag)); 2872ebd3b9afSBarry Smith if (flag) { 28739566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 28749566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 2875ebd3b9afSBarry Smith } 28763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2877e35cf81dSBarry Smith } 2878efd4aadfSBarry Smith if (snes->npc && snes->npcside == PC_LEFT) { 28799566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 28809566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 28813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2882d728fb7dSPeter Brune } 2883e35cf81dSBarry Smith 28849566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_JacobianEval, snes, X, A, B)); 28859566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(X)); 2886800f99ffSJeremy L Thompson { 2887800f99ffSJeremy L Thompson void *ctx; 28888434afd1SBarry Smith SNESJacobianFn *J; 2889800f99ffSJeremy L Thompson PetscCall(DMSNESGetJacobian(dm, &J, &ctx)); 2890800f99ffSJeremy L Thompson PetscCallBack("SNES callback Jacobian", (*J)(snes, X, A, B, ctx)); 2891800f99ffSJeremy L Thompson } 28929566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(X)); 28939566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_JacobianEval, snes, X, A, B)); 289428d58a37SPierre Jolivet 289528d58a37SPierre Jolivet /* attach latest linearization point to the preconditioning matrix */ 28969566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)B, "__SNES_latest_X", (PetscObject)X)); 2897a8054027SBarry Smith 2898e0e3a89bSBarry Smith /* the next line ensures that snes->ksp exists */ 28999566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 29003b4f5425SBarry Smith if (snes->lagpreconditioner == -2) { 29019566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Rebuilding preconditioner exactly once since lag is -2\n")); 29029566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE)); 29033b4f5425SBarry Smith snes->lagpreconditioner = -1; 29043b4f5425SBarry Smith } else if (snes->lagpreconditioner == -1) { 29059566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is -1\n")); 29069566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE)); 290737ec4e1aSPeter Brune } else if (snes->lagpreconditioner > 1 && (snes->iter + snes->pre_iter) % snes->lagpreconditioner) { 290863a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagpreconditioner, snes->iter)); 29099566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE)); 2910d1e9a80fSBarry Smith } else { 29119566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Rebuilding preconditioner\n")); 29129566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE)); 2913a8054027SBarry Smith } 2914a8054027SBarry Smith 29154df93895SStefano Zampini /* monkey business to allow testing Jacobians in multilevel solvers. 29164df93895SStefano Zampini This is needed because the SNESTestXXX interface does not accept vectors and matrices */ 29174df93895SStefano Zampini { 29184df93895SStefano Zampini Vec xsave = snes->vec_sol; 29194df93895SStefano Zampini Mat jacobiansave = snes->jacobian; 29204df93895SStefano Zampini Mat jacobian_presave = snes->jacobian_pre; 29214df93895SStefano Zampini 29224df93895SStefano Zampini snes->vec_sol = X; 29234df93895SStefano Zampini snes->jacobian = A; 29244df93895SStefano Zampini snes->jacobian_pre = B; 2925494a190aSStefano Zampini PetscCall(SNESTestFunction(snes)); 29269566063dSJacob Faibussowitsch PetscCall(SNESTestJacobian(snes)); 2927494a190aSStefano Zampini 29284df93895SStefano Zampini snes->vec_sol = xsave; 29294df93895SStefano Zampini snes->jacobian = jacobiansave; 29304df93895SStefano Zampini snes->jacobian_pre = jacobian_presave; 29314df93895SStefano Zampini } 29324df93895SStefano Zampini 2933693365a8SJed Brown { 2934693365a8SJed Brown PetscBool flag = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_operator = PETSC_FALSE; 29359566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit", NULL, NULL, &flag)); 29369566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw", NULL, NULL, &flag_draw)); 29379566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw_contour", NULL, NULL, &flag_contour)); 29389566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_operator", NULL, NULL, &flag_operator)); 2939693365a8SJed Brown if (flag || flag_draw || flag_contour) { 29400298fd71SBarry Smith Mat Bexp_mine = NULL, Bexp, FDexp; 2941693365a8SJed Brown PetscViewer vdraw, vstdout; 29426b3a5b13SJed Brown PetscBool flg; 2943693365a8SJed Brown if (flag_operator) { 29449566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(A, MATAIJ, &Bexp_mine)); 2945693365a8SJed Brown Bexp = Bexp_mine; 2946693365a8SJed Brown } else { 2947693365a8SJed Brown /* See if the preconditioning matrix can be viewed and added directly */ 29489566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)B, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPIBAIJ, "")); 294994ab13aaSBarry Smith if (flg) Bexp = B; 2950693365a8SJed Brown else { 2951693365a8SJed Brown /* If the "preconditioning" matrix is itself MATSHELL or some other type without direct support */ 29529566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(B, MATAIJ, &Bexp_mine)); 2953693365a8SJed Brown Bexp = Bexp_mine; 2954693365a8SJed Brown } 2955693365a8SJed Brown } 29569566063dSJacob Faibussowitsch PetscCall(MatConvert(Bexp, MATSAME, MAT_INITIAL_MATRIX, &FDexp)); 29579566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobianDefault(snes, X, FDexp, FDexp, NULL)); 29589566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout)); 2959693365a8SJed Brown if (flag_draw || flag_contour) { 29609566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Explicit Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw)); 29619566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 29620298fd71SBarry Smith } else vdraw = NULL; 29639566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit %s\n", flag_operator ? "Jacobian" : "preconditioning Jacobian")); 29649566063dSJacob Faibussowitsch if (flag) PetscCall(MatView(Bexp, vstdout)); 29659566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(Bexp, vdraw)); 29669566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Finite difference Jacobian\n")); 29679566063dSJacob Faibussowitsch if (flag) PetscCall(MatView(FDexp, vstdout)); 29689566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(FDexp, vdraw)); 29699566063dSJacob Faibussowitsch PetscCall(MatAYPX(FDexp, -1.0, Bexp, SAME_NONZERO_PATTERN)); 29709566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian\n")); 29719566063dSJacob Faibussowitsch if (flag) PetscCall(MatView(FDexp, vstdout)); 2972693365a8SJed Brown if (vdraw) { /* Always use contour for the difference */ 29739566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 29749566063dSJacob Faibussowitsch PetscCall(MatView(FDexp, vdraw)); 29759566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(vdraw)); 2976693365a8SJed Brown } 29779566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw)); 29789566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&vdraw)); 29799566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bexp_mine)); 29809566063dSJacob Faibussowitsch PetscCall(MatDestroy(&FDexp)); 2981693365a8SJed Brown } 2982693365a8SJed Brown } 29834c30e9fbSJed Brown { 29846719d8e4SJed Brown PetscBool flag = PETSC_FALSE, flag_display = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_threshold = PETSC_FALSE; 29856719d8e4SJed Brown PetscReal threshold_atol = PETSC_SQRT_MACHINE_EPSILON, threshold_rtol = 10 * PETSC_SQRT_MACHINE_EPSILON; 29869566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring", NULL, NULL, &flag)); 29879566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_display", NULL, NULL, &flag_display)); 29889566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw", NULL, NULL, &flag_draw)); 29899566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw_contour", NULL, NULL, &flag_contour)); 29909566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold", NULL, NULL, &flag_threshold)); 299127b0f280SBarry Smith if (flag_threshold) { 29929566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_rtol", &threshold_rtol, NULL)); 29939566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_atol", &threshold_atol, NULL)); 299427b0f280SBarry Smith } 29956719d8e4SJed Brown if (flag || flag_display || flag_draw || flag_contour || flag_threshold) { 29964c30e9fbSJed Brown Mat Bfd; 29974c30e9fbSJed Brown PetscViewer vdraw, vstdout; 2998335efc43SPeter Brune MatColoring coloring; 29994c30e9fbSJed Brown ISColoring iscoloring; 30004c30e9fbSJed Brown MatFDColoring matfdcoloring; 30018434afd1SBarry Smith SNESFunctionFn *func; 30024c30e9fbSJed Brown void *funcctx; 30036719d8e4SJed Brown PetscReal norm1, norm2, normmax; 30044c30e9fbSJed Brown 30059566063dSJacob Faibussowitsch PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &Bfd)); 30069566063dSJacob Faibussowitsch PetscCall(MatColoringCreate(Bfd, &coloring)); 30079566063dSJacob Faibussowitsch PetscCall(MatColoringSetType(coloring, MATCOLORINGSL)); 30089566063dSJacob Faibussowitsch PetscCall(MatColoringSetFromOptions(coloring)); 30099566063dSJacob Faibussowitsch PetscCall(MatColoringApply(coloring, &iscoloring)); 30109566063dSJacob Faibussowitsch PetscCall(MatColoringDestroy(&coloring)); 30119566063dSJacob Faibussowitsch PetscCall(MatFDColoringCreate(Bfd, iscoloring, &matfdcoloring)); 30129566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFromOptions(matfdcoloring)); 30139566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetUp(Bfd, iscoloring, matfdcoloring)); 30149566063dSJacob Faibussowitsch PetscCall(ISColoringDestroy(&iscoloring)); 30154c30e9fbSJed Brown 30164c30e9fbSJed Brown /* This method of getting the function is currently unreliable since it doesn't work for DM local functions. */ 30179566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, &func, &funcctx)); 30189566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFunction(matfdcoloring, (PetscErrorCode(*)(void))func, funcctx)); 30199566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)matfdcoloring, ((PetscObject)snes)->prefix)); 30209566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)matfdcoloring, "coloring_")); 30219566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFromOptions(matfdcoloring)); 30229566063dSJacob Faibussowitsch PetscCall(MatFDColoringApply(Bfd, matfdcoloring, X, snes)); 30239566063dSJacob Faibussowitsch PetscCall(MatFDColoringDestroy(&matfdcoloring)); 30244c30e9fbSJed Brown 30259566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout)); 30264c30e9fbSJed Brown if (flag_draw || flag_contour) { 30279566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Colored Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw)); 30289566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 30290298fd71SBarry Smith } else vdraw = NULL; 30309566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit preconditioning Jacobian\n")); 30319566063dSJacob Faibussowitsch if (flag_display) PetscCall(MatView(B, vstdout)); 30329566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(B, vdraw)); 30339566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Colored Finite difference Jacobian\n")); 30349566063dSJacob Faibussowitsch if (flag_display) PetscCall(MatView(Bfd, vstdout)); 30359566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(Bfd, vdraw)); 30369566063dSJacob Faibussowitsch PetscCall(MatAYPX(Bfd, -1.0, B, SAME_NONZERO_PATTERN)); 30379566063dSJacob Faibussowitsch PetscCall(MatNorm(Bfd, NORM_1, &norm1)); 30389566063dSJacob Faibussowitsch PetscCall(MatNorm(Bfd, NORM_FROBENIUS, &norm2)); 30399566063dSJacob Faibussowitsch PetscCall(MatNorm(Bfd, NORM_MAX, &normmax)); 30409566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian, norm1=%g normFrob=%g normmax=%g\n", (double)norm1, (double)norm2, (double)normmax)); 30419566063dSJacob Faibussowitsch if (flag_display) PetscCall(MatView(Bfd, vstdout)); 30424c30e9fbSJed Brown if (vdraw) { /* Always use contour for the difference */ 30439566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 30449566063dSJacob Faibussowitsch PetscCall(MatView(Bfd, vdraw)); 30459566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(vdraw)); 30464c30e9fbSJed Brown } 30479566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw)); 30486719d8e4SJed Brown 30496719d8e4SJed Brown if (flag_threshold) { 30506719d8e4SJed Brown PetscInt bs, rstart, rend, i; 30519566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(B, &bs)); 30529566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(B, &rstart, &rend)); 30536719d8e4SJed Brown for (i = rstart; i < rend; i++) { 30546719d8e4SJed Brown const PetscScalar *ba, *ca; 30556719d8e4SJed Brown const PetscInt *bj, *cj; 30566719d8e4SJed Brown PetscInt bn, cn, j, maxentrycol = -1, maxdiffcol = -1, maxrdiffcol = -1; 30576719d8e4SJed Brown PetscReal maxentry = 0, maxdiff = 0, maxrdiff = 0; 30589566063dSJacob Faibussowitsch PetscCall(MatGetRow(B, i, &bn, &bj, &ba)); 30599566063dSJacob Faibussowitsch PetscCall(MatGetRow(Bfd, i, &cn, &cj, &ca)); 30605f80ce2aSJacob Faibussowitsch PetscCheck(bn == cn, ((PetscObject)A)->comm, PETSC_ERR_PLIB, "Unexpected different nonzero pattern in -snes_compare_coloring_threshold"); 30616719d8e4SJed Brown for (j = 0; j < bn; j++) { 30626719d8e4SJed Brown PetscReal rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j])); 30636719d8e4SJed Brown if (PetscAbsScalar(ba[j]) > PetscAbs(maxentry)) { 30646719d8e4SJed Brown maxentrycol = bj[j]; 30656719d8e4SJed Brown maxentry = PetscRealPart(ba[j]); 30666719d8e4SJed Brown } 30676719d8e4SJed Brown if (PetscAbsScalar(ca[j]) > PetscAbs(maxdiff)) { 30686719d8e4SJed Brown maxdiffcol = bj[j]; 30696719d8e4SJed Brown maxdiff = PetscRealPart(ca[j]); 30706719d8e4SJed Brown } 30716719d8e4SJed Brown if (rdiff > maxrdiff) { 30726719d8e4SJed Brown maxrdiffcol = bj[j]; 30736719d8e4SJed Brown maxrdiff = rdiff; 30746719d8e4SJed Brown } 30756719d8e4SJed Brown } 30766719d8e4SJed Brown if (maxrdiff > 1) { 307763a3b9bcSJacob 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)); 30786719d8e4SJed Brown for (j = 0; j < bn; j++) { 30796719d8e4SJed Brown PetscReal rdiff; 30806719d8e4SJed Brown rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j])); 308148a46eb9SPierre Jolivet if (rdiff > 1) PetscCall(PetscViewerASCIIPrintf(vstdout, " (%" PetscInt_FMT ",%g:%g)", bj[j], (double)PetscRealPart(ba[j]), (double)PetscRealPart(ca[j]))); 30826719d8e4SJed Brown } 308363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "\n")); 30846719d8e4SJed Brown } 30859566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(B, i, &bn, &bj, &ba)); 30869566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(Bfd, i, &cn, &cj, &ca)); 30876719d8e4SJed Brown } 30886719d8e4SJed Brown } 30899566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&vdraw)); 30909566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bfd)); 30914c30e9fbSJed Brown } 30924c30e9fbSJed Brown } 30933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30949b94acceSBarry Smith } 30959b94acceSBarry Smith 30969b94acceSBarry Smith /*@C 30979b94acceSBarry Smith SNESSetJacobian - Sets the function to compute Jacobian as well as the 3098044dda88SLois Curfman McInnes location to store the matrix. 30999b94acceSBarry Smith 3100c3339decSBarry Smith Logically Collective 3101c7afd0dbSLois Curfman McInnes 31029b94acceSBarry Smith Input Parameters: 3103f6dfbefdSBarry Smith + snes - the `SNES` context 3104e5d3d808SBarry Smith . Amat - the matrix that defines the (approximate) Jacobian 3105dc4c0fb0SBarry Smith . Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`. 31068434afd1SBarry Smith . J - Jacobian evaluation routine (if `NULL` then `SNES` retains any previously set value), see `SNESJacobianFn` for details 3107c7afd0dbSLois Curfman McInnes - ctx - [optional] user-defined context for private data for the 3108dc4c0fb0SBarry Smith Jacobian evaluation routine (may be `NULL`) (if `NULL` then `SNES` retains any previously set value) 3109dc4c0fb0SBarry Smith 3110dc4c0fb0SBarry Smith Level: beginner 31119b94acceSBarry Smith 31129b94acceSBarry Smith Notes: 3113dc4c0fb0SBarry Smith If the `Amat` matrix and `Pmat` matrix are different you must call `MatAssemblyBegin()`/`MatAssemblyEnd()` on 311416913363SBarry Smith each matrix. 311516913363SBarry Smith 3116dc4c0fb0SBarry Smith If you know the operator `Amat` has a null space you can use `MatSetNullSpace()` and `MatSetTransposeNullSpace()` to supply the null 3117dc4c0fb0SBarry Smith space to `Amat` and the `KSP` solvers will automatically use that null space as needed during the solution process. 3118895c21f2SBarry Smith 3119dc4c0fb0SBarry Smith If using `SNESComputeJacobianDefaultColor()` to assemble a Jacobian, the `ctx` argument 3120f6dfbefdSBarry Smith must be a `MatFDColoring`. 3121a8a26c1eSJed Brown 3122c3cc8fd1SJed Brown Other defect-correction schemes can be used by computing a different matrix in place of the Jacobian. One common 3123f6dfbefdSBarry Smith example is to use the "Picard linearization" which only differentiates through the highest order parts of each term using `SNESSetPicard()` 3124c3cc8fd1SJed Brown 31251cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSPSetOperators()`, `SNESSetFunction()`, `MatMFFDComputeJacobian()`, `SNESComputeJacobianDefaultColor()`, `MatStructure`, 31268434afd1SBarry Smith `SNESSetPicard()`, `SNESJacobianFn`, `SNESFunctionFn` 31279b94acceSBarry Smith @*/ 31288434afd1SBarry Smith PetscErrorCode SNESSetJacobian(SNES snes, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx) 3129d71ae5a4SJacob Faibussowitsch { 31306cab3a1bSJed Brown DM dm; 31313a7fca6bSBarry Smith 31323a40ed3dSBarry Smith PetscFunctionBegin; 31330700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3134e5d3d808SBarry Smith if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2); 3135e5d3d808SBarry Smith if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3); 3136e5d3d808SBarry Smith if (Amat) PetscCheckSameComm(snes, 1, Amat, 2); 3137e5d3d808SBarry Smith if (Pmat) PetscCheckSameComm(snes, 1, Pmat, 3); 31389566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 31399566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, J, ctx)); 3140e5d3d808SBarry Smith if (Amat) { 31419566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)Amat)); 31429566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian)); 3143f5af7f23SKarl Rupp 3144e5d3d808SBarry Smith snes->jacobian = Amat; 31453a7fca6bSBarry Smith } 3146e5d3d808SBarry Smith if (Pmat) { 31479566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)Pmat)); 31489566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian_pre)); 3149f5af7f23SKarl Rupp 3150e5d3d808SBarry Smith snes->jacobian_pre = Pmat; 31513a7fca6bSBarry Smith } 31523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 31539b94acceSBarry Smith } 315462fef451SLois Curfman McInnes 3155c2aafc4cSSatish Balay /*@C 3156b4fd4287SBarry Smith SNESGetJacobian - Returns the Jacobian matrix and optionally the user 3157b4fd4287SBarry Smith provided context for evaluating the Jacobian. 3158b4fd4287SBarry Smith 3159420bcc1bSBarry Smith Not Collective, but `Mat` object will be parallel if `SNES` is 3160c7afd0dbSLois Curfman McInnes 3161b4fd4287SBarry Smith Input Parameter: 3162b4fd4287SBarry Smith . snes - the nonlinear solver context 3163b4fd4287SBarry Smith 3164b4fd4287SBarry Smith Output Parameters: 3165dc4c0fb0SBarry Smith + Amat - location to stash (approximate) Jacobian matrix (or `NULL`) 3166dc4c0fb0SBarry Smith . Pmat - location to stash matrix used to compute the preconditioner (or `NULL`) 31678434afd1SBarry Smith . J - location to put Jacobian function (or `NULL`), for calling sequence see `SNESJacobianFn` 3168dc4c0fb0SBarry Smith - ctx - location to stash Jacobian ctx (or `NULL`) 3169fee21e36SBarry Smith 317036851e7fSLois Curfman McInnes Level: advanced 317136851e7fSLois Curfman McInnes 31728434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `Mat`, `SNESSetJacobian()`, `SNESComputeJacobian()`, `SNESJacobianFn`, `SNESGetFunction()` 3173b4fd4287SBarry Smith @*/ 31748434afd1SBarry Smith PetscErrorCode SNESGetJacobian(SNES snes, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx) 3175d71ae5a4SJacob Faibussowitsch { 31766cab3a1bSJed Brown DM dm; 31776cab3a1bSJed Brown 31783a40ed3dSBarry Smith PetscFunctionBegin; 31790700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3180e5d3d808SBarry Smith if (Amat) *Amat = snes->jacobian; 3181e5d3d808SBarry Smith if (Pmat) *Pmat = snes->jacobian_pre; 31829566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 3183800f99ffSJeremy L Thompson PetscCall(DMSNESGetJacobian(dm, J, ctx)); 31843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3185b4fd4287SBarry Smith } 3186b4fd4287SBarry Smith 3187d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetDefaultComputeJacobian(SNES snes) 3188d71ae5a4SJacob Faibussowitsch { 318958b371f3SBarry Smith DM dm; 319058b371f3SBarry Smith DMSNES sdm; 319158b371f3SBarry Smith 319258b371f3SBarry Smith PetscFunctionBegin; 31939566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 31949566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 319558b371f3SBarry Smith if (!sdm->ops->computejacobian && snes->jacobian_pre) { 319658b371f3SBarry Smith DM dm; 319758b371f3SBarry Smith PetscBool isdense, ismf; 319858b371f3SBarry Smith 31999566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 32009566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &isdense, MATSEQDENSE, MATMPIDENSE, MATDENSE, NULL)); 32019566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &ismf, MATMFFD, MATSHELL, NULL)); 320258b371f3SBarry Smith if (isdense) { 32039566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefault, NULL)); 320458b371f3SBarry Smith } else if (!ismf) { 32059566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefaultColor, NULL)); 320658b371f3SBarry Smith } 320758b371f3SBarry Smith } 32083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 320958b371f3SBarry Smith } 321058b371f3SBarry Smith 32119b94acceSBarry Smith /*@ 32129b94acceSBarry Smith SNESSetUp - Sets up the internal data structures for the later use 3213272ac6f2SLois Curfman McInnes of a nonlinear solver. 32149b94acceSBarry Smith 3215c3339decSBarry Smith Collective 3216fee21e36SBarry Smith 32172fe279fdSBarry Smith Input Parameter: 3218f6dfbefdSBarry Smith . snes - the `SNES` context 3219c7afd0dbSLois Curfman McInnes 3220dc4c0fb0SBarry Smith Level: advanced 3221dc4c0fb0SBarry Smith 3222f6dfbefdSBarry Smith Note: 3223f6dfbefdSBarry Smith For basic use of the `SNES` solvers the user need not explicitly call 3224f6dfbefdSBarry Smith `SNESSetUp()`, since these actions will automatically occur during 3225f6dfbefdSBarry Smith the call to `SNESSolve()`. However, if one wishes to control this 3226f6dfbefdSBarry Smith phase separately, `SNESSetUp()` should be called after `SNESCreate()` 3227f6dfbefdSBarry Smith and optional routines of the form SNESSetXXX(), but before `SNESSolve()`. 3228272ac6f2SLois Curfman McInnes 32291cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`, `SNESDestroy()` 32309b94acceSBarry Smith @*/ 3231d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUp(SNES snes) 3232d71ae5a4SJacob Faibussowitsch { 32336cab3a1bSJed Brown DM dm; 3234942e3340SBarry Smith DMSNES sdm; 3235c35f09e5SBarry Smith SNESLineSearch linesearch, pclinesearch; 32366e2a1849SPeter Brune void *lsprectx, *lspostctx; 32379b5c1c08SStefano Zampini PetscBool mf_operator, mf; 32389b5c1c08SStefano Zampini Vec f, fpc; 32399b5c1c08SStefano Zampini void *funcctx; 32409b5c1c08SStefano Zampini void *jacctx, *appctx; 32419b5c1c08SStefano Zampini Mat j, jpre; 32426b2b7091SBarry Smith PetscErrorCode (*precheck)(SNESLineSearch, Vec, Vec, PetscBool *, void *); 32436b2b7091SBarry Smith PetscErrorCode (*postcheck)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *); 32448434afd1SBarry Smith SNESFunctionFn *func; 32458434afd1SBarry Smith SNESJacobianFn *jac; 32463a40ed3dSBarry Smith 32473a40ed3dSBarry Smith PetscFunctionBegin; 32480700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 32493ba16761SJacob Faibussowitsch if (snes->setupcalled) PetscFunctionReturn(PETSC_SUCCESS); 3250fc8bc0e3SRichard Tran Mills PetscCall(PetscLogEventBegin(SNES_SetUp, snes, 0, 0, 0)); 32519b94acceSBarry Smith 325248a46eb9SPierre Jolivet if (!((PetscObject)snes)->type_name) PetscCall(SNESSetType(snes, SNESNEWTONLS)); 325385385478SLisandro Dalcin 32549566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &snes->vec_func, NULL, NULL)); 325558c9b817SLisandro Dalcin 32569566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 32579566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 32589566063dSJacob Faibussowitsch PetscCall(SNESSetDefaultComputeJacobian(snes)); 325958b371f3SBarry Smith 326048a46eb9SPierre Jolivet if (!snes->vec_func) PetscCall(DMCreateGlobalVector(dm, &snes->vec_func)); 3261efd51863SBarry Smith 326248a46eb9SPierre Jolivet if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 3263b710008aSBarry Smith 3264d8d34be6SBarry Smith if (snes->linesearch) { 32659566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 32669566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetFunction(snes->linesearch, SNESComputeFunction)); 3267d8d34be6SBarry Smith } 32689e764e56SPeter Brune 32699b5c1c08SStefano Zampini PetscCall(SNESGetUseMatrixFree(snes, &mf_operator, &mf)); 3270b552625fSStefano Zampini if (snes->npc && snes->npcside == PC_LEFT) { 3271172a4300SPeter Brune snes->mf = PETSC_TRUE; 3272172a4300SPeter Brune snes->mf_operator = PETSC_FALSE; 3273172a4300SPeter Brune } 3274d8f46077SPeter Brune 3275efd4aadfSBarry Smith if (snes->npc) { 32766e2a1849SPeter Brune /* copy the DM over */ 32779566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 32789566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes->npc, dm)); 32796e2a1849SPeter Brune 32809566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &f, &func, &funcctx)); 32819566063dSJacob Faibussowitsch PetscCall(VecDuplicate(f, &fpc)); 32829566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes->npc, fpc, func, funcctx)); 32839566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, &j, &jpre, &jac, &jacctx)); 32849566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes->npc, j, jpre, jac, jacctx)); 32859566063dSJacob Faibussowitsch PetscCall(SNESGetApplicationContext(snes, &appctx)); 32869566063dSJacob Faibussowitsch PetscCall(SNESSetApplicationContext(snes->npc, appctx)); 32879b5c1c08SStefano Zampini PetscCall(SNESSetUseMatrixFree(snes->npc, mf_operator, mf)); 32889566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fpc)); 32896e2a1849SPeter Brune 32906e2a1849SPeter Brune /* copy the function pointers over */ 32919566063dSJacob Faibussowitsch PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)snes->npc)); 32926e2a1849SPeter Brune 32936e2a1849SPeter Brune /* default to 1 iteration */ 32949566063dSJacob Faibussowitsch PetscCall(SNESSetTolerances(snes->npc, 0.0, 0.0, 0.0, 1, snes->npc->max_funcs)); 3295efd4aadfSBarry Smith if (snes->npcside == PC_RIGHT) { 32969566063dSJacob Faibussowitsch PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_FINAL_ONLY)); 3297a9936a0cSPeter Brune } else { 32989566063dSJacob Faibussowitsch PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_NONE)); 3299a9936a0cSPeter Brune } 33009566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes->npc)); 33016e2a1849SPeter Brune 33026e2a1849SPeter Brune /* copy the line search context over */ 3303d8d34be6SBarry Smith if (snes->linesearch && snes->npc->linesearch) { 33049566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &linesearch)); 33059566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes->npc, &pclinesearch)); 33069566063dSJacob Faibussowitsch PetscCall(SNESLineSearchGetPreCheck(linesearch, &precheck, &lsprectx)); 33079566063dSJacob Faibussowitsch PetscCall(SNESLineSearchGetPostCheck(linesearch, &postcheck, &lspostctx)); 33089566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetPreCheck(pclinesearch, precheck, lsprectx)); 33099566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetPostCheck(pclinesearch, postcheck, lspostctx)); 33109566063dSJacob Faibussowitsch PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch)); 33116e2a1849SPeter Brune } 3312d8d34be6SBarry Smith } 33131baa6e33SBarry Smith if (snes->mf) PetscCall(SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version)); 33149927e4dfSBarry Smith if (snes->ops->usercompute && !snes->user) PetscCallBack("SNES callback compute application context", (*snes->ops->usercompute)(snes, (void **)&snes->user)); 33156e2a1849SPeter Brune 331637ec4e1aSPeter Brune snes->jac_iter = 0; 331737ec4e1aSPeter Brune snes->pre_iter = 0; 331837ec4e1aSPeter Brune 3319dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, setup); 332058c9b817SLisandro Dalcin 33219566063dSJacob Faibussowitsch PetscCall(SNESSetDefaultComputeJacobian(snes)); 332258b371f3SBarry Smith 3323b552625fSStefano Zampini if (snes->npc && snes->npcside == PC_LEFT) { 33246c67d002SPeter Brune if (snes->functype == SNES_FUNCTION_PRECONDITIONED) { 3325d8d34be6SBarry Smith if (snes->linesearch) { 33269566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &linesearch)); 33279566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunctionDefaultNPC)); 33286c67d002SPeter Brune } 33296c67d002SPeter Brune } 3330d8d34be6SBarry Smith } 3331fc8bc0e3SRichard Tran Mills PetscCall(PetscLogEventEnd(SNES_SetUp, snes, 0, 0, 0)); 33327aaed0d8SBarry Smith snes->setupcalled = PETSC_TRUE; 33333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 33349b94acceSBarry Smith } 33359b94acceSBarry Smith 333637596af1SLisandro Dalcin /*@ 3337f6dfbefdSBarry Smith SNESReset - Resets a `SNES` context to the snessetupcalled = 0 state and removes any allocated `Vec`s and `Mat`s 333837596af1SLisandro Dalcin 3339c3339decSBarry Smith Collective 334037596af1SLisandro Dalcin 334137596af1SLisandro Dalcin Input Parameter: 3342f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 334337596af1SLisandro Dalcin 3344d25893d9SBarry Smith Level: intermediate 3345d25893d9SBarry Smith 334695452b02SPatrick Sanan Notes: 3347f6dfbefdSBarry Smith Call this if you wish to reuse a `SNES` but with different size vectors 334837596af1SLisandro Dalcin 3349f6dfbefdSBarry Smith Also calls the application context destroy routine set with `SNESSetComputeApplicationContext()` 3350f6dfbefdSBarry Smith 33511cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESDestroy()`, `SNESCreate()`, `SNESSetUp()`, `SNESSolve()` 335237596af1SLisandro Dalcin @*/ 3353d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESReset(SNES snes) 3354d71ae5a4SJacob Faibussowitsch { 335537596af1SLisandro Dalcin PetscFunctionBegin; 335637596af1SLisandro Dalcin PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3357d25893d9SBarry Smith if (snes->ops->userdestroy && snes->user) { 33589927e4dfSBarry Smith PetscCallBack("SNES callback destroy application context", (*snes->ops->userdestroy)((void **)&snes->user)); 33590298fd71SBarry Smith snes->user = NULL; 3360d25893d9SBarry Smith } 33611baa6e33SBarry Smith if (snes->npc) PetscCall(SNESReset(snes->npc)); 33628a23116dSBarry Smith 3363dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, reset); 33641baa6e33SBarry Smith if (snes->ksp) PetscCall(KSPReset(snes->ksp)); 33659e764e56SPeter Brune 33661baa6e33SBarry Smith if (snes->linesearch) PetscCall(SNESLineSearchReset(snes->linesearch)); 33679e764e56SPeter Brune 33689566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_rhs)); 33699566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol)); 33709566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol_update)); 33719566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_func)); 33729566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian)); 33739566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian_pre)); 33749566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->picard)); 33759566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(snes->nwork, &snes->work)); 33769566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(snes->nvwork, &snes->vwork)); 3377f5af7f23SKarl Rupp 337840fdac6aSLawrence Mitchell snes->alwayscomputesfinalresidual = PETSC_FALSE; 337940fdac6aSLawrence Mitchell 338037596af1SLisandro Dalcin snes->nwork = snes->nvwork = 0; 338137596af1SLisandro Dalcin snes->setupcalled = PETSC_FALSE; 33823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 338337596af1SLisandro Dalcin } 338437596af1SLisandro Dalcin 338552baeb72SSatish Balay /*@ 3386420bcc1bSBarry Smith SNESConvergedReasonViewCancel - Clears all the reason view functions for a `SNES` object provided with `SNESConvergedReasonViewSet()` 3387c4421ceaSFande Kong 3388c3339decSBarry Smith Collective 3389c4421ceaSFande Kong 3390c4421ceaSFande Kong Input Parameter: 3391f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 3392c4421ceaSFande Kong 3393c4421ceaSFande Kong Level: intermediate 3394c4421ceaSFande Kong 3395420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESReset()`, `SNESConvergedReasonViewSet()` 3396c4421ceaSFande Kong @*/ 3397d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewCancel(SNES snes) 3398d71ae5a4SJacob Faibussowitsch { 3399c4421ceaSFande Kong PetscInt i; 3400c4421ceaSFande Kong 3401c4421ceaSFande Kong PetscFunctionBegin; 3402c4421ceaSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3403c4421ceaSFande Kong for (i = 0; i < snes->numberreasonviews; i++) { 340448a46eb9SPierre Jolivet if (snes->reasonviewdestroy[i]) PetscCall((*snes->reasonviewdestroy[i])(&snes->reasonviewcontext[i])); 3405c4421ceaSFande Kong } 3406c4421ceaSFande Kong snes->numberreasonviews = 0; 34073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3408c4421ceaSFande Kong } 3409c4421ceaSFande Kong 34100764c050SBarry Smith /*@ 34119b94acceSBarry Smith SNESDestroy - Destroys the nonlinear solver context that was created 3412f6dfbefdSBarry Smith with `SNESCreate()`. 34139b94acceSBarry Smith 3414c3339decSBarry Smith Collective 3415c7afd0dbSLois Curfman McInnes 34169b94acceSBarry Smith Input Parameter: 3417f6dfbefdSBarry Smith . snes - the `SNES` context 34189b94acceSBarry Smith 341936851e7fSLois Curfman McInnes Level: beginner 342036851e7fSLois Curfman McInnes 34211cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()` 34229b94acceSBarry Smith @*/ 3423d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESDestroy(SNES *snes) 3424d71ae5a4SJacob Faibussowitsch { 34253a40ed3dSBarry Smith PetscFunctionBegin; 34263ba16761SJacob Faibussowitsch if (!*snes) PetscFunctionReturn(PETSC_SUCCESS); 3427f4f49eeaSPierre Jolivet PetscValidHeaderSpecific(*snes, SNES_CLASSID, 1); 3428f4f49eeaSPierre Jolivet if (--((PetscObject)*snes)->refct > 0) { 34299371c9d4SSatish Balay *snes = NULL; 34303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 34319371c9d4SSatish Balay } 3432d4bb536fSBarry Smith 3433f4f49eeaSPierre Jolivet PetscCall(SNESReset(*snes)); 34349566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&(*snes)->npc)); 34356b8b9a38SLisandro Dalcin 3436e04113cfSBarry Smith /* if memory was published with SAWs then destroy it */ 34379566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsViewOff((PetscObject)*snes)); 3438f4f49eeaSPierre Jolivet PetscTryTypeMethod(*snes, destroy); 34396d4c513bSLisandro Dalcin 34409566063dSJacob Faibussowitsch if ((*snes)->dm) PetscCall(DMCoarsenHookRemove((*snes)->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, *snes)); 34419566063dSJacob Faibussowitsch PetscCall(DMDestroy(&(*snes)->dm)); 34429566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&(*snes)->ksp)); 34439566063dSJacob Faibussowitsch PetscCall(SNESLineSearchDestroy(&(*snes)->linesearch)); 34446b8b9a38SLisandro Dalcin 34459566063dSJacob Faibussowitsch PetscCall(PetscFree((*snes)->kspconvctx)); 344648a46eb9SPierre Jolivet if ((*snes)->ops->convergeddestroy) PetscCall((*(*snes)->ops->convergeddestroy)((*snes)->cnvP)); 344748a46eb9SPierre Jolivet if ((*snes)->conv_hist_alloc) PetscCall(PetscFree2((*snes)->conv_hist, (*snes)->conv_hist_its)); 3448f4f49eeaSPierre Jolivet PetscCall(SNESMonitorCancel(*snes)); 3449f4f49eeaSPierre Jolivet PetscCall(SNESConvergedReasonViewCancel(*snes)); 34509566063dSJacob Faibussowitsch PetscCall(PetscHeaderDestroy(snes)); 34513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 34529b94acceSBarry Smith } 34539b94acceSBarry Smith 34549b94acceSBarry Smith /* ----------- Routines to set solver parameters ---------- */ 34559b94acceSBarry Smith 3456a8054027SBarry Smith /*@ 3457a8054027SBarry Smith SNESSetLagPreconditioner - Determines when the preconditioner is rebuilt in the nonlinear solve. 3458a8054027SBarry Smith 3459c3339decSBarry Smith Logically Collective 3460a8054027SBarry Smith 3461a8054027SBarry Smith Input Parameters: 3462f6dfbefdSBarry Smith + snes - the `SNES` context 3463d8e291bfSBarry Smith - lag - 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time 34643b4f5425SBarry Smith the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that 3465a8054027SBarry Smith 3466a8054027SBarry Smith Options Database Keys: 3467420bcc1bSBarry Smith + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple `SNESSolve()` 34683d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 3469420bcc1bSBarry Smith . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple `SNESSolve()` 34703d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 3471a8054027SBarry Smith 3472dc4c0fb0SBarry Smith Level: intermediate 3473dc4c0fb0SBarry Smith 3474420bcc1bSBarry Smith Notes: 3475a8054027SBarry Smith The default is 1 3476420bcc1bSBarry Smith 3477f6dfbefdSBarry Smith The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagPreconditionerPersists()` was called 3478d8e291bfSBarry Smith 3479f6dfbefdSBarry Smith `SNESSetLagPreconditionerPersists()` allows using the same uniform lagging (for example every second linear solve) across multiple nonlinear solves. 3480a8054027SBarry Smith 34811cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetLagPreconditionerPersists()`, 3482f6dfbefdSBarry Smith `SNESSetLagJacobianPersists()`, `SNES`, `SNESSolve()` 3483a8054027SBarry Smith @*/ 3484d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditioner(SNES snes, PetscInt lag) 3485d71ae5a4SJacob Faibussowitsch { 3486a8054027SBarry Smith PetscFunctionBegin; 34870700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 34885f80ce2aSJacob Faibussowitsch PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater"); 34895f80ce2aSJacob Faibussowitsch PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0"); 3490c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, lag, 2); 3491a8054027SBarry Smith snes->lagpreconditioner = lag; 34923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3493a8054027SBarry Smith } 3494a8054027SBarry Smith 3495efd51863SBarry Smith /*@ 3496f6dfbefdSBarry Smith SNESSetGridSequence - sets the number of steps of grid sequencing that `SNES` will do 3497efd51863SBarry Smith 3498c3339decSBarry Smith Logically Collective 3499efd51863SBarry Smith 3500efd51863SBarry Smith Input Parameters: 3501f6dfbefdSBarry Smith + snes - the `SNES` context 3502efd51863SBarry Smith - steps - the number of refinements to do, defaults to 0 3503efd51863SBarry Smith 3504f6dfbefdSBarry Smith Options Database Key: 350567b8a455SSatish Balay . -snes_grid_sequence <steps> - Use grid sequencing to generate initial guess 3506efd51863SBarry Smith 3507efd51863SBarry Smith Level: intermediate 3508efd51863SBarry Smith 3509f6dfbefdSBarry Smith Note: 3510f6dfbefdSBarry Smith Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing. 3511c0df2a02SJed Brown 3512420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetGridSequence()`, 3513420bcc1bSBarry Smith `SNESetDM()` 3514efd51863SBarry Smith @*/ 3515d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetGridSequence(SNES snes, PetscInt steps) 3516d71ae5a4SJacob Faibussowitsch { 3517efd51863SBarry Smith PetscFunctionBegin; 3518efd51863SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3519efd51863SBarry Smith PetscValidLogicalCollectiveInt(snes, steps, 2); 3520efd51863SBarry Smith snes->gridsequence = steps; 35213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3522efd51863SBarry Smith } 3523efd51863SBarry Smith 3524fa19ca70SBarry Smith /*@ 3525f6dfbefdSBarry Smith SNESGetGridSequence - gets the number of steps of grid sequencing that `SNES` will do 3526fa19ca70SBarry Smith 3527c3339decSBarry Smith Logically Collective 3528fa19ca70SBarry Smith 3529fa19ca70SBarry Smith Input Parameter: 3530f6dfbefdSBarry Smith . snes - the `SNES` context 3531fa19ca70SBarry Smith 3532fa19ca70SBarry Smith Output Parameter: 3533fa19ca70SBarry Smith . steps - the number of refinements to do, defaults to 0 3534fa19ca70SBarry Smith 3535fa19ca70SBarry Smith Level: intermediate 3536fa19ca70SBarry Smith 35371cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetGridSequence()` 3538fa19ca70SBarry Smith @*/ 3539d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetGridSequence(SNES snes, PetscInt *steps) 3540d71ae5a4SJacob Faibussowitsch { 3541fa19ca70SBarry Smith PetscFunctionBegin; 3542fa19ca70SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3543fa19ca70SBarry Smith *steps = snes->gridsequence; 35443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3545fa19ca70SBarry Smith } 3546fa19ca70SBarry Smith 3547a8054027SBarry Smith /*@ 3548f6dfbefdSBarry Smith SNESGetLagPreconditioner - Return how often the preconditioner is rebuilt 3549a8054027SBarry Smith 35503f9fe445SBarry Smith Not Collective 3551a8054027SBarry Smith 3552a8054027SBarry Smith Input Parameter: 3553f6dfbefdSBarry Smith . snes - the `SNES` context 3554a8054027SBarry Smith 3555a8054027SBarry Smith Output Parameter: 3556a8054027SBarry 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 35573b4f5425SBarry Smith the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that 3558a8054027SBarry Smith 3559dc4c0fb0SBarry Smith Level: intermediate 3560dc4c0fb0SBarry Smith 3561a8054027SBarry Smith Notes: 3562a8054027SBarry Smith The default is 1 3563f6dfbefdSBarry Smith 3564a8054027SBarry Smith The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 3565a8054027SBarry Smith 35661cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3567a8054027SBarry Smith @*/ 3568d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagPreconditioner(SNES snes, PetscInt *lag) 3569d71ae5a4SJacob Faibussowitsch { 3570a8054027SBarry Smith PetscFunctionBegin; 35710700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3572a8054027SBarry Smith *lag = snes->lagpreconditioner; 35733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3574a8054027SBarry Smith } 3575a8054027SBarry Smith 3576e35cf81dSBarry Smith /*@ 3577f6dfbefdSBarry Smith SNESSetLagJacobian - Set when the Jacobian is rebuilt in the nonlinear solve. See `SNESSetLagPreconditioner()` for determining how 3578e35cf81dSBarry Smith often the preconditioner is rebuilt. 3579e35cf81dSBarry Smith 3580c3339decSBarry Smith Logically Collective 3581e35cf81dSBarry Smith 3582e35cf81dSBarry Smith Input Parameters: 3583f6dfbefdSBarry Smith + snes - the `SNES` context 3584e35cf81dSBarry 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 3585fe3ffe1eSBarry Smith the Jacobian is built etc. -2 means rebuild at next chance but then never again 3586e35cf81dSBarry Smith 3587e35cf81dSBarry Smith Options Database Keys: 358879a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 35893d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 359079a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 35913d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag. 3592e35cf81dSBarry Smith 3593dc4c0fb0SBarry Smith Level: intermediate 3594dc4c0fb0SBarry Smith 3595e35cf81dSBarry Smith Notes: 3596e35cf81dSBarry Smith The default is 1 3597f6dfbefdSBarry Smith 3598e35cf81dSBarry Smith The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 3599f6dfbefdSBarry Smith 3600fe3ffe1eSBarry 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 3601fe3ffe1eSBarry Smith at the next Newton step but never again (unless it is reset to another value) 3602e35cf81dSBarry Smith 36031cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagPreconditioner()`, `SNESGetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3604e35cf81dSBarry Smith @*/ 3605d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobian(SNES snes, PetscInt lag) 3606d71ae5a4SJacob Faibussowitsch { 3607e35cf81dSBarry Smith PetscFunctionBegin; 36080700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 36095f80ce2aSJacob Faibussowitsch PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater"); 36105f80ce2aSJacob Faibussowitsch PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0"); 3611c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, lag, 2); 3612e35cf81dSBarry Smith snes->lagjacobian = lag; 36133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3614e35cf81dSBarry Smith } 3615e35cf81dSBarry Smith 3616e35cf81dSBarry Smith /*@ 3617f6dfbefdSBarry Smith SNESGetLagJacobian - Get how often the Jacobian is rebuilt. See `SNESGetLagPreconditioner()` to determine when the preconditioner is rebuilt 3618e35cf81dSBarry Smith 36193f9fe445SBarry Smith Not Collective 3620e35cf81dSBarry Smith 3621e35cf81dSBarry Smith Input Parameter: 3622f6dfbefdSBarry Smith . snes - the `SNES` context 3623e35cf81dSBarry Smith 3624e35cf81dSBarry Smith Output Parameter: 3625e35cf81dSBarry 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 3626e35cf81dSBarry Smith the Jacobian is built etc. 3627e35cf81dSBarry Smith 3628dc4c0fb0SBarry Smith Level: intermediate 3629dc4c0fb0SBarry Smith 3630e35cf81dSBarry Smith Notes: 3631e35cf81dSBarry Smith The default is 1 3632f6dfbefdSBarry Smith 3633f6dfbefdSBarry Smith The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagJacobianPersists()` was called. 3634e35cf81dSBarry Smith 36351cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetLagJacobian()`, `SNESSetLagPreconditioner()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3636e35cf81dSBarry Smith 3637e35cf81dSBarry Smith @*/ 3638d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagJacobian(SNES snes, PetscInt *lag) 3639d71ae5a4SJacob Faibussowitsch { 3640e35cf81dSBarry Smith PetscFunctionBegin; 36410700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3642e35cf81dSBarry Smith *lag = snes->lagjacobian; 36433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3644e35cf81dSBarry Smith } 3645e35cf81dSBarry Smith 364637ec4e1aSPeter Brune /*@ 3647f6dfbefdSBarry Smith SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple nonlinear solves 364837ec4e1aSPeter Brune 3649c3339decSBarry Smith Logically collective 365037ec4e1aSPeter Brune 3651d8d19677SJose E. Roman Input Parameters: 3652f6dfbefdSBarry Smith + snes - the `SNES` context 36539d7e2deaSPeter Brune - flg - jacobian lagging persists if true 365437ec4e1aSPeter Brune 365537ec4e1aSPeter Brune Options Database Keys: 365679a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 36573d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 365879a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 36593d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 36603d5a8a6aSBarry Smith 3661dc4c0fb0SBarry Smith Level: advanced 3662dc4c0fb0SBarry Smith 366395452b02SPatrick Sanan Notes: 3664420bcc1bSBarry Smith Normally when `SNESSetLagJacobian()` is used, the Jacobian is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior 3665f6dfbefdSBarry Smith 366695452b02SPatrick Sanan This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by 366737ec4e1aSPeter Brune several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several 366837ec4e1aSPeter Brune timesteps may present huge efficiency gains. 366937ec4e1aSPeter Brune 367042747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditionerPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()` 367137ec4e1aSPeter Brune @*/ 3672d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobianPersists(SNES snes, PetscBool flg) 3673d71ae5a4SJacob Faibussowitsch { 367437ec4e1aSPeter Brune PetscFunctionBegin; 367537ec4e1aSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 367637ec4e1aSPeter Brune PetscValidLogicalCollectiveBool(snes, flg, 2); 367737ec4e1aSPeter Brune snes->lagjac_persist = flg; 36783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 367937ec4e1aSPeter Brune } 368037ec4e1aSPeter Brune 368137ec4e1aSPeter Brune /*@ 3682d8e291bfSBarry Smith SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple nonlinear solves 368337ec4e1aSPeter Brune 3684c3339decSBarry Smith Logically Collective 368537ec4e1aSPeter Brune 3686d8d19677SJose E. Roman Input Parameters: 3687f6dfbefdSBarry Smith + snes - the `SNES` context 36889d7e2deaSPeter Brune - flg - preconditioner lagging persists if true 368937ec4e1aSPeter Brune 369037ec4e1aSPeter Brune Options Database Keys: 369179a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 36923d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 369379a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 36943d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 369537ec4e1aSPeter Brune 3696dc4c0fb0SBarry Smith Level: developer 3697dc4c0fb0SBarry Smith 369895452b02SPatrick Sanan Notes: 3699420bcc1bSBarry Smith Normally when `SNESSetLagPreconditioner()` is used, the preconditioner is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior 3700f6dfbefdSBarry Smith 370195452b02SPatrick Sanan This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale 370237ec4e1aSPeter Brune by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over 370337ec4e1aSPeter Brune several timesteps may present huge efficiency gains. 370437ec4e1aSPeter Brune 37051cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobianPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagPreconditioner()` 370637ec4e1aSPeter Brune @*/ 3707d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes, PetscBool flg) 3708d71ae5a4SJacob Faibussowitsch { 370937ec4e1aSPeter Brune PetscFunctionBegin; 371037ec4e1aSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 371137ec4e1aSPeter Brune PetscValidLogicalCollectiveBool(snes, flg, 2); 371237ec4e1aSPeter Brune snes->lagpre_persist = flg; 37133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 371437ec4e1aSPeter Brune } 371537ec4e1aSPeter Brune 37169b94acceSBarry Smith /*@ 3717f6dfbefdSBarry Smith SNESSetForceIteration - force `SNESSolve()` to take at least one iteration regardless of the initial residual norm 3718be5caee7SBarry Smith 3719c3339decSBarry Smith Logically Collective 3720be5caee7SBarry Smith 3721be5caee7SBarry Smith Input Parameters: 3722f6dfbefdSBarry Smith + snes - the `SNES` context 3723f6dfbefdSBarry Smith - force - `PETSC_TRUE` require at least one iteration 3724be5caee7SBarry Smith 3725f6dfbefdSBarry Smith Options Database Key: 3726be5caee7SBarry Smith . -snes_force_iteration <force> - Sets forcing an iteration 3727be5caee7SBarry Smith 3728dc4c0fb0SBarry Smith Level: intermediate 3729dc4c0fb0SBarry Smith 3730f6dfbefdSBarry Smith Note: 3731f6dfbefdSBarry Smith This is used sometimes with `TS` to prevent `TS` from detecting a false steady state solution 3732be5caee7SBarry Smith 37331cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `TS`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()` 3734be5caee7SBarry Smith @*/ 3735d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetForceIteration(SNES snes, PetscBool force) 3736d71ae5a4SJacob Faibussowitsch { 3737be5caee7SBarry Smith PetscFunctionBegin; 3738be5caee7SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3739be5caee7SBarry Smith snes->forceiteration = force; 37403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3741be5caee7SBarry Smith } 3742be5caee7SBarry Smith 374385216dc7SFande Kong /*@ 3744f6dfbefdSBarry Smith SNESGetForceIteration - Check whether or not `SNESSolve()` take at least one iteration regardless of the initial residual norm 374585216dc7SFande Kong 3746c3339decSBarry Smith Logically Collective 374785216dc7SFande Kong 37482fe279fdSBarry Smith Input Parameter: 3749f6dfbefdSBarry Smith . snes - the `SNES` context 375085216dc7SFande Kong 375185216dc7SFande Kong Output Parameter: 3752dc4c0fb0SBarry Smith . force - `PETSC_TRUE` requires at least one iteration. 375385216dc7SFande Kong 375406dd6b0eSSatish Balay Level: intermediate 375506dd6b0eSSatish Balay 37561cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetForceIteration()`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()` 375785216dc7SFande Kong @*/ 3758d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetForceIteration(SNES snes, PetscBool *force) 3759d71ae5a4SJacob Faibussowitsch { 376085216dc7SFande Kong PetscFunctionBegin; 376185216dc7SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 376285216dc7SFande Kong *force = snes->forceiteration; 37633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 376485216dc7SFande Kong } 3765be5caee7SBarry Smith 3766be5caee7SBarry Smith /*@ 3767f6dfbefdSBarry Smith SNESSetTolerances - Sets `SNES` various parameters used in convergence tests. 37689b94acceSBarry Smith 3769c3339decSBarry Smith Logically Collective 3770c7afd0dbSLois Curfman McInnes 37719b94acceSBarry Smith Input Parameters: 3772f6dfbefdSBarry Smith + snes - the `SNES` context 377370441072SBarry Smith . abstol - absolute convergence tolerance 377433174efeSLois Curfman McInnes . rtol - relative convergence tolerance 37755358d0d4SBarry Smith . stol - convergence tolerance in terms of the norm of the change in the solution between steps, || delta x || < stol*|| x || 3776f6dfbefdSBarry Smith . maxit - maximum number of iterations, default 50. 3777f6dfbefdSBarry Smith - maxf - maximum number of function evaluations (-1 indicates no limit), default 1000 3778fee21e36SBarry Smith 377933174efeSLois Curfman McInnes Options Database Keys: 378070441072SBarry Smith + -snes_atol <abstol> - Sets abstol 3781c7afd0dbSLois Curfman McInnes . -snes_rtol <rtol> - Sets rtol 3782c7afd0dbSLois Curfman McInnes . -snes_stol <stol> - Sets stol 3783c7afd0dbSLois Curfman McInnes . -snes_max_it <maxit> - Sets maxit 3784c7afd0dbSLois Curfman McInnes - -snes_max_funcs <maxf> - Sets maxf 37859b94acceSBarry Smith 378636851e7fSLois Curfman McInnes Level: intermediate 378736851e7fSLois Curfman McInnes 378800677de2SStefano Zampini .seealso: [](ch_snes), `SNESSolve()`, `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()`, `SNESSetForceIteration()` 37899b94acceSBarry Smith @*/ 3790d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTolerances(SNES snes, PetscReal abstol, PetscReal rtol, PetscReal stol, PetscInt maxit, PetscInt maxf) 3791d71ae5a4SJacob Faibussowitsch { 37923a40ed3dSBarry Smith PetscFunctionBegin; 37930700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3794c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, abstol, 2); 3795c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, rtol, 3); 3796c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, stol, 4); 3797c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, maxit, 5); 3798c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, maxf, 6); 3799c5eb9154SBarry Smith 380013bcc0bdSJacob Faibussowitsch if (abstol != (PetscReal)PETSC_DEFAULT) { 38015f80ce2aSJacob Faibussowitsch PetscCheck(abstol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)abstol); 3802ab54825eSJed Brown snes->abstol = abstol; 3803ab54825eSJed Brown } 380413bcc0bdSJacob Faibussowitsch if (rtol != (PetscReal)PETSC_DEFAULT) { 38055f80ce2aSJacob 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); 3806ab54825eSJed Brown snes->rtol = rtol; 3807ab54825eSJed Brown } 380813bcc0bdSJacob Faibussowitsch if (stol != (PetscReal)PETSC_DEFAULT) { 38095f80ce2aSJacob Faibussowitsch PetscCheck(stol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Step tolerance %g must be non-negative", (double)stol); 3810c60f73f4SPeter Brune snes->stol = stol; 3811ab54825eSJed Brown } 3812ab54825eSJed Brown if (maxit != PETSC_DEFAULT) { 381363a3b9bcSJacob Faibussowitsch PetscCheck(maxit >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", maxit); 3814ab54825eSJed Brown snes->max_its = maxit; 3815ab54825eSJed Brown } 3816ab54825eSJed Brown if (maxf != PETSC_DEFAULT) { 381763a3b9bcSJacob Faibussowitsch PetscCheck(maxf >= -1, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations %" PetscInt_FMT " must be -1 or nonnegative", maxf); 3818ab54825eSJed Brown snes->max_funcs = maxf; 3819ab54825eSJed Brown } 382088976e71SPeter Brune snes->tolerancesset = PETSC_TRUE; 38213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 38229b94acceSBarry Smith } 38239b94acceSBarry Smith 3824e4d06f11SPatrick Farrell /*@ 3825f6dfbefdSBarry Smith SNESSetDivergenceTolerance - Sets the divergence tolerance used for the `SNES` divergence test. 3826e4d06f11SPatrick Farrell 3827c3339decSBarry Smith Logically Collective 3828e4d06f11SPatrick Farrell 3829e4d06f11SPatrick Farrell Input Parameters: 3830f6dfbefdSBarry Smith + snes - the `SNES` context 3831f6dfbefdSBarry Smith - divtol - the divergence tolerance. Use -1 to deactivate the test, default is 1e4 3832e4d06f11SPatrick Farrell 3833f6dfbefdSBarry Smith Options Database Key: 3834dc4c0fb0SBarry Smith . -snes_divergence_tolerance <divtol> - Sets `divtol` 3835e4d06f11SPatrick Farrell 3836e4d06f11SPatrick Farrell Level: intermediate 3837e4d06f11SPatrick Farrell 38381cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetTolerances()`, `SNESGetDivergenceTolerance` 3839e4d06f11SPatrick Farrell @*/ 3840d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDivergenceTolerance(SNES snes, PetscReal divtol) 3841d71ae5a4SJacob Faibussowitsch { 3842e4d06f11SPatrick Farrell PetscFunctionBegin; 3843e4d06f11SPatrick Farrell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3844e4d06f11SPatrick Farrell PetscValidLogicalCollectiveReal(snes, divtol, 2); 3845e4d06f11SPatrick Farrell 384613bcc0bdSJacob Faibussowitsch if (divtol != (PetscReal)PETSC_DEFAULT) { 3847e4d06f11SPatrick Farrell snes->divtol = divtol; 38489371c9d4SSatish Balay } else { 3849e4d06f11SPatrick Farrell snes->divtol = 1.0e4; 3850e4d06f11SPatrick Farrell } 38513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3852e4d06f11SPatrick Farrell } 3853e4d06f11SPatrick Farrell 38549b94acceSBarry Smith /*@ 385533174efeSLois Curfman McInnes SNESGetTolerances - Gets various parameters used in convergence tests. 385633174efeSLois Curfman McInnes 3857c7afd0dbSLois Curfman McInnes Not Collective 3858c7afd0dbSLois Curfman McInnes 385933174efeSLois Curfman McInnes Input Parameters: 3860f6dfbefdSBarry Smith + snes - the `SNES` context 386185385478SLisandro Dalcin . atol - absolute convergence tolerance 386233174efeSLois Curfman McInnes . rtol - relative convergence tolerance 386333174efeSLois Curfman McInnes . stol - convergence tolerance in terms of the norm 386433174efeSLois Curfman McInnes of the change in the solution between steps 386533174efeSLois Curfman McInnes . maxit - maximum number of iterations 3866c7afd0dbSLois Curfman McInnes - maxf - maximum number of function evaluations 3867fee21e36SBarry Smith 386836851e7fSLois Curfman McInnes Level: intermediate 386936851e7fSLois Curfman McInnes 3870dc4c0fb0SBarry Smith Note: 3871dc4c0fb0SBarry Smith The user can specify `NULL` for any parameter that is not needed. 3872dc4c0fb0SBarry Smith 38731cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTolerances()` 387433174efeSLois Curfman McInnes @*/ 3875d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetTolerances(SNES snes, PetscReal *atol, PetscReal *rtol, PetscReal *stol, PetscInt *maxit, PetscInt *maxf) 3876d71ae5a4SJacob Faibussowitsch { 38773a40ed3dSBarry Smith PetscFunctionBegin; 38780700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 387985385478SLisandro Dalcin if (atol) *atol = snes->abstol; 388033174efeSLois Curfman McInnes if (rtol) *rtol = snes->rtol; 3881c60f73f4SPeter Brune if (stol) *stol = snes->stol; 388233174efeSLois Curfman McInnes if (maxit) *maxit = snes->max_its; 388333174efeSLois Curfman McInnes if (maxf) *maxf = snes->max_funcs; 38843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 388533174efeSLois Curfman McInnes } 388633174efeSLois Curfman McInnes 3887e4d06f11SPatrick Farrell /*@ 3888e4d06f11SPatrick Farrell SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test. 3889e4d06f11SPatrick Farrell 3890e4d06f11SPatrick Farrell Not Collective 3891e4d06f11SPatrick Farrell 3892e4d06f11SPatrick Farrell Input Parameters: 3893f6dfbefdSBarry Smith + snes - the `SNES` context 3894e4d06f11SPatrick Farrell - divtol - divergence tolerance 3895e4d06f11SPatrick Farrell 3896e4d06f11SPatrick Farrell Level: intermediate 3897e4d06f11SPatrick Farrell 38981cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetDivergenceTolerance()` 3899e4d06f11SPatrick Farrell @*/ 3900d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDivergenceTolerance(SNES snes, PetscReal *divtol) 3901d71ae5a4SJacob Faibussowitsch { 3902e4d06f11SPatrick Farrell PetscFunctionBegin; 3903e4d06f11SPatrick Farrell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3904e4d06f11SPatrick Farrell if (divtol) *divtol = snes->divtol; 39053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3906e4d06f11SPatrick Farrell } 3907e4d06f11SPatrick Farrell 390833174efeSLois Curfman McInnes /*@ 39099b94acceSBarry Smith SNESSetTrustRegionTolerance - Sets the trust region parameter tolerance. 39109b94acceSBarry Smith 3911c3339decSBarry Smith Logically Collective 3912fee21e36SBarry Smith 3913c7afd0dbSLois Curfman McInnes Input Parameters: 3914f6dfbefdSBarry Smith + snes - the `SNES` context 3915c7afd0dbSLois Curfman McInnes - tol - tolerance 3916c7afd0dbSLois Curfman McInnes 39179b94acceSBarry Smith Options Database Key: 39184a221d59SStefano Zampini . -snes_tr_tol <tol> - Sets tol 39199b94acceSBarry Smith 392036851e7fSLois Curfman McInnes Level: intermediate 392136851e7fSLois Curfman McInnes 39229bcc50f1SBarry Smith Developer Note: 39239bcc50f1SBarry Smith Should be SNESTrustRegionSetTolerance() 39249bcc50f1SBarry Smith 39251cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNEWTONTR`, `SNESSetTolerances()` 39269b94acceSBarry Smith @*/ 3927d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTrustRegionTolerance(SNES snes, PetscReal tol) 3928d71ae5a4SJacob Faibussowitsch { 39293a40ed3dSBarry Smith PetscFunctionBegin; 39300700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3931c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, tol, 2); 39329b94acceSBarry Smith snes->deltatol = tol; 39333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 39349b94acceSBarry Smith } 39359b94acceSBarry Smith 39366ba87a44SLisandro Dalcin PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *); 39376ba87a44SLisandro Dalcin 3938d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorLGRange(SNES snes, PetscInt n, PetscReal rnorm, void *monctx) 3939d71ae5a4SJacob Faibussowitsch { 3940b271bb04SBarry Smith PetscDrawLG lg; 3941b271bb04SBarry Smith PetscReal x, y, per; 3942b271bb04SBarry Smith PetscViewer v = (PetscViewer)monctx; 3943b271bb04SBarry Smith static PetscReal prev; /* should be in the context */ 3944b271bb04SBarry Smith PetscDraw draw; 3945b271bb04SBarry Smith 3946459f5d12SBarry Smith PetscFunctionBegin; 39474d4332d5SBarry Smith PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 4); 39489566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 0, &lg)); 39499566063dSJacob Faibussowitsch if (!n) PetscCall(PetscDrawLGReset(lg)); 39509566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 39519566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "Residual norm")); 3952b271bb04SBarry Smith x = (PetscReal)n; 395377b4d14cSPeter Brune if (rnorm > 0.0) y = PetscLog10Real(rnorm); 395494c9c6d3SKarl Rupp else y = -15.0; 39559566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 39566934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 39579566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 39589566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 3959b271bb04SBarry Smith } 3960b271bb04SBarry Smith 39619566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 1, &lg)); 39629566063dSJacob Faibussowitsch if (!n) PetscCall(PetscDrawLGReset(lg)); 39639566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 3964aaa8cc7dSPierre Jolivet PetscCall(PetscDrawSetTitle(draw, "% elements > .2*max element")); 39659566063dSJacob Faibussowitsch PetscCall(SNESMonitorRange_Private(snes, n, &per)); 3966b271bb04SBarry Smith x = (PetscReal)n; 3967b271bb04SBarry Smith y = 100.0 * per; 39689566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 39696934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 39709566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 39719566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 3972b271bb04SBarry Smith } 3973b271bb04SBarry Smith 39749566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 2, &lg)); 39759371c9d4SSatish Balay if (!n) { 39769371c9d4SSatish Balay prev = rnorm; 39779371c9d4SSatish Balay PetscCall(PetscDrawLGReset(lg)); 39789371c9d4SSatish Balay } 39799566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 39809566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm")); 3981b271bb04SBarry Smith x = (PetscReal)n; 3982b271bb04SBarry Smith y = (prev - rnorm) / prev; 39839566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 39846934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 39859566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 39869566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 3987b271bb04SBarry Smith } 3988b271bb04SBarry Smith 39899566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 3, &lg)); 39909566063dSJacob Faibussowitsch if (!n) PetscCall(PetscDrawLGReset(lg)); 39919566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 39929566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm*(% > .2 max)")); 3993b271bb04SBarry Smith x = (PetscReal)n; 3994b271bb04SBarry Smith y = (prev - rnorm) / (prev * per); 3995b271bb04SBarry Smith if (n > 2) { /*skip initial crazy value */ 39969566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 3997b271bb04SBarry Smith } 39986934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 39999566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 40009566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 4001b271bb04SBarry Smith } 4002b271bb04SBarry Smith prev = rnorm; 40033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4004b271bb04SBarry Smith } 4005b271bb04SBarry Smith 4006228d79bcSJed Brown /*@ 40072d157150SStefano Zampini SNESConverged - Run the convergence test and update the `SNESConvergedReason`. 40082d157150SStefano Zampini 40092d157150SStefano Zampini Collective 40102d157150SStefano Zampini 40112d157150SStefano Zampini Input Parameters: 40122d157150SStefano Zampini + snes - the `SNES` context 40132d157150SStefano Zampini . it - current iteration 40142d157150SStefano Zampini . xnorm - 2-norm of current iterate 40152d157150SStefano Zampini . snorm - 2-norm of current step 40162d157150SStefano Zampini - fnorm - 2-norm of function 40172d157150SStefano Zampini 40182d157150SStefano Zampini Level: developer 40192d157150SStefano Zampini 40202d157150SStefano Zampini Note: 4021420bcc1bSBarry Smith This routine is called by the `SNESSolve()` implementations. 40222d157150SStefano Zampini It does not typically need to be called by the user. 40232d157150SStefano Zampini 4024be50c303SSatish Balay .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`, `SNESGetConvergenceTest()` 40252d157150SStefano Zampini @*/ 40262d157150SStefano Zampini PetscErrorCode SNESConverged(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm) 40272d157150SStefano Zampini { 40282d157150SStefano Zampini PetscFunctionBegin; 40292d157150SStefano Zampini if (!snes->reason) { 40302d157150SStefano Zampini if (snes->normschedule == SNES_NORM_ALWAYS) PetscUseTypeMethod(snes, converged, it, xnorm, snorm, fnorm, &snes->reason, snes->cnvP); 40312d157150SStefano Zampini if (it == snes->max_its && !snes->reason) { 40322d157150SStefano Zampini if (snes->normschedule == SNES_NORM_ALWAYS) { 40332d157150SStefano Zampini PetscCall(PetscInfo(snes, "Maximum number of iterations has been reached: %" PetscInt_FMT "\n", snes->max_its)); 40342d157150SStefano Zampini snes->reason = SNES_DIVERGED_MAX_IT; 40352d157150SStefano Zampini } else snes->reason = SNES_CONVERGED_ITS; 40362d157150SStefano Zampini } 40372d157150SStefano Zampini } 40382d157150SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 40392d157150SStefano Zampini } 40402d157150SStefano Zampini 40412d157150SStefano Zampini /*@ 4042228d79bcSJed Brown SNESMonitor - runs the user provided monitor routines, if they exist 4043228d79bcSJed Brown 4044c3339decSBarry Smith Collective 4045228d79bcSJed Brown 4046228d79bcSJed Brown Input Parameters: 4047f6dfbefdSBarry Smith + snes - nonlinear solver context obtained from `SNESCreate()` 4048228d79bcSJed Brown . iter - iteration number 4049228d79bcSJed Brown - rnorm - relative norm of the residual 4050228d79bcSJed Brown 4051dc4c0fb0SBarry Smith Level: developer 4052dc4c0fb0SBarry Smith 4053f6dfbefdSBarry Smith Note: 4054420bcc1bSBarry Smith This routine is called by the `SNESSolve()` implementations. 4055228d79bcSJed Brown It does not typically need to be called by the user. 4056228d79bcSJed Brown 40571cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorSet()` 4058228d79bcSJed Brown @*/ 4059d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitor(SNES snes, PetscInt iter, PetscReal rnorm) 4060d71ae5a4SJacob Faibussowitsch { 40617a03ce2fSLisandro Dalcin PetscInt i, n = snes->numbermonitors; 40627a03ce2fSLisandro Dalcin 40637a03ce2fSLisandro Dalcin PetscFunctionBegin; 40645f3c5e7aSBarry Smith if (n > 0) SNESCheckFunctionNorm(snes, rnorm); 40659566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(snes->vec_sol)); 406648a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall((*snes->monitor[i])(snes, iter, rnorm, snes->monitorcontext[i])); 40679566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(snes->vec_sol)); 40683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 40697a03ce2fSLisandro Dalcin } 40707a03ce2fSLisandro Dalcin 40719b94acceSBarry Smith /* ------------ Routines to set performance monitoring options ----------- */ 40729b94acceSBarry Smith 4073bf388a1fSBarry Smith /*MC 4074f6dfbefdSBarry Smith SNESMonitorFunction - functional form passed to `SNESMonitorSet()` to monitor convergence of nonlinear solver 4075bf388a1fSBarry Smith 4076bf388a1fSBarry Smith Synopsis: 4077aaa7dc30SBarry Smith #include <petscsnes.h> 407837fdd005SBarry Smith PetscErrorCode SNESMonitorFunction(SNES snes, PetscInt its, PetscReal norm, void *mctx) 4079bf388a1fSBarry Smith 4080c3339decSBarry Smith Collective 40811843f636SBarry Smith 40821843f636SBarry Smith Input Parameters: 4083f6dfbefdSBarry Smith + snes - the `SNES` context 4084bf388a1fSBarry Smith . its - iteration number 4085bf388a1fSBarry Smith . norm - 2-norm function value (may be estimated) 4086bf388a1fSBarry Smith - mctx - [optional] monitoring context 4087bf388a1fSBarry Smith 4088878cb397SSatish Balay Level: advanced 4089878cb397SSatish Balay 40901cc06b55SBarry Smith .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSet()`, `SNESMonitorGet()` 4091bf388a1fSBarry Smith M*/ 4092bf388a1fSBarry Smith 40939b94acceSBarry Smith /*@C 4094a6570f20SBarry Smith SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every 40959b94acceSBarry Smith iteration of the nonlinear solver to display the iteration's 40969b94acceSBarry Smith progress. 40979b94acceSBarry Smith 4098c3339decSBarry Smith Logically Collective 4099fee21e36SBarry Smith 4100c7afd0dbSLois Curfman McInnes Input Parameters: 4101f6dfbefdSBarry Smith + snes - the `SNES` context 410220f4b53cSBarry Smith . f - the monitor function, for the calling sequence see `SNESMonitorFunction` 4103420bcc1bSBarry Smith . mctx - [optional] user-defined context for private data for the monitor routine (use `NULL` if no context is desired) 4104dc4c0fb0SBarry Smith - monitordestroy - [optional] routine that frees monitor context (may be `NULL`) 41059b94acceSBarry Smith 41069665c990SLois Curfman McInnes Options Database Keys: 4107f6dfbefdSBarry Smith + -snes_monitor - sets `SNESMonitorDefault()` 4108798534f6SMatthew G. Knepley . -snes_monitor draw::draw_lg - sets line graph monitor, 4109dc4c0fb0SBarry 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 4110c7afd0dbSLois Curfman McInnes the options database. 41119665c990SLois Curfman McInnes 4112dc4c0fb0SBarry Smith Level: intermediate 4113dc4c0fb0SBarry Smith 4114f6dfbefdSBarry Smith Note: 41156bc08f3fSLois Curfman McInnes Several different monitoring routines may be set by calling 4116f6dfbefdSBarry Smith `SNESMonitorSet()` multiple times; all will be called in the 41176bc08f3fSLois Curfman McInnes order in which they were set. 4118639f9d9dSBarry Smith 4119420bcc1bSBarry Smith Fortran Note: 4120f6dfbefdSBarry Smith Only a single monitor function can be set for each `SNES` object 4121025f1a04SBarry Smith 41221cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESMonitorDefault()`, `SNESMonitorCancel()`, `SNESMonitorFunction` 41239b94acceSBarry Smith @*/ 4124d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorSet(SNES snes, PetscErrorCode (*f)(SNES, PetscInt, PetscReal, void *), void *mctx, PetscErrorCode (*monitordestroy)(void **)) 4125d71ae5a4SJacob Faibussowitsch { 4126b90d0a6eSBarry Smith PetscInt i; 412778064530SBarry Smith PetscBool identical; 4128b90d0a6eSBarry Smith 41293a40ed3dSBarry Smith PetscFunctionBegin; 41300700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4131b90d0a6eSBarry Smith for (i = 0; i < snes->numbermonitors; i++) { 41329566063dSJacob Faibussowitsch PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, mctx, monitordestroy, (PetscErrorCode(*)(void))snes->monitor[i], snes->monitorcontext[i], snes->monitordestroy[i], &identical)); 41333ba16761SJacob Faibussowitsch if (identical) PetscFunctionReturn(PETSC_SUCCESS); 4134649052a6SBarry Smith } 41355f80ce2aSJacob Faibussowitsch PetscCheck(snes->numbermonitors < MAXSNESMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set"); 41366e4dcb14SBarry Smith snes->monitor[snes->numbermonitors] = f; 4137b8a78c4aSBarry Smith snes->monitordestroy[snes->numbermonitors] = monitordestroy; 4138639f9d9dSBarry Smith snes->monitorcontext[snes->numbermonitors++] = (void *)mctx; 41393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 41409b94acceSBarry Smith } 41419b94acceSBarry Smith 4142a278d85bSSatish Balay /*@ 4143f6dfbefdSBarry Smith SNESMonitorCancel - Clears all the monitor functions for a `SNES` object. 41445cd90555SBarry Smith 4145c3339decSBarry Smith Logically Collective 4146c7afd0dbSLois Curfman McInnes 41472fe279fdSBarry Smith Input Parameter: 4148f6dfbefdSBarry Smith . snes - the `SNES` context 41495cd90555SBarry Smith 41501a480d89SAdministrator Options Database Key: 4151a6570f20SBarry Smith . -snes_monitor_cancel - cancels all monitors that have been hardwired 4152dc4c0fb0SBarry Smith into a code by calls to `SNESMonitorSet()`, but does not cancel those 4153c7afd0dbSLois Curfman McInnes set via the options database 41545cd90555SBarry Smith 4155dc4c0fb0SBarry Smith Level: intermediate 4156dc4c0fb0SBarry Smith 4157f6dfbefdSBarry Smith Note: 4158f6dfbefdSBarry Smith There is no way to clear one specific monitor from a `SNES` object. 41595cd90555SBarry Smith 41601cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorGet()`, `SNESMonitorDefault()`, `SNESMonitorSet()` 41615cd90555SBarry Smith @*/ 4162d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorCancel(SNES snes) 4163d71ae5a4SJacob Faibussowitsch { 4164d952e501SBarry Smith PetscInt i; 4165d952e501SBarry Smith 41665cd90555SBarry Smith PetscFunctionBegin; 41670700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4168d952e501SBarry Smith for (i = 0; i < snes->numbermonitors; i++) { 416948a46eb9SPierre Jolivet if (snes->monitordestroy[i]) PetscCall((*snes->monitordestroy[i])(&snes->monitorcontext[i])); 4170d952e501SBarry Smith } 41715cd90555SBarry Smith snes->numbermonitors = 0; 41723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 41735cd90555SBarry Smith } 41745cd90555SBarry Smith 4175bf388a1fSBarry Smith /*MC 4176bf388a1fSBarry Smith SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver 4177bf388a1fSBarry Smith 4178bf388a1fSBarry Smith Synopsis: 4179aaa7dc30SBarry Smith #include <petscsnes.h> 418037fdd005SBarry Smith PetscErrorCode SNESConvergenceTest(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *cctx) 4181bf388a1fSBarry Smith 4182c3339decSBarry Smith Collective 41831843f636SBarry Smith 41841843f636SBarry Smith Input Parameters: 4185f6dfbefdSBarry Smith + snes - the `SNES` context 4186bf388a1fSBarry Smith . it - current iteration (0 is the first and is before any Newton step) 4187bf388a1fSBarry Smith . xnorm - 2-norm of current iterate 4188bf388a1fSBarry Smith . gnorm - 2-norm of current step 41891843f636SBarry Smith . f - 2-norm of function 41901843f636SBarry Smith - cctx - [optional] convergence context 41911843f636SBarry Smith 41921843f636SBarry Smith Output Parameter: 41931843f636SBarry Smith . reason - reason for convergence/divergence, only needs to be set when convergence or divergence is detected 4194bf388a1fSBarry Smith 4195878cb397SSatish Balay Level: intermediate 4196bf388a1fSBarry Smith 41971cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`, `SNESGetConvergenceTest()` 4198bf388a1fSBarry Smith M*/ 4199bf388a1fSBarry Smith 42009b94acceSBarry Smith /*@C 42019b94acceSBarry Smith SNESSetConvergenceTest - Sets the function that is to be used 42029b94acceSBarry Smith to test for convergence of the nonlinear iterative solution. 42039b94acceSBarry Smith 4204c3339decSBarry Smith Logically Collective 4205fee21e36SBarry Smith 4206c7afd0dbSLois Curfman McInnes Input Parameters: 4207f6dfbefdSBarry Smith + snes - the `SNES` context 4208e4094ef1SJacob Faibussowitsch . SNESConvergenceTestFunction - routine to test for convergence 4209dc4c0fb0SBarry Smith . cctx - [optional] context for private data for the convergence routine (may be `NULL`) 4210dc4c0fb0SBarry Smith - destroy - [optional] destructor for the context (may be `NULL`; `PETSC_NULL_FUNCTION` in Fortran) 42119b94acceSBarry Smith 421236851e7fSLois Curfman McInnes Level: advanced 421336851e7fSLois Curfman McInnes 42141cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedDefault()`, `SNESConvergedSkip()`, `SNESConvergenceTestFunction` 42159b94acceSBarry Smith @*/ 4216d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceTest(SNES snes, PetscErrorCode (*SNESConvergenceTestFunction)(SNES, PetscInt, PetscReal, PetscReal, PetscReal, SNESConvergedReason *, void *), void *cctx, PetscErrorCode (*destroy)(void *)) 4217d71ae5a4SJacob Faibussowitsch { 42183a40ed3dSBarry Smith PetscFunctionBegin; 42190700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4220e2a6519dSDmitry Karpeev if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip; 42211baa6e33SBarry Smith if (snes->ops->convergeddestroy) PetscCall((*snes->ops->convergeddestroy)(snes->cnvP)); 4222bf388a1fSBarry Smith snes->ops->converged = SNESConvergenceTestFunction; 42237f7931b9SBarry Smith snes->ops->convergeddestroy = destroy; 422485385478SLisandro Dalcin snes->cnvP = cctx; 42253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 42269b94acceSBarry Smith } 42279b94acceSBarry Smith 422852baeb72SSatish Balay /*@ 4229f6dfbefdSBarry Smith SNESGetConvergedReason - Gets the reason the `SNES` iteration was stopped. 4230184914b5SBarry Smith 4231184914b5SBarry Smith Not Collective 4232184914b5SBarry Smith 4233184914b5SBarry Smith Input Parameter: 4234f6dfbefdSBarry Smith . snes - the `SNES` context 4235184914b5SBarry Smith 4236184914b5SBarry Smith Output Parameter: 4237f6dfbefdSBarry Smith . reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` for the individual convergence tests for complete lists 4238184914b5SBarry Smith 4239f6dfbefdSBarry Smith Options Database Key: 42406a4d7782SBarry Smith . -snes_converged_reason - prints the reason to standard out 42416a4d7782SBarry Smith 4242184914b5SBarry Smith Level: intermediate 4243184914b5SBarry Smith 4244f6dfbefdSBarry Smith Note: 4245f6dfbefdSBarry Smith Should only be called after the call the `SNESSolve()` is complete, if it is called earlier it returns the value `SNES__CONVERGED_ITERATING`. 4246184914b5SBarry Smith 42471cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESSetConvergedReason()`, `SNESConvergedReason`, `SNESGetConvergedReasonString()` 4248184914b5SBarry Smith @*/ 4249d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReason(SNES snes, SNESConvergedReason *reason) 4250d71ae5a4SJacob Faibussowitsch { 4251184914b5SBarry Smith PetscFunctionBegin; 42520700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 42534f572ea9SToby Isaac PetscAssertPointer(reason, 2); 4254184914b5SBarry Smith *reason = snes->reason; 42553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4256184914b5SBarry Smith } 4257184914b5SBarry Smith 4258c4421ceaSFande Kong /*@C 4259f6dfbefdSBarry Smith SNESGetConvergedReasonString - Return a human readable string for `SNESConvergedReason` 4260c4421ceaSFande Kong 4261c4421ceaSFande Kong Not Collective 4262c4421ceaSFande Kong 4263c4421ceaSFande Kong Input Parameter: 4264f6dfbefdSBarry Smith . snes - the `SNES` context 4265c4421ceaSFande Kong 4266c4421ceaSFande Kong Output Parameter: 4267dc4c0fb0SBarry Smith . strreason - a human readable string that describes `SNES` converged reason 4268c4421ceaSFande Kong 426999c90e12SSatish Balay Level: beginner 4270c4421ceaSFande Kong 42711cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetConvergedReason()` 4272c4421ceaSFande Kong @*/ 4273d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReasonString(SNES snes, const char **strreason) 4274d71ae5a4SJacob Faibussowitsch { 4275c4421ceaSFande Kong PetscFunctionBegin; 4276c4421ceaSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 42774f572ea9SToby Isaac PetscAssertPointer(strreason, 2); 4278c4421ceaSFande Kong *strreason = SNESConvergedReasons[snes->reason]; 42793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4280c4421ceaSFande Kong } 4281c4421ceaSFande Kong 428233866048SMatthew G. Knepley /*@ 4283f6dfbefdSBarry Smith SNESSetConvergedReason - Sets the reason the `SNES` iteration was stopped. 428433866048SMatthew G. Knepley 428533866048SMatthew G. Knepley Not Collective 428633866048SMatthew G. Knepley 428733866048SMatthew G. Knepley Input Parameters: 4288f6dfbefdSBarry Smith + snes - the `SNES` context 4289f6dfbefdSBarry Smith - reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` or the 429033866048SMatthew G. Knepley manual pages for the individual convergence tests for complete lists 429133866048SMatthew G. Knepley 4292f6dfbefdSBarry Smith Level: developer 4293f6dfbefdSBarry Smith 4294420bcc1bSBarry Smith Developer Note: 4295f6dfbefdSBarry Smith Called inside the various `SNESSolve()` implementations 429633866048SMatthew G. Knepley 42971cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetConvergedReason()`, `SNESSetConvergenceTest()`, `SNESConvergedReason` 429833866048SMatthew G. Knepley @*/ 4299d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergedReason(SNES snes, SNESConvergedReason reason) 4300d71ae5a4SJacob Faibussowitsch { 430133866048SMatthew G. Knepley PetscFunctionBegin; 430233866048SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 43035f3c5e7aSBarry Smith PetscCheck(!snes->errorifnotconverged || reason > 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "SNES code should have previously errored due to negative reason"); 430433866048SMatthew G. Knepley snes->reason = reason; 43053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 430633866048SMatthew G. Knepley } 430733866048SMatthew G. Knepley 4308c9005455SLois Curfman McInnes /*@ 4309420bcc1bSBarry Smith SNESSetConvergenceHistory - Sets the arrays used to hold the convergence history. 4310c9005455SLois Curfman McInnes 4311c3339decSBarry Smith Logically Collective 4312fee21e36SBarry Smith 4313c7afd0dbSLois Curfman McInnes Input Parameters: 4314f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 43158c7482ecSBarry Smith . a - array to hold history, this array will contain the function norms computed at each step 4316cd5578b5SBarry Smith . its - integer array holds the number of linear iterations for each solve. 4317420bcc1bSBarry Smith . na - size of `a` and `its` 4318f6dfbefdSBarry Smith - reset - `PETSC_TRUE` indicates each new nonlinear solve resets the history counter to zero, 4319758f92a0SBarry Smith else it continues storing new values for new nonlinear solves after the old ones 4320c7afd0dbSLois Curfman McInnes 4321dc4c0fb0SBarry Smith Level: intermediate 4322dc4c0fb0SBarry Smith 4323308dcc3eSBarry Smith Notes: 4324dc4c0fb0SBarry Smith If 'a' and 'its' are `NULL` then space is allocated for the history. If 'na' `PETSC_DECIDE` or `PETSC_DEFAULT` then a 4325308dcc3eSBarry Smith default array of length 10000 is allocated. 4326308dcc3eSBarry Smith 4327c9005455SLois Curfman McInnes This routine is useful, e.g., when running a code for purposes 4328c9005455SLois Curfman McInnes of accurate performance monitoring, when no I/O should be done 4329c9005455SLois Curfman McInnes during the section of code that is being timed. 4330c9005455SLois Curfman McInnes 4331420bcc1bSBarry Smith If the arrays run out of space after a number of iterations then the later values are not saved in the history 4332420bcc1bSBarry Smith 43331cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetConvergenceHistory()` 4334c9005455SLois Curfman McInnes @*/ 4335d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceHistory(SNES snes, PetscReal a[], PetscInt its[], PetscInt na, PetscBool reset) 4336d71ae5a4SJacob Faibussowitsch { 43373a40ed3dSBarry Smith PetscFunctionBegin; 43380700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 43394f572ea9SToby Isaac if (a) PetscAssertPointer(a, 2); 43404f572ea9SToby Isaac if (its) PetscAssertPointer(its, 3); 43417a1ec6d4SBarry Smith if (!a) { 4342308dcc3eSBarry Smith if (na == PETSC_DECIDE || na == PETSC_DEFAULT) na = 1000; 43439566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(na, &a, na, &its)); 4344071fcb05SBarry Smith snes->conv_hist_alloc = PETSC_TRUE; 4345308dcc3eSBarry Smith } 4346c9005455SLois Curfman McInnes snes->conv_hist = a; 4347758f92a0SBarry Smith snes->conv_hist_its = its; 4348115dd874SBarry Smith snes->conv_hist_max = (size_t)na; 4349a12bc48fSLisandro Dalcin snes->conv_hist_len = 0; 4350758f92a0SBarry Smith snes->conv_hist_reset = reset; 43513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4352758f92a0SBarry Smith } 4353758f92a0SBarry Smith 4354d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB) 4355c6db04a5SJed Brown #include <engine.h> /* MATLAB include file */ 4356c6db04a5SJed Brown #include <mex.h> /* MATLAB include file */ 435799e0435eSBarry Smith 4358d71ae5a4SJacob Faibussowitsch PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes) 4359d71ae5a4SJacob Faibussowitsch { 4360308dcc3eSBarry Smith mxArray *mat; 4361308dcc3eSBarry Smith PetscInt i; 4362308dcc3eSBarry Smith PetscReal *ar; 4363308dcc3eSBarry Smith 4364308dcc3eSBarry Smith mat = mxCreateDoubleMatrix(snes->conv_hist_len, 1, mxREAL); 4365308dcc3eSBarry Smith ar = (PetscReal *)mxGetData(mat); 4366f5af7f23SKarl Rupp for (i = 0; i < snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i]; 436711cc89d2SBarry Smith return mat; 4368308dcc3eSBarry Smith } 4369308dcc3eSBarry Smith #endif 4370308dcc3eSBarry Smith 43710c4c9dddSBarry Smith /*@C 4372420bcc1bSBarry Smith SNESGetConvergenceHistory - Gets the arrays used to hold the convergence history. 4373758f92a0SBarry Smith 43743f9fe445SBarry Smith Not Collective 4375758f92a0SBarry Smith 4376758f92a0SBarry Smith Input Parameter: 4377f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 4378758f92a0SBarry Smith 4379758f92a0SBarry Smith Output Parameters: 4380f6dfbefdSBarry Smith + a - array to hold history, usually was set with `SNESSetConvergenceHistory()` 4381758f92a0SBarry Smith . its - integer array holds the number of linear iterations (or 4382758f92a0SBarry Smith negative if not converged) for each solve. 438320f4b53cSBarry Smith - na - size of `a` and `its` 4384758f92a0SBarry Smith 4385dc4c0fb0SBarry Smith Level: intermediate 4386dc4c0fb0SBarry Smith 438720f4b53cSBarry Smith Note: 438820f4b53cSBarry Smith This routine is useful, e.g., when running a code for purposes 438920f4b53cSBarry Smith of accurate performance monitoring, when no I/O should be done 439020f4b53cSBarry Smith during the section of code that is being timed. 439120f4b53cSBarry Smith 4392420bcc1bSBarry Smith Fortran Note: 4393758f92a0SBarry Smith The calling sequence for this routine in Fortran is 4394dc4c0fb0SBarry Smith .vb 4395dc4c0fb0SBarry Smith call SNESGetConvergenceHistory(SNES snes, integer na, integer ierr) 4396dc4c0fb0SBarry Smith .ve 4397758f92a0SBarry Smith 43981cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceHistory()` 4399758f92a0SBarry Smith @*/ 4400d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergenceHistory(SNES snes, PetscReal *a[], PetscInt *its[], PetscInt *na) 4401d71ae5a4SJacob Faibussowitsch { 4402758f92a0SBarry Smith PetscFunctionBegin; 44030700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4404758f92a0SBarry Smith if (a) *a = snes->conv_hist; 4405758f92a0SBarry Smith if (its) *its = snes->conv_hist_its; 4406115dd874SBarry Smith if (na) *na = (PetscInt)snes->conv_hist_len; 44073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4408c9005455SLois Curfman McInnes } 4409c9005455SLois Curfman McInnes 4410ac226902SBarry Smith /*@C 441176b2cf59SMatthew Knepley SNESSetUpdate - Sets the general-purpose update function called 4412eec8f646SJed Brown at the beginning of every iteration of the nonlinear solve. Specifically 4413*53e5d35bSStefano Zampini it is called just before the Jacobian is "evaluated" and after the function 4414*53e5d35bSStefano Zampini evaluation. 441576b2cf59SMatthew Knepley 4416c3339decSBarry Smith Logically Collective 441776b2cf59SMatthew Knepley 441876b2cf59SMatthew Knepley Input Parameters: 4419a2b725a8SWilliam Gropp + snes - The nonlinear solver context 4420*53e5d35bSStefano Zampini - func - The update function; for calling sequence see `SNESUpdateFn` 442176b2cf59SMatthew Knepley 4422fe97e370SBarry Smith Level: advanced 4423fe97e370SBarry Smith 4424420bcc1bSBarry Smith Notes: 4425f6dfbefdSBarry 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 4426f6dfbefdSBarry Smith to `SNESSetFunction()`, or `SNESSetPicard()` 4427*53e5d35bSStefano Zampini This is not used by most users, and it is intended to provide a general hook that is run 4428*53e5d35bSStefano Zampini right before the direction step is computed. 4429*53e5d35bSStefano Zampini Users are free to modify the current residual vector, 4430*53e5d35bSStefano Zampini the current linearization point, or any other vector associated to the specific solver used. 4431*53e5d35bSStefano Zampini If such modifications take place, it is the user responsibility to update all the relevant 4432*53e5d35bSStefano Zampini vectors. 443376b2cf59SMatthew Knepley 4434aaa8cc7dSPierre 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. 44356b7fb656SBarry Smith 4436e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetJacobian()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRSetPostCheck()`, 4437*53e5d35bSStefano Zampini `SNESMonitorSet()` 443876b2cf59SMatthew Knepley @*/ 4439*53e5d35bSStefano Zampini PetscErrorCode SNESSetUpdate(SNES snes, SNESUpdateFn *func) 4440d71ae5a4SJacob Faibussowitsch { 444176b2cf59SMatthew Knepley PetscFunctionBegin; 44420700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4443e7788613SBarry Smith snes->ops->update = func; 44443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 444576b2cf59SMatthew Knepley } 444676b2cf59SMatthew Knepley 4447ffeef943SBarry Smith /*@ 4448f6dfbefdSBarry Smith SNESConvergedReasonView - Displays the reason a `SNES` solve converged or diverged to a viewer 44492a359c20SBarry Smith 4450c3339decSBarry Smith Collective 44512a359c20SBarry Smith 4452e4094ef1SJacob Faibussowitsch Input Parameters: 4453f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 44542a359c20SBarry Smith - viewer - the viewer to display the reason 44552a359c20SBarry Smith 44562a359c20SBarry Smith Options Database Keys: 4457ee300463SSatish Balay + -snes_converged_reason - print reason for converged or diverged, also prints number of iterations 4458ee300463SSatish Balay - -snes_converged_reason ::failed - only print reason and number of iterations when diverged 4459eafd5ff0SAlex Lindsay 4460420bcc1bSBarry Smith Level: beginner 4461420bcc1bSBarry Smith 4462f6dfbefdSBarry Smith Note: 4463f6dfbefdSBarry Smith To change the format of the output call `PetscViewerPushFormat`(viewer,format) before this call. Use `PETSC_VIEWER_DEFAULT` for the default, 4464f6dfbefdSBarry Smith use `PETSC_VIEWER_FAILED` to only display a reason if it fails. 44652a359c20SBarry Smith 44661cc06b55SBarry Smith .seealso: [](ch_snes), `SNESConvergedReason`, `PetscViewer`, `SNES`, 4467f6dfbefdSBarry Smith `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, 4468f6dfbefdSBarry Smith `SNESConvergedReasonViewFromOptions()`, 4469db781477SPatrick Sanan `PetscViewerPushFormat()`, `PetscViewerPopFormat()` 44702a359c20SBarry Smith @*/ 4471d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonView(SNES snes, PetscViewer viewer) 4472d71ae5a4SJacob Faibussowitsch { 447375cca76cSMatthew G. Knepley PetscViewerFormat format; 44742a359c20SBarry Smith PetscBool isAscii; 44752a359c20SBarry Smith 44762a359c20SBarry Smith PetscFunctionBegin; 447719a666eeSBarry Smith if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)); 44789566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii)); 44792a359c20SBarry Smith if (isAscii) { 44809566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 448165bf60d2SBarry Smith PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel + 1)); 448275cca76cSMatthew G. Knepley if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 448375cca76cSMatthew G. Knepley DM dm; 448475cca76cSMatthew G. Knepley Vec u; 448575cca76cSMatthew G. Knepley PetscDS prob; 448675cca76cSMatthew G. Knepley PetscInt Nf, f; 448795cbbfd3SMatthew G. Knepley PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *); 448895cbbfd3SMatthew G. Knepley void **exactCtx; 448975cca76cSMatthew G. Knepley PetscReal error; 449075cca76cSMatthew G. Knepley 44919566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 44929566063dSJacob Faibussowitsch PetscCall(SNESGetSolution(snes, &u)); 44939566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob)); 44949566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(prob, &Nf)); 44959566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(Nf, &exactSol, Nf, &exactCtx)); 44969566063dSJacob Faibussowitsch for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f])); 44979566063dSJacob Faibussowitsch PetscCall(DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error)); 44989566063dSJacob Faibussowitsch PetscCall(PetscFree2(exactSol, exactCtx)); 44999566063dSJacob Faibussowitsch if (error < 1.0e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n")); 450063a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", (double)error)); 450175cca76cSMatthew G. Knepley } 4502eafd5ff0SAlex Lindsay if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) { 45032a359c20SBarry Smith if (((PetscObject)snes)->prefix) { 450463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter)); 45052a359c20SBarry Smith } else { 450663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve converged due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter)); 45072a359c20SBarry Smith } 4508eafd5ff0SAlex Lindsay } else if (snes->reason <= 0) { 45092a359c20SBarry Smith if (((PetscObject)snes)->prefix) { 451063a3b9bcSJacob 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)); 45112a359c20SBarry Smith } else { 451263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve did not converge due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter)); 45132a359c20SBarry Smith } 45142a359c20SBarry Smith } 451565bf60d2SBarry Smith PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel + 1)); 45162a359c20SBarry Smith } 45173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 45182a359c20SBarry Smith } 45192a359c20SBarry Smith 4520c4421ceaSFande Kong /*@C 4521c4421ceaSFande Kong SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the 4522aaa8cc7dSPierre Jolivet end of the nonlinear solver to display the convergence reason of the nonlinear solver. 4523c4421ceaSFande Kong 4524c3339decSBarry Smith Logically Collective 4525c4421ceaSFande Kong 4526c4421ceaSFande Kong Input Parameters: 4527f6dfbefdSBarry Smith + snes - the `SNES` context 4528420bcc1bSBarry Smith . f - the `SNESConvergedReason` view function 4529420bcc1bSBarry Smith . vctx - [optional] user-defined context for private data for the `SNESConvergedReason` view function (use `NULL` if no context is desired) 4530420bcc1bSBarry Smith - reasonviewdestroy - [optional] routine that frees the context (may be `NULL`) 4531420bcc1bSBarry Smith 4532420bcc1bSBarry Smith Calling sequence of `f`: 4533420bcc1bSBarry Smith + snes - the `SNES` context 4534420bcc1bSBarry Smith - vctx - [optional] user-defined context for private data for the function 4535420bcc1bSBarry Smith 4536420bcc1bSBarry Smith Calling sequence of `reasonviewerdestroy`: 4537420bcc1bSBarry Smith . vctx - [optional] user-defined context for private data for the function 4538c4421ceaSFande Kong 4539c4421ceaSFande Kong Options Database Keys: 4540f6dfbefdSBarry Smith + -snes_converged_reason - sets a default `SNESConvergedReasonView()` 4541420bcc1bSBarry Smith - -snes_converged_reason_view_cancel - cancels all converged reason viewers that have been hardwired into a code by 4542420bcc1bSBarry Smith calls to `SNESConvergedReasonViewSet()`, but does not cancel those set via the options database. 4543c4421ceaSFande Kong 4544dc4c0fb0SBarry Smith Level: intermediate 4545dc4c0fb0SBarry Smith 4546f6dfbefdSBarry Smith Note: 4547c4421ceaSFande Kong Several different converged reason view routines may be set by calling 4548f6dfbefdSBarry Smith `SNESConvergedReasonViewSet()` multiple times; all will be called in the 4549c4421ceaSFande Kong order in which they were set. 4550c4421ceaSFande Kong 45511cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`, `SNESConvergedReasonViewCancel()` 4552c4421ceaSFande Kong @*/ 4553420bcc1bSBarry Smith PetscErrorCode SNESConvergedReasonViewSet(SNES snes, PetscErrorCode (*f)(SNES snes, void *vctx), void *vctx, PetscErrorCode (*reasonviewdestroy)(void **vctx)) 4554d71ae5a4SJacob Faibussowitsch { 4555c4421ceaSFande Kong PetscInt i; 4556c4421ceaSFande Kong PetscBool identical; 4557c4421ceaSFande Kong 4558c4421ceaSFande Kong PetscFunctionBegin; 4559c4421ceaSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4560c4421ceaSFande Kong for (i = 0; i < snes->numberreasonviews; i++) { 45619566063dSJacob Faibussowitsch PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, vctx, reasonviewdestroy, (PetscErrorCode(*)(void))snes->reasonview[i], snes->reasonviewcontext[i], snes->reasonviewdestroy[i], &identical)); 45623ba16761SJacob Faibussowitsch if (identical) PetscFunctionReturn(PETSC_SUCCESS); 4563c4421ceaSFande Kong } 45645f80ce2aSJacob Faibussowitsch PetscCheck(snes->numberreasonviews < MAXSNESREASONVIEWS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many SNES reasonview set"); 4565c4421ceaSFande Kong snes->reasonview[snes->numberreasonviews] = f; 4566c4421ceaSFande Kong snes->reasonviewdestroy[snes->numberreasonviews] = reasonviewdestroy; 4567c4421ceaSFande Kong snes->reasonviewcontext[snes->numberreasonviews++] = (void *)vctx; 45683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4569c4421ceaSFande Kong } 4570c4421ceaSFande Kong 457191f3e32bSBarry Smith /*@ 4572420bcc1bSBarry Smith SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a `SNESConvergedReason` is to be viewed at the end of `SNESSolve()` 4573c4421ceaSFande Kong All the user-provided convergedReasonView routines will be involved as well, if they exist. 45742a359c20SBarry Smith 4575c3339decSBarry Smith Collective 45762a359c20SBarry Smith 45772fe279fdSBarry Smith Input Parameter: 4578f6dfbefdSBarry Smith . snes - the `SNES` object 45792a359c20SBarry Smith 4580f6dfbefdSBarry Smith Level: advanced 45812a359c20SBarry Smith 45821cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESConvergedReasonViewSet()`, `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, 4583f6dfbefdSBarry Smith `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()` 45842a359c20SBarry Smith @*/ 4585d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes) 4586d71ae5a4SJacob Faibussowitsch { 45872a359c20SBarry Smith PetscViewer viewer; 45882a359c20SBarry Smith PetscBool flg; 45892a359c20SBarry Smith static PetscBool incall = PETSC_FALSE; 45902a359c20SBarry Smith PetscViewerFormat format; 4591c4421ceaSFande Kong PetscInt i; 45922a359c20SBarry Smith 45932a359c20SBarry Smith PetscFunctionBegin; 45943ba16761SJacob Faibussowitsch if (incall) PetscFunctionReturn(PETSC_SUCCESS); 45952a359c20SBarry Smith incall = PETSC_TRUE; 4596c4421ceaSFande Kong 4597c4421ceaSFande Kong /* All user-provided viewers are called first, if they exist. */ 459848a46eb9SPierre Jolivet for (i = 0; i < snes->numberreasonviews; i++) PetscCall((*snes->reasonview[i])(snes, snes->reasonviewcontext[i])); 4599c4421ceaSFande Kong 4600c4421ceaSFande Kong /* Call PETSc default routine if users ask for it */ 46019566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_converged_reason", &viewer, &format, &flg)); 46022a359c20SBarry Smith if (flg) { 46039566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(viewer, format)); 46049566063dSJacob Faibussowitsch PetscCall(SNESConvergedReasonView(snes, viewer)); 46059566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer)); 4606cd791dc2SBarry Smith PetscCall(PetscOptionsRestoreViewer(&viewer)); 46072a359c20SBarry Smith } 46082a359c20SBarry Smith incall = PETSC_FALSE; 46093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 46102a359c20SBarry Smith } 46112a359c20SBarry Smith 4612487a658cSBarry Smith /*@ 4613f69a0ea3SMatthew Knepley SNESSolve - Solves a nonlinear system F(x) = b. 46149b94acceSBarry Smith 4615c3339decSBarry Smith Collective 4616c7afd0dbSLois Curfman McInnes 4617b2002411SLois Curfman McInnes Input Parameters: 4618f6dfbefdSBarry Smith + snes - the `SNES` context 4619dc4c0fb0SBarry Smith . b - the constant part of the equation F(x) = b, or `NULL` to use zero. 462085385478SLisandro Dalcin - x - the solution vector. 46219b94acceSBarry Smith 4622dc4c0fb0SBarry Smith Level: beginner 4623dc4c0fb0SBarry Smith 4624f6dfbefdSBarry Smith Note: 4625420bcc1bSBarry Smith The user should initialize the vector, `x`, with the initial guess 4626420bcc1bSBarry Smith for the nonlinear solve prior to calling `SNESSolve()` or use `SNESSetInitialSolution()`. In particular, 46278ddd3da0SLois Curfman McInnes to employ an initial guess of zero, the user should explicitly set 4628f6dfbefdSBarry Smith this vector to zero by calling `VecSet()`. 46298ddd3da0SLois Curfman McInnes 46301cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESSetFunction()`, `SNESSetJacobian()`, `SNESSetGridSequence()`, `SNESGetSolution()`, 4631db781477SPatrick Sanan `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRGetPreCheck()`, `SNESNewtonTRSetPostCheck()`, `SNESNewtonTRGetPostCheck()`, 4632420bcc1bSBarry Smith `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`, `SNESSetInitialSolution()` 46339b94acceSBarry Smith @*/ 4634d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSolve(SNES snes, Vec b, Vec x) 4635d71ae5a4SJacob Faibussowitsch { 4636ace3abfcSBarry Smith PetscBool flg; 4637efd51863SBarry Smith PetscInt grid; 46380298fd71SBarry Smith Vec xcreated = NULL; 4639caa4e7f2SJed Brown DM dm; 4640052efed2SBarry Smith 46413a40ed3dSBarry Smith PetscFunctionBegin; 46420700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4643a69afd8bSBarry Smith if (x) PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4644a69afd8bSBarry Smith if (x) PetscCheckSameComm(snes, 1, x, 3); 46450700a824SBarry Smith if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 464685385478SLisandro Dalcin if (b) PetscCheckSameComm(snes, 1, b, 2); 464785385478SLisandro Dalcin 464834b4d3a8SMatthew G. Knepley /* High level operations using the nonlinear solver */ 464906fc46c8SMatthew G. Knepley { 465006fc46c8SMatthew G. Knepley PetscViewer viewer; 465106fc46c8SMatthew G. Knepley PetscViewerFormat format; 46527c88af5aSMatthew G. Knepley PetscInt num; 465306fc46c8SMatthew G. Knepley PetscBool flg; 465406fc46c8SMatthew G. Knepley static PetscBool incall = PETSC_FALSE; 465506fc46c8SMatthew G. Knepley 465606fc46c8SMatthew G. Knepley if (!incall) { 465734b4d3a8SMatthew G. Knepley /* Estimate the convergence rate of the discretization */ 46589566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg)); 465906fc46c8SMatthew G. Knepley if (flg) { 466006fc46c8SMatthew G. Knepley PetscConvEst conv; 466146079b62SMatthew G. Knepley DM dm; 466246079b62SMatthew G. Knepley PetscReal *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */ 466346079b62SMatthew G. Knepley PetscInt Nf; 466406fc46c8SMatthew G. Knepley 466506fc46c8SMatthew G. Knepley incall = PETSC_TRUE; 46669566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 46679566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 46689566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(Nf, &alpha)); 46699566063dSJacob Faibussowitsch PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)snes), &conv)); 46709566063dSJacob Faibussowitsch PetscCall(PetscConvEstSetSolver(conv, (PetscObject)snes)); 46719566063dSJacob Faibussowitsch PetscCall(PetscConvEstSetFromOptions(conv)); 46729566063dSJacob Faibussowitsch PetscCall(PetscConvEstSetUp(conv)); 46739566063dSJacob Faibussowitsch PetscCall(PetscConvEstGetConvRate(conv, alpha)); 46749566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(viewer, format)); 46759566063dSJacob Faibussowitsch PetscCall(PetscConvEstRateView(conv, alpha, viewer)); 46769566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer)); 4677cd791dc2SBarry Smith PetscCall(PetscOptionsRestoreViewer(&viewer)); 46789566063dSJacob Faibussowitsch PetscCall(PetscConvEstDestroy(&conv)); 46799566063dSJacob Faibussowitsch PetscCall(PetscFree(alpha)); 468006fc46c8SMatthew G. Knepley incall = PETSC_FALSE; 468106fc46c8SMatthew G. Knepley } 468234b4d3a8SMatthew G. Knepley /* Adaptively refine the initial grid */ 4683b2588ea6SMatthew G. Knepley num = 1; 46849566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_initial", &num, &flg)); 468534b4d3a8SMatthew G. Knepley if (flg) { 468634b4d3a8SMatthew G. Knepley DMAdaptor adaptor; 468734b4d3a8SMatthew G. Knepley 468834b4d3a8SMatthew G. Knepley incall = PETSC_TRUE; 46899566063dSJacob Faibussowitsch PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor)); 46909566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSolver(adaptor, snes)); 46919566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSequenceLength(adaptor, num)); 46929566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetFromOptions(adaptor)); 46939566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetUp(adaptor)); 46949566063dSJacob Faibussowitsch PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x)); 46959566063dSJacob Faibussowitsch PetscCall(DMAdaptorDestroy(&adaptor)); 469634b4d3a8SMatthew G. Knepley incall = PETSC_FALSE; 469734b4d3a8SMatthew G. Knepley } 46987c88af5aSMatthew G. Knepley /* Use grid sequencing to adapt */ 46997c88af5aSMatthew G. Knepley num = 0; 47009566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_sequence", &num, NULL)); 47017c88af5aSMatthew G. Knepley if (num) { 47027c88af5aSMatthew G. Knepley DMAdaptor adaptor; 47037c88af5aSMatthew G. Knepley 47047c88af5aSMatthew G. Knepley incall = PETSC_TRUE; 47059566063dSJacob Faibussowitsch PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor)); 47069566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSolver(adaptor, snes)); 47079566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSequenceLength(adaptor, num)); 47089566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetFromOptions(adaptor)); 47099566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetUp(adaptor)); 47109566063dSJacob Faibussowitsch PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x)); 47119566063dSJacob Faibussowitsch PetscCall(DMAdaptorDestroy(&adaptor)); 47127c88af5aSMatthew G. Knepley incall = PETSC_FALSE; 47137c88af5aSMatthew G. Knepley } 471406fc46c8SMatthew G. Knepley } 471506fc46c8SMatthew G. Knepley } 4716ad540459SPierre Jolivet if (!x) x = snes->vec_sol; 4717caa4e7f2SJed Brown if (!x) { 47189566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 47199566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dm, &xcreated)); 4720a69afd8bSBarry Smith x = xcreated; 4721a69afd8bSBarry Smith } 47229566063dSJacob Faibussowitsch PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view_pre")); 4723f05ece33SBarry Smith 47249566063dSJacob Faibussowitsch for (grid = 0; grid < snes->gridsequence; grid++) PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)))); 4725efd51863SBarry Smith for (grid = 0; grid < snes->gridsequence + 1; grid++) { 472685385478SLisandro Dalcin /* set solution vector */ 47279566063dSJacob Faibussowitsch if (!grid) PetscCall(PetscObjectReference((PetscObject)x)); 47289566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol)); 472985385478SLisandro Dalcin snes->vec_sol = x; 47309566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 4731caa4e7f2SJed Brown 4732caa4e7f2SJed Brown /* set affine vector if provided */ 47339566063dSJacob Faibussowitsch if (b) PetscCall(PetscObjectReference((PetscObject)b)); 47349566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_rhs)); 473585385478SLisandro Dalcin snes->vec_rhs = b; 473685385478SLisandro Dalcin 47375f80ce2aSJacob 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"); 47385f80ce2aSJacob Faibussowitsch PetscCheck(snes->vec_func != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be function vector"); 4739dd8e379bSPierre Jolivet PetscCheck(snes->vec_rhs != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be right-hand side vector"); 4740aa624791SPierre Jolivet if (!snes->vec_sol_update /* && snes->vec_sol */) PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_sol_update)); 47419566063dSJacob Faibussowitsch PetscCall(DMShellSetGlobalVector(dm, snes->vec_sol)); 47429566063dSJacob Faibussowitsch PetscCall(SNESSetUp(snes)); 47433f149594SLisandro Dalcin 47447eee914bSBarry Smith if (!grid) { 47459927e4dfSBarry Smith if (snes->ops->computeinitialguess) PetscCallBack("SNES callback compute initial guess", (*snes->ops->computeinitialguess)(snes, snes->vec_sol, snes->initialguessP)); 4746dd568438SSatish Balay } 4747d25893d9SBarry Smith 4748abc0a331SBarry Smith if (snes->conv_hist_reset) snes->conv_hist_len = 0; 47499371c9d4SSatish Balay if (snes->counters_reset) { 47509371c9d4SSatish Balay snes->nfuncs = 0; 47519371c9d4SSatish Balay snes->linear_its = 0; 47529371c9d4SSatish Balay snes->numFailures = 0; 47539371c9d4SSatish Balay } 4754d5e45103SBarry Smith 47552d157150SStefano Zampini snes->reason = SNES_CONVERGED_ITERATING; 47569566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_Solve, snes, 0, 0, 0)); 4757dbbe0bcdSBarry Smith PetscUseTypeMethod(snes, solve); 47589566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_Solve, snes, 0, 0, 0)); 47592d157150SStefano Zampini PetscCheck(snes->reason, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error, solver %s returned without setting converged reason", ((PetscObject)snes)->type_name); 4760422a814eSBarry Smith snes->domainerror = PETSC_FALSE; /* clear the flag if it has been set */ 47613f149594SLisandro Dalcin 476237ec4e1aSPeter Brune if (snes->lagjac_persist) snes->jac_iter += snes->iter; 476337ec4e1aSPeter Brune if (snes->lagpre_persist) snes->pre_iter += snes->iter; 476437ec4e1aSPeter Brune 47659566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_test_local_min", NULL, NULL, &flg)); 47669566063dSJacob Faibussowitsch if (flg && !PetscPreLoadingOn) PetscCall(SNESTestLocalMin(snes)); 4767c4421ceaSFande Kong /* Call converged reason views. This may involve user-provided viewers as well */ 47689566063dSJacob Faibussowitsch PetscCall(SNESConvergedReasonViewFromOptions(snes)); 47695968eb51SBarry Smith 47705f80ce2aSJacob Faibussowitsch if (snes->errorifnotconverged) PetscCheck(snes->reason >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_NOT_CONVERGED, "SNESSolve has not converged"); 47719c8e83a9SBarry Smith if (snes->reason < 0) break; 4772efd51863SBarry Smith if (grid < snes->gridsequence) { 4773efd51863SBarry Smith DM fine; 4774efd51863SBarry Smith Vec xnew; 4775efd51863SBarry Smith Mat interp; 4776efd51863SBarry Smith 47779566063dSJacob Faibussowitsch PetscCall(DMRefine(snes->dm, PetscObjectComm((PetscObject)snes), &fine)); 47785f80ce2aSJacob Faibussowitsch PetscCheck(fine, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_INCOMP, "DMRefine() did not perform any refinement, cannot continue grid sequencing"); 47799566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(snes->dm, fine, &interp, NULL)); 47809566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(fine, &xnew)); 47819566063dSJacob Faibussowitsch PetscCall(MatInterpolate(interp, x, xnew)); 47829566063dSJacob Faibussowitsch PetscCall(DMInterpolate(snes->dm, interp, fine)); 47839566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interp)); 4784efd51863SBarry Smith x = xnew; 4785efd51863SBarry Smith 47869566063dSJacob Faibussowitsch PetscCall(SNESReset(snes)); 47879566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes, fine)); 47889566063dSJacob Faibussowitsch PetscCall(SNESResetFromOptions(snes)); 47899566063dSJacob Faibussowitsch PetscCall(DMDestroy(&fine)); 47909566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)))); 4791efd51863SBarry Smith } 4792efd51863SBarry Smith } 47939566063dSJacob Faibussowitsch PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view")); 47949566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(snes->vec_sol, (PetscObject)snes, "-snes_view_solution")); 47959566063dSJacob Faibussowitsch PetscCall(DMMonitor(snes->dm)); 47969566063dSJacob Faibussowitsch PetscCall(SNESMonitorPauseFinal_Internal(snes)); 47973f7e2da0SPeter Brune 47989566063dSJacob Faibussowitsch PetscCall(VecDestroy(&xcreated)); 47999566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsBlock((PetscObject)snes)); 48003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 48019b94acceSBarry Smith } 48029b94acceSBarry Smith 48039b94acceSBarry Smith /* --------- Internal routines for SNES Package --------- */ 48049b94acceSBarry Smith 4805cc4c1da9SBarry Smith /*@ 48064b0e389bSBarry Smith SNESSetType - Sets the method for the nonlinear solver. 48079b94acceSBarry Smith 4808c3339decSBarry Smith Collective 4809fee21e36SBarry Smith 4810c7afd0dbSLois Curfman McInnes Input Parameters: 4811f6dfbefdSBarry Smith + snes - the `SNES` context 4812454a90a3SBarry Smith - type - a known method 4813c7afd0dbSLois Curfman McInnes 4814c7afd0dbSLois Curfman McInnes Options Database Key: 4815454a90a3SBarry Smith . -snes_type <type> - Sets the method; use -help for a list 481604d7464bSBarry Smith of available methods (for instance, newtonls or newtontr) 4817ae12b187SLois Curfman McInnes 4818dc4c0fb0SBarry Smith Level: intermediate 4819dc4c0fb0SBarry Smith 48209b94acceSBarry Smith Notes: 4821e090d566SSatish Balay See "petsc/include/petscsnes.h" for available methods (for instance) 4822f6dfbefdSBarry Smith + `SNESNEWTONLS` - Newton's method with line search 4823c7afd0dbSLois Curfman McInnes (systems of nonlinear equations) 48244a221d59SStefano Zampini - `SNESNEWTONTR` - Newton's method with trust region 4825c7afd0dbSLois Curfman McInnes (systems of nonlinear equations) 48269b94acceSBarry Smith 4827f6dfbefdSBarry Smith Normally, it is best to use the `SNESSetFromOptions()` command and then 4828f6dfbefdSBarry Smith set the `SNES` solver type from the options database rather than by using 4829ae12b187SLois Curfman McInnes this routine. Using the options database provides the user with 4830ae12b187SLois Curfman McInnes maximum flexibility in evaluating the many nonlinear solvers. 4831f6dfbefdSBarry Smith The `SNESSetType()` routine is provided for those situations where it 4832ae12b187SLois Curfman McInnes is necessary to set the nonlinear solver independently of the command 4833ae12b187SLois Curfman McInnes line or options database. This might be the case, for example, when 4834ae12b187SLois Curfman McInnes the choice of solver changes during the execution of the program, 4835ae12b187SLois Curfman McInnes and the user's application is taking responsibility for choosing the 4836b0a32e0cSBarry Smith appropriate method. 483736851e7fSLois Curfman McInnes 4838420bcc1bSBarry Smith Developer Note: 4839f6dfbefdSBarry Smith `SNESRegister()` adds a constructor for a new `SNESType` to `SNESList`, `SNESSetType()` locates 4840f6dfbefdSBarry Smith the constructor in that list and calls it to create the specific object. 48418f6c3df8SBarry Smith 48421cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESType`, `SNESCreate()`, `SNESDestroy()`, `SNESGetType()`, `SNESSetFromOptions()` 48439b94acceSBarry Smith @*/ 4844d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetType(SNES snes, SNESType type) 4845d71ae5a4SJacob Faibussowitsch { 4846ace3abfcSBarry Smith PetscBool match; 48475f80ce2aSJacob Faibussowitsch PetscErrorCode (*r)(SNES); 48483a40ed3dSBarry Smith 48493a40ed3dSBarry Smith PetscFunctionBegin; 48500700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 48514f572ea9SToby Isaac PetscAssertPointer(type, 2); 485282bf6240SBarry Smith 48539566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes, type, &match)); 48543ba16761SJacob Faibussowitsch if (match) PetscFunctionReturn(PETSC_SUCCESS); 485592ff6ae8SBarry Smith 48569566063dSJacob Faibussowitsch PetscCall(PetscFunctionListFind(SNESList, type, &r)); 48576adde796SStefano Zampini PetscCheck(r, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested SNES type %s", type); 485875396ef9SLisandro Dalcin /* Destroy the previous private SNES context */ 4859dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, destroy); 486075396ef9SLisandro Dalcin /* Reinitialize function pointers in SNESOps structure */ 48619e5d0892SLisandro Dalcin snes->ops->setup = NULL; 48629e5d0892SLisandro Dalcin snes->ops->solve = NULL; 48639e5d0892SLisandro Dalcin snes->ops->view = NULL; 48649e5d0892SLisandro Dalcin snes->ops->setfromoptions = NULL; 48659e5d0892SLisandro Dalcin snes->ops->destroy = NULL; 48667fe760d5SStefano Zampini 48677fe760d5SStefano Zampini /* It may happen the user has customized the line search before calling SNESSetType */ 48689566063dSJacob Faibussowitsch if (((PetscObject)snes)->type_name) PetscCall(SNESLineSearchDestroy(&snes->linesearch)); 48697fe760d5SStefano Zampini 487075396ef9SLisandro Dalcin /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */ 487175396ef9SLisandro Dalcin snes->setupcalled = PETSC_FALSE; 4872f5af7f23SKarl Rupp 48739566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)snes, type)); 48749566063dSJacob Faibussowitsch PetscCall((*r)(snes)); 48753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 48769b94acceSBarry Smith } 48779b94acceSBarry Smith 4878cc4c1da9SBarry Smith /*@ 4879f6dfbefdSBarry Smith SNESGetType - Gets the `SNES` method type and name (as a string). 48809b94acceSBarry Smith 4881c7afd0dbSLois Curfman McInnes Not Collective 4882c7afd0dbSLois Curfman McInnes 48839b94acceSBarry Smith Input Parameter: 48844b0e389bSBarry Smith . snes - nonlinear solver context 48859b94acceSBarry Smith 48869b94acceSBarry Smith Output Parameter: 4887f6dfbefdSBarry Smith . type - `SNES` method (a character string) 48889b94acceSBarry Smith 488936851e7fSLois Curfman McInnes Level: intermediate 489036851e7fSLois Curfman McInnes 48911cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetType()`, `SNESType`, `SNESSetFromOptions()`, `SNES` 48929b94acceSBarry Smith @*/ 4893d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetType(SNES snes, SNESType *type) 4894d71ae5a4SJacob Faibussowitsch { 48953a40ed3dSBarry Smith PetscFunctionBegin; 48960700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 48974f572ea9SToby Isaac PetscAssertPointer(type, 2); 48987adad957SLisandro Dalcin *type = ((PetscObject)snes)->type_name; 48993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49009b94acceSBarry Smith } 49019b94acceSBarry Smith 49023cd8a7caSMatthew G. Knepley /*@ 4903f6dfbefdSBarry Smith SNESSetSolution - Sets the solution vector for use by the `SNES` routines. 49043cd8a7caSMatthew G. Knepley 4905c3339decSBarry Smith Logically Collective 49063cd8a7caSMatthew G. Knepley 49073cd8a7caSMatthew G. Knepley Input Parameters: 4908f6dfbefdSBarry Smith + snes - the `SNES` context obtained from `SNESCreate()` 49093cd8a7caSMatthew G. Knepley - u - the solution vector 49103cd8a7caSMatthew G. Knepley 49113cd8a7caSMatthew G. Knepley Level: beginner 49123cd8a7caSMatthew G. Knepley 49131cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetSolution()`, `Vec` 49143cd8a7caSMatthew G. Knepley @*/ 4915d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetSolution(SNES snes, Vec u) 4916d71ae5a4SJacob Faibussowitsch { 49173cd8a7caSMatthew G. Knepley DM dm; 49183cd8a7caSMatthew G. Knepley 49193cd8a7caSMatthew G. Knepley PetscFunctionBegin; 49203cd8a7caSMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 49213cd8a7caSMatthew G. Knepley PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 49229566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)u)); 49239566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol)); 49243cd8a7caSMatthew G. Knepley 49253cd8a7caSMatthew G. Knepley snes->vec_sol = u; 49263cd8a7caSMatthew G. Knepley 49279566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 49289566063dSJacob Faibussowitsch PetscCall(DMShellSetGlobalVector(dm, u)); 49293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49303cd8a7caSMatthew G. Knepley } 49313cd8a7caSMatthew G. Knepley 493252baeb72SSatish Balay /*@ 49339b94acceSBarry Smith SNESGetSolution - Returns the vector where the approximate solution is 4934f6dfbefdSBarry Smith stored. This is the fine grid solution when using `SNESSetGridSequence()`. 49359b94acceSBarry Smith 4936420bcc1bSBarry Smith Not Collective, but `x` is parallel if `snes` is parallel 4937c7afd0dbSLois Curfman McInnes 49389b94acceSBarry Smith Input Parameter: 4939f6dfbefdSBarry Smith . snes - the `SNES` context 49409b94acceSBarry Smith 49419b94acceSBarry Smith Output Parameter: 49429b94acceSBarry Smith . x - the solution 49439b94acceSBarry Smith 494470e92668SMatthew Knepley Level: intermediate 494536851e7fSLois Curfman McInnes 49461cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetSolution()`, `SNESSolve()`, `SNES`, `SNESGetSolutionUpdate()`, `SNESGetFunction()` 49479b94acceSBarry Smith @*/ 4948d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolution(SNES snes, Vec *x) 4949d71ae5a4SJacob Faibussowitsch { 49503a40ed3dSBarry Smith PetscFunctionBegin; 49510700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 49524f572ea9SToby Isaac PetscAssertPointer(x, 2); 495385385478SLisandro Dalcin *x = snes->vec_sol; 49543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 495570e92668SMatthew Knepley } 495670e92668SMatthew Knepley 495752baeb72SSatish Balay /*@ 49589b94acceSBarry Smith SNESGetSolutionUpdate - Returns the vector where the solution update is 49599b94acceSBarry Smith stored. 49609b94acceSBarry Smith 4961420bcc1bSBarry Smith Not Collective, but `x` is parallel if `snes` is parallel 4962c7afd0dbSLois Curfman McInnes 49639b94acceSBarry Smith Input Parameter: 4964f6dfbefdSBarry Smith . snes - the `SNES` context 49659b94acceSBarry Smith 49669b94acceSBarry Smith Output Parameter: 49679b94acceSBarry Smith . x - the solution update 49689b94acceSBarry Smith 496936851e7fSLois Curfman McInnes Level: advanced 497036851e7fSLois Curfman McInnes 49711cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()` 49729b94acceSBarry Smith @*/ 4973d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionUpdate(SNES snes, Vec *x) 4974d71ae5a4SJacob Faibussowitsch { 49753a40ed3dSBarry Smith PetscFunctionBegin; 49760700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 49774f572ea9SToby Isaac PetscAssertPointer(x, 2); 497885385478SLisandro Dalcin *x = snes->vec_sol_update; 49793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49809b94acceSBarry Smith } 49819b94acceSBarry Smith 49829b94acceSBarry Smith /*@C 4983f6dfbefdSBarry Smith SNESGetFunction - Returns the function that defines the nonlinear system set with `SNESSetFunction()` 49849b94acceSBarry Smith 4985420bcc1bSBarry Smith Not Collective, but `r` is parallel if `snes` is parallel. Collective if `r` is requested, but has not been created yet. 4986c7afd0dbSLois Curfman McInnes 49879b94acceSBarry Smith Input Parameter: 4988f6dfbefdSBarry Smith . snes - the `SNES` context 49899b94acceSBarry Smith 4990d8d19677SJose E. Roman Output Parameters: 4991dc4c0fb0SBarry Smith + r - the vector that is used to store residuals (or `NULL` if you don't want it) 49928434afd1SBarry Smith . f - the function (or `NULL` if you don't want it); for calling sequence see `SNESFunctionFn` 4993dc4c0fb0SBarry Smith - ctx - the function context (or `NULL` if you don't want it) 49949b94acceSBarry Smith 499536851e7fSLois Curfman McInnes Level: advanced 499636851e7fSLois Curfman McInnes 4997f6dfbefdSBarry Smith Note: 4998dc4c0fb0SBarry Smith The vector `r` DOES NOT, in general, contain the current value of the `SNES` nonlinear function 499904edfde5SBarry Smith 50008434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetSolution()`, `SNESFunctionFn` 50019b94acceSBarry Smith @*/ 50028434afd1SBarry Smith PetscErrorCode SNESGetFunction(SNES snes, Vec *r, SNESFunctionFn **f, void **ctx) 5003d71ae5a4SJacob Faibussowitsch { 50046cab3a1bSJed Brown DM dm; 5005a63bb30eSJed Brown 50063a40ed3dSBarry Smith PetscFunctionBegin; 50070700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5008a63bb30eSJed Brown if (r) { 5009a63bb30eSJed Brown if (!snes->vec_func) { 5010a63bb30eSJed Brown if (snes->vec_rhs) { 50119566063dSJacob Faibussowitsch PetscCall(VecDuplicate(snes->vec_rhs, &snes->vec_func)); 5012a63bb30eSJed Brown } else if (snes->vec_sol) { 50139566063dSJacob Faibussowitsch PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_func)); 5014a63bb30eSJed Brown } else if (snes->dm) { 50159566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(snes->dm, &snes->vec_func)); 5016a63bb30eSJed Brown } 5017a63bb30eSJed Brown } 5018a63bb30eSJed Brown *r = snes->vec_func; 5019a63bb30eSJed Brown } 50209566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 50219566063dSJacob Faibussowitsch PetscCall(DMSNESGetFunction(dm, f, ctx)); 50223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50239b94acceSBarry Smith } 50249b94acceSBarry Smith 5025c79ef259SPeter Brune /*@C 502637fdd005SBarry Smith SNESGetNGS - Returns the function and context set with `SNESSetNGS()` 5027c79ef259SPeter Brune 5028c79ef259SPeter Brune Input Parameter: 5029f6dfbefdSBarry Smith . snes - the `SNES` context 5030c79ef259SPeter Brune 5031d8d19677SJose E. Roman Output Parameters: 50328434afd1SBarry Smith + f - the function (or `NULL`) see `SNESNGSFn` for calling sequence 5033dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`) 5034c79ef259SPeter Brune 5035c79ef259SPeter Brune Level: advanced 5036c79ef259SPeter Brune 50378434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetNGS()`, `SNESGetFunction()`, `SNESNGSFn` 5038c79ef259SPeter Brune @*/ 50398434afd1SBarry Smith PetscErrorCode SNESGetNGS(SNES snes, SNESNGSFn **f, void **ctx) 5040d71ae5a4SJacob Faibussowitsch { 50416cab3a1bSJed Brown DM dm; 50426cab3a1bSJed Brown 5043646217ecSPeter Brune PetscFunctionBegin; 5044646217ecSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 50459566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 50469566063dSJacob Faibussowitsch PetscCall(DMSNESGetNGS(dm, f, ctx)); 50473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5048646217ecSPeter Brune } 5049646217ecSPeter Brune 5050cc4c1da9SBarry Smith /*@ 50513c7409f5SSatish Balay SNESSetOptionsPrefix - Sets the prefix used for searching for all 5052f6dfbefdSBarry Smith `SNES` options in the database. 50533c7409f5SSatish Balay 5054c3339decSBarry Smith Logically Collective 5055fee21e36SBarry Smith 5056d8d19677SJose E. Roman Input Parameters: 5057f6dfbefdSBarry Smith + snes - the `SNES` context 5058c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names 5059c7afd0dbSLois Curfman McInnes 5060dc4c0fb0SBarry Smith Level: advanced 5061dc4c0fb0SBarry Smith 5062f6dfbefdSBarry Smith Note: 5063a83b1b31SSatish Balay A hyphen (-) must NOT be given at the beginning of the prefix name. 5064c7afd0dbSLois Curfman McInnes The first character of all runtime options is AUTOMATICALLY the hyphen. 5065d850072dSLois Curfman McInnes 50661cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESAppendOptionsPrefix()` 50673c7409f5SSatish Balay @*/ 5068d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetOptionsPrefix(SNES snes, const char prefix[]) 5069d71ae5a4SJacob Faibussowitsch { 50703a40ed3dSBarry Smith PetscFunctionBegin; 50710700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 50729566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes, prefix)); 50739566063dSJacob Faibussowitsch if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 507435f5d045SPeter Brune if (snes->linesearch) { 50759566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 50769566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch, prefix)); 507735f5d045SPeter Brune } 50789566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(snes->ksp, prefix)); 50793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50803c7409f5SSatish Balay } 50813c7409f5SSatish Balay 5082cc4c1da9SBarry Smith /*@ 5083f525115eSLois Curfman McInnes SNESAppendOptionsPrefix - Appends to the prefix used for searching for all 5084f6dfbefdSBarry Smith `SNES` options in the database. 50853c7409f5SSatish Balay 5086c3339decSBarry Smith Logically Collective 5087fee21e36SBarry Smith 5088c7afd0dbSLois Curfman McInnes Input Parameters: 5089f6dfbefdSBarry Smith + snes - the `SNES` context 5090c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names 5091c7afd0dbSLois Curfman McInnes 5092dc4c0fb0SBarry Smith Level: advanced 5093dc4c0fb0SBarry Smith 5094f6dfbefdSBarry Smith Note: 5095a83b1b31SSatish Balay A hyphen (-) must NOT be given at the beginning of the prefix name. 5096c7afd0dbSLois Curfman McInnes The first character of all runtime options is AUTOMATICALLY the hyphen. 5097d850072dSLois Curfman McInnes 50981cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetOptionsPrefix()`, `SNESSetOptionsPrefix()` 50993c7409f5SSatish Balay @*/ 5100d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESAppendOptionsPrefix(SNES snes, const char prefix[]) 5101d71ae5a4SJacob Faibussowitsch { 51023a40ed3dSBarry Smith PetscFunctionBegin; 51030700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 51049566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes, prefix)); 51059566063dSJacob Faibussowitsch if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 510635f5d045SPeter Brune if (snes->linesearch) { 51079566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 51089566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch, prefix)); 510935f5d045SPeter Brune } 51109566063dSJacob Faibussowitsch PetscCall(KSPAppendOptionsPrefix(snes->ksp, prefix)); 51113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 51123c7409f5SSatish Balay } 51133c7409f5SSatish Balay 5114cc4c1da9SBarry Smith /*@ 5115f6dfbefdSBarry Smith SNESGetOptionsPrefix - Gets the prefix used for searching for all 5116f6dfbefdSBarry Smith `SNES` options in the database. 51173c7409f5SSatish Balay 5118c7afd0dbSLois Curfman McInnes Not Collective 5119c7afd0dbSLois Curfman McInnes 51203c7409f5SSatish Balay Input Parameter: 5121f6dfbefdSBarry Smith . snes - the `SNES` context 51223c7409f5SSatish Balay 51233c7409f5SSatish Balay Output Parameter: 51243c7409f5SSatish Balay . prefix - pointer to the prefix string used 51253c7409f5SSatish Balay 512636851e7fSLois Curfman McInnes Level: advanced 512736851e7fSLois Curfman McInnes 5128420bcc1bSBarry Smith Fortran Note: 5129dc4c0fb0SBarry Smith The user should pass in a string 'prefix' of 5130dc4c0fb0SBarry Smith sufficient length to hold the prefix. 5131dc4c0fb0SBarry Smith 51321cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetOptionsPrefix()`, `SNESAppendOptionsPrefix()` 51333c7409f5SSatish Balay @*/ 5134d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetOptionsPrefix(SNES snes, const char *prefix[]) 5135d71ae5a4SJacob Faibussowitsch { 51363a40ed3dSBarry Smith PetscFunctionBegin; 51370700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 51389566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)snes, prefix)); 51393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 51403c7409f5SSatish Balay } 51413c7409f5SSatish Balay 51423cea93caSBarry Smith /*@C 51431c84c290SBarry Smith SNESRegister - Adds a method to the nonlinear solver package. 51441c84c290SBarry Smith 514520f4b53cSBarry Smith Not Collective 51461c84c290SBarry Smith 51471c84c290SBarry Smith Input Parameters: 514820f4b53cSBarry Smith + sname - name of a new user-defined solver 514920f4b53cSBarry Smith - function - routine to create method context 51501c84c290SBarry Smith 5151dc4c0fb0SBarry Smith Level: advanced 5152dc4c0fb0SBarry Smith 5153f6dfbefdSBarry Smith Note: 5154f6dfbefdSBarry Smith `SNESRegister()` may be called multiple times to add several user-defined solvers. 51551c84c290SBarry Smith 5156e4094ef1SJacob Faibussowitsch Example Usage: 51571c84c290SBarry Smith .vb 5158bdf89e91SBarry Smith SNESRegister("my_solver", MySolverCreate); 51591c84c290SBarry Smith .ve 51601c84c290SBarry Smith 51611c84c290SBarry Smith Then, your solver can be chosen with the procedural interface via 51621c84c290SBarry Smith $ SNESSetType(snes, "my_solver") 51631c84c290SBarry Smith or at runtime via the option 51641c84c290SBarry Smith $ -snes_type my_solver 51651c84c290SBarry Smith 51661cc06b55SBarry Smith .seealso: [](ch_snes), `SNESRegisterAll()`, `SNESRegisterDestroy()` 51673cea93caSBarry Smith @*/ 5168d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESRegister(const char sname[], PetscErrorCode (*function)(SNES)) 5169d71ae5a4SJacob Faibussowitsch { 5170b2002411SLois Curfman McInnes PetscFunctionBegin; 51719566063dSJacob Faibussowitsch PetscCall(SNESInitializePackage()); 51729566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&SNESList, sname, function)); 51733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5174b2002411SLois Curfman McInnes } 5175da9b6338SBarry Smith 5176d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestLocalMin(SNES snes) 5177d71ae5a4SJacob Faibussowitsch { 517877431f27SBarry Smith PetscInt N, i, j; 5179da9b6338SBarry Smith Vec u, uh, fh; 5180da9b6338SBarry Smith PetscScalar value; 5181da9b6338SBarry Smith PetscReal norm; 5182da9b6338SBarry Smith 5183da9b6338SBarry Smith PetscFunctionBegin; 51849566063dSJacob Faibussowitsch PetscCall(SNESGetSolution(snes, &u)); 51859566063dSJacob Faibussowitsch PetscCall(VecDuplicate(u, &uh)); 51869566063dSJacob Faibussowitsch PetscCall(VecDuplicate(u, &fh)); 5187da9b6338SBarry Smith 5188da9b6338SBarry Smith /* currently only works for sequential */ 51899566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Testing FormFunction() for local min\n")); 51909566063dSJacob Faibussowitsch PetscCall(VecGetSize(u, &N)); 5191da9b6338SBarry Smith for (i = 0; i < N; i++) { 51929566063dSJacob Faibussowitsch PetscCall(VecCopy(u, uh)); 519363a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "i = %" PetscInt_FMT "\n", i)); 5194da9b6338SBarry Smith for (j = -10; j < 11; j++) { 51958b49ba18SBarry Smith value = PetscSign(j) * PetscExpReal(PetscAbs(j) - 10.0); 51969566063dSJacob Faibussowitsch PetscCall(VecSetValue(uh, i, value, ADD_VALUES)); 51979566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, uh, fh)); 51989566063dSJacob Faibussowitsch PetscCall(VecNorm(fh, NORM_2, &norm)); 519963a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), " j norm %" PetscInt_FMT " %18.16e\n", j, (double)norm)); 5200da9b6338SBarry Smith value = -value; 52019566063dSJacob Faibussowitsch PetscCall(VecSetValue(uh, i, value, ADD_VALUES)); 5202da9b6338SBarry Smith } 5203da9b6338SBarry Smith } 52049566063dSJacob Faibussowitsch PetscCall(VecDestroy(&uh)); 52059566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fh)); 52063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5207da9b6338SBarry Smith } 520871f87433Sdalcinl 520971f87433Sdalcinl /*@ 5210f6dfbefdSBarry Smith SNESKSPSetUseEW - Sets `SNES` to the use Eisenstat-Walker method for 521171f87433Sdalcinl computing relative tolerance for linear solvers within an inexact 521271f87433Sdalcinl Newton method. 521371f87433Sdalcinl 5214c3339decSBarry Smith Logically Collective 521571f87433Sdalcinl 521671f87433Sdalcinl Input Parameters: 5217f6dfbefdSBarry Smith + snes - `SNES` context 5218f6dfbefdSBarry Smith - flag - `PETSC_TRUE` or `PETSC_FALSE` 521971f87433Sdalcinl 5220f6dfbefdSBarry Smith Options Database Keys: 522164ba62caSBarry Smith + -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence 522264ba62caSBarry Smith . -snes_ksp_ew_version ver - version of Eisenstat-Walker method 522364ba62caSBarry Smith . -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0 522464ba62caSBarry Smith . -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax 522564ba62caSBarry Smith . -snes_ksp_ew_gamma <gamma> - Sets gamma 522664ba62caSBarry Smith . -snes_ksp_ew_alpha <alpha> - Sets alpha 522764ba62caSBarry Smith . -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2 522864ba62caSBarry Smith - -snes_ksp_ew_threshold <threshold> - Sets threshold 522964ba62caSBarry Smith 5230dc4c0fb0SBarry Smith Level: advanced 5231dc4c0fb0SBarry Smith 5232f6dfbefdSBarry Smith Note: 5233f6dfbefdSBarry Smith The default is to use a constant relative tolerance for 523471f87433Sdalcinl the inner linear solvers. Alternatively, one can use the 52351d27aa22SBarry Smith Eisenstat-Walker method {cite}`ew96`, where the relative convergence tolerance 523671f87433Sdalcinl is reset at each Newton iteration according progress of the nonlinear 523771f87433Sdalcinl solver. 523871f87433Sdalcinl 52391cc06b55SBarry Smith .seealso: [](ch_snes), `KSP`, `SNES`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()` 524071f87433Sdalcinl @*/ 5241d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetUseEW(SNES snes, PetscBool flag) 5242d71ae5a4SJacob Faibussowitsch { 524371f87433Sdalcinl PetscFunctionBegin; 52440700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5245acfcf0e5SJed Brown PetscValidLogicalCollectiveBool(snes, flag, 2); 524671f87433Sdalcinl snes->ksp_ewconv = flag; 52473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 524871f87433Sdalcinl } 524971f87433Sdalcinl 525071f87433Sdalcinl /*@ 5251f6dfbefdSBarry Smith SNESKSPGetUseEW - Gets if `SNES` is using Eisenstat-Walker method 525271f87433Sdalcinl for computing relative tolerance for linear solvers within an 525371f87433Sdalcinl inexact Newton method. 525471f87433Sdalcinl 525571f87433Sdalcinl Not Collective 525671f87433Sdalcinl 525771f87433Sdalcinl Input Parameter: 5258f6dfbefdSBarry Smith . snes - `SNES` context 525971f87433Sdalcinl 526071f87433Sdalcinl Output Parameter: 5261f6dfbefdSBarry Smith . flag - `PETSC_TRUE` or `PETSC_FALSE` 526271f87433Sdalcinl 526371f87433Sdalcinl Level: advanced 526471f87433Sdalcinl 52651cc06b55SBarry Smith .seealso: [](ch_snes), `SNESKSPSetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()` 526671f87433Sdalcinl @*/ 5267d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag) 5268d71ae5a4SJacob Faibussowitsch { 526971f87433Sdalcinl PetscFunctionBegin; 52700700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 52714f572ea9SToby Isaac PetscAssertPointer(flag, 2); 527271f87433Sdalcinl *flag = snes->ksp_ewconv; 52733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 527471f87433Sdalcinl } 527571f87433Sdalcinl 527671f87433Sdalcinl /*@ 5277fa9f3622SBarry Smith SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker 527871f87433Sdalcinl convergence criteria for the linear solvers within an inexact 527971f87433Sdalcinl Newton method. 528071f87433Sdalcinl 5281c3339decSBarry Smith Logically Collective 528271f87433Sdalcinl 528371f87433Sdalcinl Input Parameters: 5284f6dfbefdSBarry Smith + snes - `SNES` context 52850f0abf79SStefano Zampini . version - version 1, 2 (default is 2), 3 or 4 528671f87433Sdalcinl . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 528771f87433Sdalcinl . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 528871f87433Sdalcinl . gamma - multiplicative factor for version 2 rtol computation 528971f87433Sdalcinl (0 <= gamma2 <= 1) 529071f87433Sdalcinl . alpha - power for version 2 rtol computation (1 < alpha <= 2) 529171f87433Sdalcinl . alpha2 - power for safeguard 529271f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1) 529371f87433Sdalcinl 5294dc4c0fb0SBarry Smith Level: advanced 5295dc4c0fb0SBarry Smith 5296f6dfbefdSBarry Smith Notes: 529771f87433Sdalcinl Version 3 was contributed by Luis Chacon, June 2006. 529871f87433Sdalcinl 5299f6dfbefdSBarry Smith Use `PETSC_DEFAULT` to retain the default for any of the parameters. 530071f87433Sdalcinl 53011cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()` 530271f87433Sdalcinl @*/ 5303d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetParametersEW(SNES snes, PetscInt version, PetscReal rtol_0, PetscReal rtol_max, PetscReal gamma, PetscReal alpha, PetscReal alpha2, PetscReal threshold) 5304d71ae5a4SJacob Faibussowitsch { 5305fa9f3622SBarry Smith SNESKSPEW *kctx; 53065fd66863SKarl Rupp 530771f87433Sdalcinl PetscFunctionBegin; 53080700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5309fa9f3622SBarry Smith kctx = (SNESKSPEW *)snes->kspconvctx; 53105f80ce2aSJacob Faibussowitsch PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing"); 5311c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, version, 2); 5312c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, rtol_0, 3); 5313c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, rtol_max, 4); 5314c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, gamma, 5); 5315c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, alpha, 6); 5316c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, alpha2, 7); 5317c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, threshold, 8); 531871f87433Sdalcinl 531971f87433Sdalcinl if (version != PETSC_DEFAULT) kctx->version = version; 532013bcc0bdSJacob Faibussowitsch if (rtol_0 != (PetscReal)PETSC_DEFAULT) kctx->rtol_0 = rtol_0; 532113bcc0bdSJacob Faibussowitsch if (rtol_max != (PetscReal)PETSC_DEFAULT) kctx->rtol_max = rtol_max; 532213bcc0bdSJacob Faibussowitsch if (gamma != (PetscReal)PETSC_DEFAULT) kctx->gamma = gamma; 532313bcc0bdSJacob Faibussowitsch if (alpha != (PetscReal)PETSC_DEFAULT) kctx->alpha = alpha; 532413bcc0bdSJacob Faibussowitsch if (alpha2 != (PetscReal)PETSC_DEFAULT) kctx->alpha2 = alpha2; 532513bcc0bdSJacob Faibussowitsch if (threshold != (PetscReal)PETSC_DEFAULT) kctx->threshold = threshold; 532671f87433Sdalcinl 53270f0abf79SStefano 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); 53280b121fc5SBarry 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); 53290b121fc5SBarry 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); 53300b121fc5SBarry 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); 53310b121fc5SBarry 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); 53320b121fc5SBarry 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); 53333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 533471f87433Sdalcinl } 533571f87433Sdalcinl 533671f87433Sdalcinl /*@ 5337fa9f3622SBarry Smith SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker 533871f87433Sdalcinl convergence criteria for the linear solvers within an inexact 533971f87433Sdalcinl Newton method. 534071f87433Sdalcinl 534171f87433Sdalcinl Not Collective 534271f87433Sdalcinl 534397bb3fdcSJose E. Roman Input Parameter: 5344f6dfbefdSBarry Smith . snes - `SNES` context 534571f87433Sdalcinl 534671f87433Sdalcinl Output Parameters: 53470f0abf79SStefano Zampini + version - version 1, 2 (default is 2), 3 or 4 534871f87433Sdalcinl . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 534971f87433Sdalcinl . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 5350bf388a1fSBarry Smith . gamma - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1) 535171f87433Sdalcinl . alpha - power for version 2 rtol computation (1 < alpha <= 2) 535271f87433Sdalcinl . alpha2 - power for safeguard 535371f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1) 535471f87433Sdalcinl 535571f87433Sdalcinl Level: advanced 535671f87433Sdalcinl 53571cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPSetParametersEW()` 535871f87433Sdalcinl @*/ 5359d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetParametersEW(SNES snes, PetscInt *version, PetscReal *rtol_0, PetscReal *rtol_max, PetscReal *gamma, PetscReal *alpha, PetscReal *alpha2, PetscReal *threshold) 5360d71ae5a4SJacob Faibussowitsch { 5361fa9f3622SBarry Smith SNESKSPEW *kctx; 53625fd66863SKarl Rupp 536371f87433Sdalcinl PetscFunctionBegin; 53640700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5365fa9f3622SBarry Smith kctx = (SNESKSPEW *)snes->kspconvctx; 53665f80ce2aSJacob Faibussowitsch PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing"); 536771f87433Sdalcinl if (version) *version = kctx->version; 536871f87433Sdalcinl if (rtol_0) *rtol_0 = kctx->rtol_0; 536971f87433Sdalcinl if (rtol_max) *rtol_max = kctx->rtol_max; 537071f87433Sdalcinl if (gamma) *gamma = kctx->gamma; 537171f87433Sdalcinl if (alpha) *alpha = kctx->alpha; 537271f87433Sdalcinl if (alpha2) *alpha2 = kctx->alpha2; 537371f87433Sdalcinl if (threshold) *threshold = kctx->threshold; 53743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 537571f87433Sdalcinl } 537671f87433Sdalcinl 53775c0db29aSPierre Jolivet PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx) 5378d71ae5a4SJacob Faibussowitsch { 53795c0db29aSPierre Jolivet SNES snes = (SNES)ctx; 5380fa9f3622SBarry Smith SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx; 538171f87433Sdalcinl PetscReal rtol = PETSC_DEFAULT, stol; 538271f87433Sdalcinl 538371f87433Sdalcinl PetscFunctionBegin; 53843ba16761SJacob Faibussowitsch if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS); 538530058271SDmitry Karpeev if (!snes->iter) { 538630058271SDmitry Karpeev rtol = kctx->rtol_0; /* first time in, so use the original user rtol */ 53879566063dSJacob Faibussowitsch PetscCall(VecNorm(snes->vec_func, NORM_2, &kctx->norm_first)); 53880f0abf79SStefano Zampini } else { 53890fdf79fbSJacob 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); 539071f87433Sdalcinl if (kctx->version == 1) { 53910f0abf79SStefano Zampini rtol = PetscAbsReal(snes->norm - kctx->lresid_last) / kctx->norm_last; 539285ec1a3cSBarry Smith stol = PetscPowReal(kctx->rtol_last, kctx->alpha2); 539371f87433Sdalcinl if (stol > kctx->threshold) rtol = PetscMax(rtol, stol); 539471f87433Sdalcinl } else if (kctx->version == 2) { 539585ec1a3cSBarry Smith rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha); 539685ec1a3cSBarry Smith stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha); 539771f87433Sdalcinl if (stol > kctx->threshold) rtol = PetscMax(rtol, stol); 539871f87433Sdalcinl } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */ 539985ec1a3cSBarry Smith rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha); 540071f87433Sdalcinl /* safeguard: avoid sharp decrease of rtol */ 540185ec1a3cSBarry Smith stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha); 540271f87433Sdalcinl stol = PetscMax(rtol, stol); 540371f87433Sdalcinl rtol = PetscMin(kctx->rtol_0, stol); 540471f87433Sdalcinl /* safeguard: avoid oversolving */ 540530058271SDmitry Karpeev stol = kctx->gamma * (kctx->norm_first * snes->rtol) / snes->norm; 540671f87433Sdalcinl stol = PetscMax(rtol, stol); 540771f87433Sdalcinl rtol = PetscMin(kctx->rtol_0, stol); 54080fdf79fbSJacob Faibussowitsch } else /* if (kctx->version == 4) */ { 54090fdf79fbSJacob Faibussowitsch /* H.-B. An et al. Journal of Computational and Applied Mathematics 200 (2007) 47-60 */ 54100f0abf79SStefano Zampini PetscReal ared = PetscAbsReal(kctx->norm_last - snes->norm); 54110f0abf79SStefano Zampini PetscReal pred = PetscAbsReal(kctx->norm_last - kctx->lresid_last); 54120f0abf79SStefano Zampini PetscReal rk = ared / pred; 54130f0abf79SStefano Zampini if (rk < kctx->v4_p1) rtol = 1. - 2. * kctx->v4_p1; 54140f0abf79SStefano Zampini else if (rk < kctx->v4_p2) rtol = kctx->rtol_last; 54150f0abf79SStefano Zampini else if (rk < kctx->v4_p3) rtol = kctx->v4_m1 * kctx->rtol_last; 54160f0abf79SStefano Zampini else rtol = kctx->v4_m2 * kctx->rtol_last; 54170f0abf79SStefano Zampini 5418a4598233SStefano 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; 54190f0abf79SStefano Zampini kctx->rtol_last_2 = kctx->rtol_last; 54200f0abf79SStefano Zampini kctx->rk_last_2 = kctx->rk_last; 54210f0abf79SStefano Zampini kctx->rk_last = rk; 54220fdf79fbSJacob Faibussowitsch } 54230f0abf79SStefano Zampini } 54240f0abf79SStefano Zampini /* safeguard: avoid rtol greater than rtol_max */ 542571f87433Sdalcinl rtol = PetscMin(rtol, kctx->rtol_max); 54269566063dSJacob Faibussowitsch PetscCall(KSPSetTolerances(ksp, rtol, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT)); 542763a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "iter %" PetscInt_FMT ", Eisenstat-Walker (version %" PetscInt_FMT ") KSP rtol=%g\n", snes->iter, kctx->version, (double)rtol)); 54283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 542971f87433Sdalcinl } 543071f87433Sdalcinl 54315c0db29aSPierre Jolivet PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx) 5432d71ae5a4SJacob Faibussowitsch { 54335c0db29aSPierre Jolivet SNES snes = (SNES)ctx; 5434fa9f3622SBarry Smith SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx; 543571f87433Sdalcinl PCSide pcside; 543671f87433Sdalcinl Vec lres; 543771f87433Sdalcinl 543871f87433Sdalcinl PetscFunctionBegin; 54393ba16761SJacob Faibussowitsch if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS); 54409566063dSJacob Faibussowitsch PetscCall(KSPGetTolerances(ksp, &kctx->rtol_last, NULL, NULL, NULL)); 544171dbe336SPeter Brune kctx->norm_last = snes->norm; 54420f0abf79SStefano Zampini if (kctx->version == 1 || kctx->version == 4) { 54434f00ce20SMatthew G. Knepley PC pc; 54440f0abf79SStefano Zampini PetscBool getRes; 54454f00ce20SMatthew G. Knepley 54469566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksp, &pc)); 54470f0abf79SStefano Zampini PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &getRes)); 54480f0abf79SStefano Zampini if (!getRes) { 54490f0abf79SStefano Zampini KSPNormType normtype; 54500f0abf79SStefano Zampini 54510f0abf79SStefano Zampini PetscCall(KSPGetNormType(ksp, &normtype)); 54520f0abf79SStefano Zampini getRes = (PetscBool)(normtype == KSP_NORM_UNPRECONDITIONED); 54530f0abf79SStefano Zampini } 54549566063dSJacob Faibussowitsch PetscCall(KSPGetPCSide(ksp, &pcside)); 54550f0abf79SStefano Zampini if (pcside == PC_RIGHT || getRes) { /* KSP residual is true linear residual */ 54569566063dSJacob Faibussowitsch PetscCall(KSPGetResidualNorm(ksp, &kctx->lresid_last)); 545771f87433Sdalcinl } else { 545871f87433Sdalcinl /* KSP residual is preconditioned residual */ 545971f87433Sdalcinl /* compute true linear residual norm */ 54600f0abf79SStefano Zampini Mat J; 54610f0abf79SStefano Zampini PetscCall(KSPGetOperators(ksp, &J, NULL)); 54629566063dSJacob Faibussowitsch PetscCall(VecDuplicate(b, &lres)); 54630f0abf79SStefano Zampini PetscCall(MatMult(J, x, lres)); 54649566063dSJacob Faibussowitsch PetscCall(VecAYPX(lres, -1.0, b)); 54659566063dSJacob Faibussowitsch PetscCall(VecNorm(lres, NORM_2, &kctx->lresid_last)); 54669566063dSJacob Faibussowitsch PetscCall(VecDestroy(&lres)); 546771f87433Sdalcinl } 546871f87433Sdalcinl } 54693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 547071f87433Sdalcinl } 547171f87433Sdalcinl 5472d4211eb9SBarry Smith /*@ 5473f6dfbefdSBarry Smith SNESGetKSP - Returns the `KSP` context for a `SNES` solver. 5474d4211eb9SBarry Smith 5475420bcc1bSBarry Smith Not Collective, but if `snes` is parallel, then `ksp` is parallel 5476d4211eb9SBarry Smith 5477d4211eb9SBarry Smith Input Parameter: 5478f6dfbefdSBarry Smith . snes - the `SNES` context 5479d4211eb9SBarry Smith 5480d4211eb9SBarry Smith Output Parameter: 5481f6dfbefdSBarry Smith . ksp - the `KSP` context 5482d4211eb9SBarry Smith 5483dc4c0fb0SBarry Smith Level: beginner 5484dc4c0fb0SBarry Smith 5485d4211eb9SBarry Smith Notes: 5486f6dfbefdSBarry Smith The user can then directly manipulate the `KSP` context to set various 5487d4211eb9SBarry Smith options, etc. Likewise, the user can then extract and manipulate the 5488f6dfbefdSBarry Smith `PC` contexts as well. 5489f6dfbefdSBarry Smith 5490f6dfbefdSBarry Smith Some `SNESType`s do not use a `KSP` but a `KSP` is still returned by this function 5491d4211eb9SBarry Smith 54921cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSP`, `PC`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()` 5493d4211eb9SBarry Smith @*/ 5494d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetKSP(SNES snes, KSP *ksp) 5495d71ae5a4SJacob Faibussowitsch { 549671f87433Sdalcinl PetscFunctionBegin; 5497d4211eb9SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 54984f572ea9SToby Isaac PetscAssertPointer(ksp, 2); 5499d4211eb9SBarry Smith 5500d4211eb9SBarry Smith if (!snes->ksp) { 55019566063dSJacob Faibussowitsch PetscCall(KSPCreate(PetscObjectComm((PetscObject)snes), &snes->ksp)); 55029566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->ksp, (PetscObject)snes, 1)); 5503d4211eb9SBarry Smith 55045c0db29aSPierre Jolivet PetscCall(KSPSetPreSolve(snes->ksp, KSPPreSolve_SNESEW, snes)); 55055c0db29aSPierre Jolivet PetscCall(KSPSetPostSolve(snes->ksp, KSPPostSolve_SNESEW, snes)); 5506a5c2985bSBarry Smith 55079566063dSJacob Faibussowitsch PetscCall(KSPMonitorSetFromOptions(snes->ksp, "-snes_monitor_ksp", "snes_preconditioned_residual", snes)); 55089566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptions((PetscObject)snes->ksp, ((PetscObject)snes)->options)); 5509d4211eb9SBarry Smith } 5510d4211eb9SBarry Smith *ksp = snes->ksp; 55113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 551271f87433Sdalcinl } 55136c699258SBarry Smith 5514af0996ceSBarry Smith #include <petsc/private/dmimpl.h> 55156c699258SBarry Smith /*@ 5516f6dfbefdSBarry Smith SNESSetDM - Sets the `DM` that may be used by some nonlinear solvers or their underlying preconditioners 55176c699258SBarry Smith 5518c3339decSBarry Smith Logically Collective 55196c699258SBarry Smith 55206c699258SBarry Smith Input Parameters: 55212a808120SBarry Smith + snes - the nonlinear solver context 5522420bcc1bSBarry Smith - dm - the `DM`, cannot be `NULL` 5523dc4c0fb0SBarry Smith 5524dc4c0fb0SBarry Smith Level: intermediate 55256c699258SBarry Smith 5526f6dfbefdSBarry Smith Note: 5527f6dfbefdSBarry Smith A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`, 5528f6dfbefdSBarry Smith even when not using interfaces like `DMSNESSetFunction()`. Use `DMClone()` to get a distinct `DM` when solving different 5529e03a659cSJed Brown problems using the same function space. 5530e03a659cSJed Brown 5531420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()` 55326c699258SBarry Smith @*/ 5533d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDM(SNES snes, DM dm) 5534d71ae5a4SJacob Faibussowitsch { 5535345fed2cSBarry Smith KSP ksp; 5536942e3340SBarry Smith DMSNES sdm; 55376c699258SBarry Smith 55386c699258SBarry Smith PetscFunctionBegin; 55390700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 55402a808120SBarry Smith PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 55419566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 5542942e3340SBarry Smith if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */ 554351f4b3c7SToby Isaac if (snes->dm->dmsnes && !dm->dmsnes) { 55449566063dSJacob Faibussowitsch PetscCall(DMCopyDMSNES(snes->dm, dm)); 55459566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(snes->dm, &sdm)); 5546f5af7f23SKarl Rupp if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */ 55476cab3a1bSJed Brown } 55489566063dSJacob Faibussowitsch PetscCall(DMCoarsenHookRemove(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes)); 55499566063dSJacob Faibussowitsch PetscCall(DMDestroy(&snes->dm)); 55506cab3a1bSJed Brown } 55516c699258SBarry Smith snes->dm = dm; 5552116d1032SJed Brown snes->dmAuto = PETSC_FALSE; 5553f5af7f23SKarl Rupp 55549566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 55559566063dSJacob Faibussowitsch PetscCall(KSPSetDM(ksp, dm)); 55569566063dSJacob Faibussowitsch PetscCall(KSPSetDMActive(ksp, PETSC_FALSE)); 5557efd4aadfSBarry Smith if (snes->npc) { 55589566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes->npc, snes->dm)); 55599566063dSJacob Faibussowitsch PetscCall(SNESSetNPCSide(snes, snes->npcside)); 55602c155ee1SBarry Smith } 55613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 55626c699258SBarry Smith } 55636c699258SBarry Smith 55646c699258SBarry Smith /*@ 5565420bcc1bSBarry Smith SNESGetDM - Gets the `DM` that may be used by some solvers/preconditioners 55666c699258SBarry Smith 5567f6dfbefdSBarry Smith Not Collective but dm obtained is parallel on snes 55686c699258SBarry Smith 55696c699258SBarry Smith Input Parameter: 5570420bcc1bSBarry Smith . snes - the `SNES` context 55716c699258SBarry Smith 55726c699258SBarry Smith Output Parameter: 5573420bcc1bSBarry Smith . dm - the `DM` 55746c699258SBarry Smith 55756c699258SBarry Smith Level: intermediate 55766c699258SBarry Smith 5577420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESSetDM()`, `KSPSetDM()`, `KSPGetDM()` 55786c699258SBarry Smith @*/ 5579d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDM(SNES snes, DM *dm) 5580d71ae5a4SJacob Faibussowitsch { 55816c699258SBarry Smith PetscFunctionBegin; 55820700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 55836cab3a1bSJed Brown if (!snes->dm) { 55849566063dSJacob Faibussowitsch PetscCall(DMShellCreate(PetscObjectComm((PetscObject)snes), &snes->dm)); 5585116d1032SJed Brown snes->dmAuto = PETSC_TRUE; 55866cab3a1bSJed Brown } 55876c699258SBarry Smith *dm = snes->dm; 55883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 55896c699258SBarry Smith } 55900807856dSBarry Smith 559131823bd8SMatthew G Knepley /*@ 5592be95d8f1SBarry Smith SNESSetNPC - Sets the nonlinear preconditioner to be used. 559331823bd8SMatthew G Knepley 5594c3339decSBarry Smith Collective 559531823bd8SMatthew G Knepley 559631823bd8SMatthew G Knepley Input Parameters: 5597f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 5598420bcc1bSBarry Smith - npc - the nonlinear preconditioner object 559931823bd8SMatthew G Knepley 5600dc4c0fb0SBarry Smith Level: developer 5601dc4c0fb0SBarry Smith 560231823bd8SMatthew G Knepley Notes: 5603f6dfbefdSBarry Smith Use `SNESGetNPC()` to retrieve the preconditioner context (for example, 560431823bd8SMatthew G Knepley to configure it using the API). 560531823bd8SMatthew G Knepley 5606f6dfbefdSBarry Smith Only some `SNESType` can use a nonlinear preconditioner 5607f6dfbefdSBarry Smith 5608420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNGS`, `SNESFAS`, `SNESGetNPC()`, `SNESHasNPC()` 560931823bd8SMatthew G Knepley @*/ 5610d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPC(SNES snes, SNES npc) 5611d71ae5a4SJacob Faibussowitsch { 561231823bd8SMatthew G Knepley PetscFunctionBegin; 561331823bd8SMatthew G Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5614f6dfbefdSBarry Smith PetscValidHeaderSpecific(npc, SNES_CLASSID, 2); 5615f6dfbefdSBarry Smith PetscCheckSameComm(snes, 1, npc, 2); 5616f6dfbefdSBarry Smith PetscCall(PetscObjectReference((PetscObject)npc)); 56179566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&snes->npc)); 5618f6dfbefdSBarry Smith snes->npc = npc; 56193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 562031823bd8SMatthew G Knepley } 562131823bd8SMatthew G Knepley 562231823bd8SMatthew G Knepley /*@ 5623f6dfbefdSBarry Smith SNESGetNPC - Gets a nonlinear preconditioning solver SNES` to be used to precondition the original nonlinear solver. 562431823bd8SMatthew G Knepley 5625f6dfbefdSBarry Smith Not Collective; but any changes to the obtained the npc object must be applied collectively 562631823bd8SMatthew G Knepley 562731823bd8SMatthew G Knepley Input Parameter: 5628f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 562931823bd8SMatthew G Knepley 563031823bd8SMatthew G Knepley Output Parameter: 5631e4094ef1SJacob Faibussowitsch . pc - preconditioner context 563231823bd8SMatthew G Knepley 5633f6dfbefdSBarry Smith Options Database Key: 5634f6dfbefdSBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner 5635b5badacbSBarry Smith 5636dc4c0fb0SBarry Smith Level: developer 5637dc4c0fb0SBarry Smith 563895452b02SPatrick Sanan Notes: 5639f6dfbefdSBarry Smith If a `SNES` was previously set with `SNESSetNPC()` then that value is returned, otherwise a new `SNES` object is created. 5640be95d8f1SBarry Smith 5641f6dfbefdSBarry Smith The (preconditioner) `SNES` returned automatically inherits the same nonlinear function and Jacobian supplied to the original 5642f6dfbefdSBarry Smith `SNES` 5643951fe5abSBarry Smith 56441cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESHasNPC()`, `SNES`, `SNESCreate()` 564531823bd8SMatthew G Knepley @*/ 5646d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPC(SNES snes, SNES *pc) 5647d71ae5a4SJacob Faibussowitsch { 5648a64e098fSPeter Brune const char *optionsprefix; 564931823bd8SMatthew G Knepley 565031823bd8SMatthew G Knepley PetscFunctionBegin; 565131823bd8SMatthew G Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 56524f572ea9SToby Isaac PetscAssertPointer(pc, 2); 5653efd4aadfSBarry Smith if (!snes->npc) { 5654ec785e5bSStefano Zampini void *ctx; 5655ec785e5bSStefano Zampini 56569566063dSJacob Faibussowitsch PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &snes->npc)); 56579566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->npc, (PetscObject)snes, 1)); 56589566063dSJacob Faibussowitsch PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 56599566063dSJacob Faibussowitsch PetscCall(SNESSetOptionsPrefix(snes->npc, optionsprefix)); 56609566063dSJacob Faibussowitsch PetscCall(SNESAppendOptionsPrefix(snes->npc, "npc_")); 5661fb87a551SStefano Zampini if (snes->ops->usercompute) { 5662fb87a551SStefano Zampini PetscCall(SNESSetComputeApplicationContext(snes, snes->ops->usercompute, snes->ops->userdestroy)); 5663fb87a551SStefano Zampini } else { 5664ec785e5bSStefano Zampini PetscCall(SNESGetApplicationContext(snes, &ctx)); 5665ec785e5bSStefano Zampini PetscCall(SNESSetApplicationContext(snes->npc, ctx)); 5666fb87a551SStefano Zampini } 56679566063dSJacob Faibussowitsch PetscCall(SNESSetCountersReset(snes->npc, PETSC_FALSE)); 566831823bd8SMatthew G Knepley } 5669efd4aadfSBarry Smith *pc = snes->npc; 56703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 567131823bd8SMatthew G Knepley } 567231823bd8SMatthew G Knepley 56733ad1a0b9SPatrick Farrell /*@ 56743ad1a0b9SPatrick Farrell SNESHasNPC - Returns whether a nonlinear preconditioner exists 56753ad1a0b9SPatrick Farrell 56763ad1a0b9SPatrick Farrell Not Collective 56773ad1a0b9SPatrick Farrell 56783ad1a0b9SPatrick Farrell Input Parameter: 5679f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 56803ad1a0b9SPatrick Farrell 56813ad1a0b9SPatrick Farrell Output Parameter: 5682420bcc1bSBarry Smith . has_npc - whether the `SNES` has a nonlinear preconditioner or not 56833ad1a0b9SPatrick Farrell 56843ad1a0b9SPatrick Farrell Level: developer 56853ad1a0b9SPatrick Farrell 56861cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESGetNPC()` 56873ad1a0b9SPatrick Farrell @*/ 5688d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc) 5689d71ae5a4SJacob Faibussowitsch { 56903ad1a0b9SPatrick Farrell PetscFunctionBegin; 56913ad1a0b9SPatrick Farrell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5692efd4aadfSBarry Smith *has_npc = (PetscBool)(snes->npc ? PETSC_TRUE : PETSC_FALSE); 56933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 56943ad1a0b9SPatrick Farrell } 56953ad1a0b9SPatrick Farrell 5696c40d0f55SPeter Brune /*@ 5697420bcc1bSBarry Smith SNESSetNPCSide - Sets the nonlinear preconditioning side. 5698c40d0f55SPeter Brune 5699c3339decSBarry Smith Logically Collective 5700c40d0f55SPeter Brune 5701c40d0f55SPeter Brune Input Parameter: 5702f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 5703c40d0f55SPeter Brune 5704c40d0f55SPeter Brune Output Parameter: 5705c40d0f55SPeter Brune . side - the preconditioning side, where side is one of 5706c40d0f55SPeter Brune .vb 57072d547940SBarry Smith PC_LEFT - left preconditioning 57082d547940SBarry Smith PC_RIGHT - right preconditioning (default for most nonlinear solvers) 5709c40d0f55SPeter Brune .ve 5710c40d0f55SPeter Brune 5711f6dfbefdSBarry Smith Options Database Key: 571267b8a455SSatish Balay . -snes_npc_side <right,left> - nonlinear preconditioner side 5713c40d0f55SPeter Brune 5714dc4c0fb0SBarry Smith Level: intermediate 5715dc4c0fb0SBarry Smith 5716f6dfbefdSBarry Smith Note: 5717f6dfbefdSBarry Smith `SNESNRICHARDSON` and `SNESNCG` only support left preconditioning. 57182d547940SBarry Smith 5719420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNRICHARDSON`, `SNESNCG`, `SNESType`, `SNESGetNPCSide()`, `KSPSetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide` 5720c40d0f55SPeter Brune @*/ 5721d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPCSide(SNES snes, PCSide side) 5722d71ae5a4SJacob Faibussowitsch { 5723c40d0f55SPeter Brune PetscFunctionBegin; 5724c40d0f55SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5725c40d0f55SPeter Brune PetscValidLogicalCollectiveEnum(snes, side, 2); 5726b552625fSStefano Zampini if (side == PC_SIDE_DEFAULT) side = PC_RIGHT; 572754c59aa7SJacob Faibussowitsch PetscCheck((side == PC_LEFT) || (side == PC_RIGHT), PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Only PC_LEFT and PC_RIGHT are supported"); 5728efd4aadfSBarry Smith snes->npcside = side; 57293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5730c40d0f55SPeter Brune } 5731c40d0f55SPeter Brune 5732c40d0f55SPeter Brune /*@ 5733be95d8f1SBarry Smith SNESGetNPCSide - Gets the preconditioning side. 5734c40d0f55SPeter Brune 5735c40d0f55SPeter Brune Not Collective 5736c40d0f55SPeter Brune 5737c40d0f55SPeter Brune Input Parameter: 5738f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 5739c40d0f55SPeter Brune 5740c40d0f55SPeter Brune Output Parameter: 5741c40d0f55SPeter Brune . side - the preconditioning side, where side is one of 5742c40d0f55SPeter Brune .vb 5743f6dfbefdSBarry Smith `PC_LEFT` - left preconditioning 5744f6dfbefdSBarry Smith `PC_RIGHT` - right preconditioning (default for most nonlinear solvers) 5745c40d0f55SPeter Brune .ve 5746c40d0f55SPeter Brune 5747c40d0f55SPeter Brune Level: intermediate 5748c40d0f55SPeter Brune 5749420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNPCSide()`, `KSPGetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide` 5750c40d0f55SPeter Brune @*/ 5751d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPCSide(SNES snes, PCSide *side) 5752d71ae5a4SJacob Faibussowitsch { 5753c40d0f55SPeter Brune PetscFunctionBegin; 5754c40d0f55SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 57554f572ea9SToby Isaac PetscAssertPointer(side, 2); 5756efd4aadfSBarry Smith *side = snes->npcside; 57573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5758c40d0f55SPeter Brune } 5759c40d0f55SPeter Brune 57609e764e56SPeter Brune /*@ 5761420bcc1bSBarry Smith SNESSetLineSearch - Sets the linesearch to be used for `SNES` 57629e764e56SPeter Brune 5763c3339decSBarry Smith Collective 57649e764e56SPeter Brune 57659e764e56SPeter Brune Input Parameters: 5766f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 57679e764e56SPeter Brune - linesearch - the linesearch object 57689e764e56SPeter Brune 5769dc4c0fb0SBarry Smith Level: developer 5770dc4c0fb0SBarry Smith 5771f6dfbefdSBarry Smith Note: 5772420bcc1bSBarry Smith This is almost never used, rather one uses `SNESGetLineSearch()` to retrieve the line search and set options on it 57739e764e56SPeter Brune to configure it using the API). 57749e764e56SPeter Brune 5775420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()` 57769e764e56SPeter Brune @*/ 5777d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch) 5778d71ae5a4SJacob Faibussowitsch { 57799e764e56SPeter Brune PetscFunctionBegin; 57809e764e56SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5781f1c6b773SPeter Brune PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 2); 57829e764e56SPeter Brune PetscCheckSameComm(snes, 1, linesearch, 2); 57839566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)linesearch)); 57849566063dSJacob Faibussowitsch PetscCall(SNESLineSearchDestroy(&snes->linesearch)); 5785f5af7f23SKarl Rupp 57869e764e56SPeter Brune snes->linesearch = linesearch; 57873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 57889e764e56SPeter Brune } 57899e764e56SPeter Brune 5790a34ceb2aSJed Brown /*@ 5791420bcc1bSBarry Smith SNESGetLineSearch - Returns the line search context possibly set with `SNESSetLineSearch()` 5792f6dfbefdSBarry Smith or creates a default line search instance associated with the `SNES` and returns it. 57939e764e56SPeter Brune 57949e764e56SPeter Brune Not Collective 57959e764e56SPeter Brune 57969e764e56SPeter Brune Input Parameter: 5797f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 57989e764e56SPeter Brune 57999e764e56SPeter Brune Output Parameter: 58009e764e56SPeter Brune . linesearch - linesearch context 58019e764e56SPeter Brune 5802162e0bf5SPeter Brune Level: beginner 58039e764e56SPeter Brune 58041cc06b55SBarry Smith .seealso: [](ch_snes), `SNESLineSearch`, `SNESSetLineSearch()`, `SNESLineSearchCreate()` 58059e764e56SPeter Brune @*/ 5806d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch) 5807d71ae5a4SJacob Faibussowitsch { 58089e764e56SPeter Brune const char *optionsprefix; 58099e764e56SPeter Brune 58109e764e56SPeter Brune PetscFunctionBegin; 58119e764e56SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 58124f572ea9SToby Isaac PetscAssertPointer(linesearch, 2); 58139e764e56SPeter Brune if (!snes->linesearch) { 58149566063dSJacob Faibussowitsch PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 58159566063dSJacob Faibussowitsch PetscCall(SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch)); 58169566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetSNES(snes->linesearch, snes)); 58179566063dSJacob Faibussowitsch PetscCall(SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix)); 58189566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->linesearch, (PetscObject)snes, 1)); 58199e764e56SPeter Brune } 58209e764e56SPeter Brune *linesearch = snes->linesearch; 58213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 58229e764e56SPeter Brune } 5823