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 274*ffeef943SBarry 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 324*ffeef943SBarry 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 348*ffeef943SBarry 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; 6840298fd71SBarry Smith Vec X, Xnamed = NULL; 685dfe15315SJed Brown DM dmsave; 6864e269d77SPeter Brune void *ctxsave; 6878434afd1SBarry Smith SNESJacobianFn *jac = NULL; 688caa4e7f2SJed Brown 689caa4e7f2SJed Brown PetscFunctionBegin; 690dfe15315SJed Brown dmsave = snes->dm; 6919566063dSJacob Faibussowitsch PetscCall(KSPGetDM(ksp, &snes->dm)); 692dfe15315SJed Brown if (dmsave == snes->dm) X = snes->vec_sol; /* We are on the finest level */ 6939371c9d4SSatish Balay else { /* We are on a coarser level, this vec was initialized using a DM restrict hook */ PetscCall(DMGetNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed)); 694dfe15315SJed Brown X = Xnamed; 6959566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, NULL, NULL, &jac, &ctxsave)); 6964e269d77SPeter Brune /* If the DM's don't match up, the MatFDColoring context needed for the jacobian won't match up either -- fixit. */ 69748a46eb9SPierre Jolivet if (jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, SNESComputeJacobianDefaultColor, NULL)); 6984e269d77SPeter Brune } 6994dde8bb0SMatthew G. Knepley /* Make sure KSP DM has the Jacobian computation routine */ 7004dde8bb0SMatthew G. Knepley { 7014dde8bb0SMatthew G. Knepley DMSNES sdm; 7024e269d77SPeter Brune 7039566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(snes->dm, &sdm)); 70448a46eb9SPierre Jolivet if (!sdm->ops->computejacobian) PetscCall(DMCopyDMSNES(dmsave, snes->dm)); 7054dde8bb0SMatthew G. Knepley } 7062b93b426SMatthew G. Knepley /* Compute the operators */ 7079566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobian(snes, X, A, B)); 7082b93b426SMatthew G. Knepley /* Put the previous context back */ 70948a46eb9SPierre Jolivet if (snes->dm != dmsave && jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, jac, ctxsave)); 7104e269d77SPeter Brune 7119566063dSJacob Faibussowitsch if (Xnamed) PetscCall(DMRestoreNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed)); 712dfe15315SJed Brown snes->dm = dmsave; 7133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 714caa4e7f2SJed Brown } 715caa4e7f2SJed Brown 7166cab3a1bSJed Brown /*@ 717dc4c0fb0SBarry Smith SNESSetUpMatrices - ensures that matrices are available for `SNES` Newton-like methods, this is called by `SNESSetUp_XXX()` 7186cab3a1bSJed Brown 7196cab3a1bSJed Brown Collective 7206cab3a1bSJed Brown 7214165533cSJose E. Roman Input Parameter: 72220f4b53cSBarry Smith . snes - `SNES` object to configure 7236cab3a1bSJed Brown 7246cab3a1bSJed Brown Level: developer 7256cab3a1bSJed Brown 726dc4c0fb0SBarry Smith Note: 727dc4c0fb0SBarry Smith If the matrices do not yet exist it attempts to create them based on options previously set for the `SNES` such as `-snes_mf` 728dc4c0fb0SBarry Smith 72973a84a35SBarry Smith Developer Note: 73073a84a35SBarry Smith The functionality of this routine overlaps in a confusing way with the functionality of `SNESSetUpMatrixFree_Private()` which is called by 73173a84a35SBarry Smith `SNESSetUp()` but sometimes `SNESSetUpMatrices()` is called without `SNESSetUp()` being called. A refactorization to simplify the 73273a84a35SBarry Smith logic that handles the matrix-free case is desirable. 73373a84a35SBarry Smith 7341cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUp()` 7356cab3a1bSJed Brown @*/ 736d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUpMatrices(SNES snes) 737d71ae5a4SJacob Faibussowitsch { 7386cab3a1bSJed Brown DM dm; 739942e3340SBarry Smith DMSNES sdm; 7406cab3a1bSJed Brown 7416cab3a1bSJed Brown PetscFunctionBegin; 7429566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 7439566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 74473a84a35SBarry Smith if (!snes->jacobian && snes->mf && !snes->mf_operator && !snes->jacobian_pre) { 7456cab3a1bSJed Brown Mat J; 7466cab3a1bSJed Brown void *functx; 7479566063dSJacob Faibussowitsch PetscCall(MatCreateSNESMF(snes, &J)); 7489566063dSJacob Faibussowitsch PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix)); 7499566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(J)); 7509566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, NULL, &functx)); 7519566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J, J, NULL, NULL)); 7529566063dSJacob Faibussowitsch PetscCall(MatDestroy(&J)); 753caa4e7f2SJed Brown } else if (snes->mf_operator && !snes->jacobian_pre && !snes->jacobian) { 7546cab3a1bSJed Brown Mat J, B; 7559566063dSJacob Faibussowitsch PetscCall(MatCreateSNESMF(snes, &J)); 7569566063dSJacob Faibussowitsch PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix)); 7579566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(J)); 7589566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(snes->dm, &B)); 75906f20277SJed Brown /* sdm->computejacobian was already set to reach here */ 7609566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J, B, NULL, NULL)); 7619566063dSJacob Faibussowitsch PetscCall(MatDestroy(&J)); 7629566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 763caa4e7f2SJed Brown } else if (!snes->jacobian_pre) { 7641ba9b98eSMatthew G. Knepley PetscDS prob; 7656cab3a1bSJed Brown Mat J, B; 7661ba9b98eSMatthew G. Knepley PetscBool hasPrec = PETSC_FALSE; 7671ba9b98eSMatthew G. Knepley 7686cab3a1bSJed Brown J = snes->jacobian; 7699566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob)); 7709566063dSJacob Faibussowitsch if (prob) PetscCall(PetscDSHasJacobianPreconditioner(prob, &hasPrec)); 7719566063dSJacob Faibussowitsch if (J) PetscCall(PetscObjectReference((PetscObject)J)); 7729566063dSJacob Faibussowitsch else if (hasPrec) PetscCall(DMCreateMatrix(snes->dm, &J)); 7739566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(snes->dm, &B)); 7749566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J ? J : B, B, NULL, NULL)); 7759566063dSJacob Faibussowitsch PetscCall(MatDestroy(&J)); 7769566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 7776cab3a1bSJed Brown } 778caa4e7f2SJed Brown { 779caa4e7f2SJed Brown KSP ksp; 7809566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 7819566063dSJacob Faibussowitsch PetscCall(KSPSetComputeOperators(ksp, KSPComputeOperators_SNES, snes)); 7829566063dSJacob Faibussowitsch PetscCall(DMCoarsenHookAdd(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes)); 783caa4e7f2SJed Brown } 7843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7856cab3a1bSJed Brown } 7866cab3a1bSJed Brown 787d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESMonitorPauseFinal_Internal(SNES snes) 788d71ae5a4SJacob Faibussowitsch { 7895e7c47f3SMatthew G. Knepley PetscInt i; 7905e7c47f3SMatthew G. Knepley 7915e7c47f3SMatthew G. Knepley PetscFunctionBegin; 7923ba16761SJacob Faibussowitsch if (!snes->pauseFinal) PetscFunctionReturn(PETSC_SUCCESS); 7935e7c47f3SMatthew G. Knepley for (i = 0; i < snes->numbermonitors; ++i) { 7945e7c47f3SMatthew G. Knepley PetscViewerAndFormat *vf = (PetscViewerAndFormat *)snes->monitorcontext[i]; 7955e7c47f3SMatthew G. Knepley PetscDraw draw; 7965e7c47f3SMatthew G. Knepley PetscReal lpause; 7975e7c47f3SMatthew G. Knepley 7985e7c47f3SMatthew G. Knepley if (!vf) continue; 7995e7c47f3SMatthew G. Knepley if (vf->lg) { 8005e7c47f3SMatthew G. Knepley if (!PetscCheckPointer(vf->lg, PETSC_OBJECT)) continue; 8015e7c47f3SMatthew G. Knepley if (((PetscObject)vf->lg)->classid != PETSC_DRAWLG_CLASSID) continue; 8029566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(vf->lg, &draw)); 8039566063dSJacob Faibussowitsch PetscCall(PetscDrawGetPause(draw, &lpause)); 8049566063dSJacob Faibussowitsch PetscCall(PetscDrawSetPause(draw, -1.0)); 8059566063dSJacob Faibussowitsch PetscCall(PetscDrawPause(draw)); 8069566063dSJacob Faibussowitsch PetscCall(PetscDrawSetPause(draw, lpause)); 8075e7c47f3SMatthew G. Knepley } else { 8085e7c47f3SMatthew G. Knepley PetscBool isdraw; 8095e7c47f3SMatthew G. Knepley 8105e7c47f3SMatthew G. Knepley if (!PetscCheckPointer(vf->viewer, PETSC_OBJECT)) continue; 8115e7c47f3SMatthew G. Knepley if (((PetscObject)vf->viewer)->classid != PETSC_VIEWER_CLASSID) continue; 8129566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)vf->viewer, PETSCVIEWERDRAW, &isdraw)); 8135e7c47f3SMatthew G. Knepley if (!isdraw) continue; 8149566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(vf->viewer, 0, &draw)); 8159566063dSJacob Faibussowitsch PetscCall(PetscDrawGetPause(draw, &lpause)); 8169566063dSJacob Faibussowitsch PetscCall(PetscDrawSetPause(draw, -1.0)); 8179566063dSJacob Faibussowitsch PetscCall(PetscDrawPause(draw)); 8189566063dSJacob Faibussowitsch PetscCall(PetscDrawSetPause(draw, lpause)); 8195e7c47f3SMatthew G. Knepley } 8205e7c47f3SMatthew G. Knepley } 8213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8225e7c47f3SMatthew G. Knepley } 8235e7c47f3SMatthew G. Knepley 824fde5950dSBarry Smith /*@C 825fde5950dSBarry Smith SNESMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user 826fde5950dSBarry Smith 827c3339decSBarry Smith Collective 828fde5950dSBarry Smith 829fde5950dSBarry Smith Input Parameters: 830dc4c0fb0SBarry Smith + snes - `SNES` object you wish to monitor 831fde5950dSBarry Smith . name - the monitor type one is seeking 832fde5950dSBarry Smith . help - message indicating what monitoring is done 833fde5950dSBarry Smith . manual - manual page for the monitor 834fde5950dSBarry Smith . monitor - the monitor function 835f6dfbefdSBarry 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 836fde5950dSBarry Smith 837420bcc1bSBarry Smith Calling sequence of `monitor`: 838420bcc1bSBarry Smith + snes - the nonlinear solver context 839420bcc1bSBarry Smith . it - the current iteration 840420bcc1bSBarry Smith . r - the current function norm 841420bcc1bSBarry Smith - vf - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use 842420bcc1bSBarry Smith 843420bcc1bSBarry Smith Calling sequence of `monitorsetup`: 844420bcc1bSBarry Smith + snes - the nonlinear solver context 845420bcc1bSBarry Smith - vf - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use 846420bcc1bSBarry Smith 847f6dfbefdSBarry Smith Options Database Key: 848f6dfbefdSBarry Smith . -name - trigger the use of this monitor in `SNESSetFromOptions()` 849f6dfbefdSBarry Smith 850f6dfbefdSBarry Smith Level: advanced 851fde5950dSBarry Smith 8521cc06b55SBarry Smith .seealso: [](ch_snes), `PetscOptionsGetViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, 853db781477SPatrick Sanan `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()` 854e4094ef1SJacob Faibussowitsch `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, 855db781477SPatrick Sanan `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`, 856c2e3fba1SPatrick Sanan `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`, 857db781477SPatrick Sanan `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`, 858db781477SPatrick Sanan `PetscOptionsFList()`, `PetscOptionsEList()` 859fde5950dSBarry Smith @*/ 860420bcc1bSBarry 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)) 861d71ae5a4SJacob Faibussowitsch { 862fde5950dSBarry Smith PetscViewer viewer; 863fde5950dSBarry Smith PetscViewerFormat format; 864fde5950dSBarry Smith PetscBool flg; 865fde5950dSBarry Smith 866fde5950dSBarry Smith PetscFunctionBegin; 8679566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, name, &viewer, &format, &flg)); 868fde5950dSBarry Smith if (flg) { 869d43b4f6eSBarry Smith PetscViewerAndFormat *vf; 8709566063dSJacob Faibussowitsch PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf)); 871cd791dc2SBarry Smith PetscCall(PetscOptionsRestoreViewer(&viewer)); 8721baa6e33SBarry Smith if (monitorsetup) PetscCall((*monitorsetup)(snes, vf)); 8739566063dSJacob Faibussowitsch PetscCall(SNESMonitorSet(snes, (PetscErrorCode(*)(SNES, PetscInt, PetscReal, void *))monitor, vf, (PetscErrorCode(*)(void **))PetscViewerAndFormatDestroy)); 874fde5950dSBarry Smith } 8753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 876fde5950dSBarry Smith } 877fde5950dSBarry Smith 878a4598233SStefano Zampini PetscErrorCode SNESEWSetFromOptions_Private(SNESKSPEW *kctx, PetscBool print_api, MPI_Comm comm, const char *prefix) 879d71ae5a4SJacob Faibussowitsch { 880a4598233SStefano Zampini const char *api = print_api ? "SNESKSPSetParametersEW" : NULL; 881a4598233SStefano Zampini 8820f0abf79SStefano Zampini PetscFunctionBegin; 8830f0abf79SStefano Zampini PetscOptionsBegin(comm, prefix, "Eisenstat and Walker type forcing options", "KSP"); 884a4598233SStefano Zampini PetscCall(PetscOptionsInt("-ksp_ew_version", "Version 1, 2 or 3", api, kctx->version, &kctx->version, NULL)); 885a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_rtol0", "0 <= rtol0 < 1", api, kctx->rtol_0, &kctx->rtol_0, NULL)); 886a4598233SStefano Zampini kctx->rtol_max = PetscMax(kctx->rtol_0, kctx->rtol_max); 887a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_rtolmax", "0 <= rtolmax < 1", api, kctx->rtol_max, &kctx->rtol_max, NULL)); 888a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_gamma", "0 <= gamma <= 1", api, kctx->gamma, &kctx->gamma, NULL)); 889a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_alpha", "1 < alpha <= 2", api, kctx->alpha, &kctx->alpha, NULL)); 8900f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_alpha2", "alpha2", NULL, kctx->alpha2, &kctx->alpha2, NULL)); 891a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_threshold", "0 < threshold < 1", api, kctx->threshold, &kctx->threshold, NULL)); 8920f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_p1", "p1", NULL, kctx->v4_p1, &kctx->v4_p1, NULL)); 8930f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_p2", "p2", NULL, kctx->v4_p2, &kctx->v4_p2, NULL)); 8940f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_p3", "p3", NULL, kctx->v4_p3, &kctx->v4_p3, NULL)); 8950f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_m1", "Scaling when rk-1 in [p2,p3)", NULL, kctx->v4_m1, &kctx->v4_m1, NULL)); 8960f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_m2", "Scaling when rk-1 in [p3,+infty)", NULL, kctx->v4_m2, &kctx->v4_m2, NULL)); 8970f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_m3", "Threshold for successive rtol (0.1 in Eq.7)", NULL, kctx->v4_m3, &kctx->v4_m3, NULL)); 8980f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_m4", "Adaptation scaling (0.5 in Eq.7)", NULL, kctx->v4_m4, &kctx->v4_m4, NULL)); 8990f0abf79SStefano Zampini PetscOptionsEnd(); 9003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9010f0abf79SStefano Zampini } 9020f0abf79SStefano Zampini 9039b94acceSBarry Smith /*@ 904f6dfbefdSBarry Smith SNESSetFromOptions - Sets various `SNES` and `KSP` parameters from user options. 9059b94acceSBarry Smith 906c3339decSBarry Smith Collective 907c7afd0dbSLois Curfman McInnes 9089b94acceSBarry Smith Input Parameter: 909f6dfbefdSBarry Smith . snes - the `SNES` context 9109b94acceSBarry Smith 91136851e7fSLois Curfman McInnes Options Database Keys: 912f6dfbefdSBarry Smith + -snes_type <type> - newtonls, newtontr, ngmres, ncg, nrichardson, qn, vi, fas, `SNESType` for complete list 913ceaaa498SBarry Smith . -snes_stol <stol> - convergence tolerance in terms of the norm of the change in the solution between steps 91470441072SBarry Smith . -snes_atol <abstol> - absolute tolerance of residual norm 915b39c3a46SLois Curfman McInnes . -snes_rtol <rtol> - relative decrease in tolerance norm from initial 916e4d06f11SPatrick Farrell . -snes_divergence_tolerance <divtol> - if the residual goes above divtol*rnorm0, exit with divergence 917ceaaa498SBarry Smith . -snes_force_iteration <force> - force `SNESSolve()` to take at least one iteration 918b39c3a46SLois Curfman McInnes . -snes_max_it <max_it> - maximum number of iterations 919b39c3a46SLois Curfman McInnes . -snes_max_funcs <max_funcs> - maximum number of function evaluations 9204839bfe8SBarry Smith . -snes_max_fail <max_fail> - maximum number of line search failures allowed before stopping, default is none 921ddf469c8SBarry Smith . -snes_max_linear_solve_fail - number of linear solver failures before SNESSolve() stops 922a8054027SBarry Smith . -snes_lag_preconditioner <lag> - how often preconditioner is rebuilt (use -1 to never rebuild) 9233d5a8a6aSBarry Smith . -snes_lag_preconditioner_persists <true,false> - retains the -snes_lag_preconditioner information across multiple SNESSolve() 924e35cf81dSBarry Smith . -snes_lag_jacobian <lag> - how often Jacobian is rebuilt (use -1 to never rebuild) 9253d5a8a6aSBarry Smith . -snes_lag_jacobian_persists <true,false> - retains the -snes_lag_jacobian information across multiple SNESSolve() 9264a221d59SStefano Zampini . -snes_tr_tol <trtol> - trust region tolerance 927ceaaa498SBarry 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. 928fde5950dSBarry Smith . -snes_monitor [ascii][:filename][:viewer format] - prints residual norm at each iteration. if no filename given prints to stdout 929fde5950dSBarry Smith . -snes_monitor_solution [ascii binary draw][:filename][:viewer format] - plots solution at each iteration 930fde5950dSBarry Smith . -snes_monitor_residual [ascii binary draw][:filename][:viewer format] - plots residual (not its norm) at each iteration 931fde5950dSBarry Smith . -snes_monitor_solution_update [ascii binary draw][:filename][:viewer format] - plots update to solution at each iteration 9324619e776SBarry Smith . -snes_monitor_lg_residualnorm - plots residual norm at each iteration 933459f5d12SBarry Smith . -snes_monitor_lg_range - plots residual norm at each iteration 9345e7c47f3SMatthew G. Knepley . -snes_monitor_pause_final - Pauses all monitor drawing after the solver ends 935e24b481bSBarry Smith . -snes_fd - use finite differences to compute Jacobian; very slow, only for testing 936e2e60de9SPeter Brune . -snes_fd_color - use finite differences with coloring to compute Jacobian 937ceaaa498SBarry Smith . -snes_mf_ksp_monitor - if using matrix-free multiply then print h at each `KSP` iteration 938b5badacbSBarry Smith . -snes_converged_reason - print the reason for convergence/divergence after each solve 939ceaaa498SBarry Smith . -npc_snes_type <type> - the `SNES` type to use as a nonlinear preconditioner 940e62ac41dSBarry 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. 941e62ac41dSBarry 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. 94282738288SBarry Smith 943f6dfbefdSBarry Smith Options Database Keys for Eisenstat-Walker method: 944fa9f3622SBarry Smith + -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence 9454b27c08aSLois Curfman McInnes . -snes_ksp_ew_version ver - version of Eisenstat-Walker method 94636851e7fSLois Curfman McInnes . -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0 94736851e7fSLois Curfman McInnes . -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax 94836851e7fSLois Curfman McInnes . -snes_ksp_ew_gamma <gamma> - Sets gamma 94936851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha <alpha> - Sets alpha 95036851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2 95136851e7fSLois Curfman McInnes - -snes_ksp_ew_threshold <threshold> - Sets threshold 95282738288SBarry Smith 953dc4c0fb0SBarry Smith Level: beginner 954dc4c0fb0SBarry Smith 95511ca99fdSLois Curfman McInnes Notes: 956ec5066bdSBarry Smith To see all options, run your program with the -help option or consult the users manual 957ec5066bdSBarry Smith 958420bcc1bSBarry Smith `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`, 959420bcc1bSBarry Smith and computing explicitly with 960f6dfbefdSBarry Smith finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object. 96183e2fdc7SBarry Smith 962420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESType`, `SNESSetOptionsPrefix()`, `SNESResetFromOptions()`, `SNES`, `SNESCreate()`, `MatCreateSNESMF()`, `MatFDColoring` 9639b94acceSBarry Smith @*/ 964d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFromOptions(SNES snes) 965d71ae5a4SJacob Faibussowitsch { 9668afaa268SBarry Smith PetscBool flg, pcset, persist, set; 967d8f46077SPeter Brune PetscInt i, indx, lag, grids; 96804d7464bSBarry Smith const char *deft = SNESNEWTONLS; 969649ef022SMatthew Knepley const char *convtests[] = {"default", "skip", "correct_pressure"}; 97085385478SLisandro Dalcin SNESKSPEW *kctx = NULL; 9710f0abf79SStefano Zampini char type[256], monfilename[PETSC_MAX_PATH_LEN], ewprefix[256]; 972c40d0f55SPeter Brune PCSide pcside; 973a64e098fSPeter Brune const char *optionsprefix; 9749b94acceSBarry Smith 9753a40ed3dSBarry Smith PetscFunctionBegin; 9760700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 9779566063dSJacob Faibussowitsch PetscCall(SNESRegisterAll()); 978d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)snes); 979639ff905SBarry Smith if (((PetscObject)snes)->type_name) deft = ((PetscObject)snes)->type_name; 9809566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-snes_type", "Nonlinear solver method", "SNESSetType", SNESList, deft, type, 256, &flg)); 981d64ed03dSBarry Smith if (flg) { 9829566063dSJacob Faibussowitsch PetscCall(SNESSetType(snes, type)); 9837adad957SLisandro Dalcin } else if (!((PetscObject)snes)->type_name) { 9849566063dSJacob Faibussowitsch PetscCall(SNESSetType(snes, deft)); 985d64ed03dSBarry Smith } 9869566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-snes_stol", "Stop if step length less than", "SNESSetTolerances", snes->stol, &snes->stol, NULL)); 9879566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-snes_atol", "Stop if function norm less than", "SNESSetTolerances", snes->abstol, &snes->abstol, NULL)); 988186905e3SBarry Smith 9899566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-snes_rtol", "Stop if decrease in function norm less than", "SNESSetTolerances", snes->rtol, &snes->rtol, NULL)); 9909566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-snes_divergence_tolerance", "Stop if residual norm increases by this factor", "SNESSetDivergenceTolerance", snes->divtol, &snes->divtol, NULL)); 9919566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_max_it", "Maximum iterations", "SNESSetTolerances", snes->max_its, &snes->max_its, NULL)); 9929566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_max_funcs", "Maximum function evaluations", "SNESSetTolerances", snes->max_funcs, &snes->max_funcs, NULL)); 9939566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_max_fail", "Maximum nonlinear step failures", "SNESSetMaxNonlinearStepFailures", snes->maxFailures, &snes->maxFailures, NULL)); 9949566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_max_linear_solve_fail", "Maximum failures in linear solves allowed", "SNESSetMaxLinearSolveFailures", snes->maxLinearSolveFailures, &snes->maxLinearSolveFailures, NULL)); 9959566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_error_if_not_converged", "Generate error if solver does not converge", "SNESSetErrorIfNotConverged", snes->errorifnotconverged, &snes->errorifnotconverged, NULL)); 9969566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_force_iteration", "Force SNESSolve() to take at least one iteration", "SNESSetForceIteration", snes->forceiteration, &snes->forceiteration, NULL)); 9979566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_check_jacobian_domain_error", "Check Jacobian domain error after Jacobian evaluation", "SNESCheckJacobianDomainError", snes->checkjacdomainerror, &snes->checkjacdomainerror, NULL)); 99885385478SLisandro Dalcin 9999566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_lag_preconditioner", "How often to rebuild preconditioner", "SNESSetLagPreconditioner", snes->lagpreconditioner, &lag, &flg)); 1000a8054027SBarry Smith if (flg) { 10015f80ce2aSJacob 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"); 10029566063dSJacob Faibussowitsch PetscCall(SNESSetLagPreconditioner(snes, lag)); 1003a8054027SBarry Smith } 10049566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_lag_preconditioner_persists", "Preconditioner lagging through multiple SNES solves", "SNESSetLagPreconditionerPersists", snes->lagjac_persist, &persist, &flg)); 10051baa6e33SBarry Smith if (flg) PetscCall(SNESSetLagPreconditionerPersists(snes, persist)); 10069566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_lag_jacobian", "How often to rebuild Jacobian", "SNESSetLagJacobian", snes->lagjacobian, &lag, &flg)); 1007e35cf81dSBarry Smith if (flg) { 10085f80ce2aSJacob 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"); 10099566063dSJacob Faibussowitsch PetscCall(SNESSetLagJacobian(snes, lag)); 1010e35cf81dSBarry Smith } 10119566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_lag_jacobian_persists", "Jacobian lagging through multiple SNES solves", "SNESSetLagJacobianPersists", snes->lagjac_persist, &persist, &flg)); 10121baa6e33SBarry Smith if (flg) PetscCall(SNESSetLagJacobianPersists(snes, persist)); 101337ec4e1aSPeter Brune 10149566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_grid_sequence", "Use grid sequencing to generate initial guess", "SNESSetGridSequence", snes->gridsequence, &grids, &flg)); 10151baa6e33SBarry Smith if (flg) PetscCall(SNESSetGridSequence(snes, grids)); 1016a8054027SBarry Smith 1017400f6f02SBarry Smith PetscCall(PetscOptionsEList("-snes_convergence_test", "Convergence test", "SNESSetConvergenceTest", convtests, PETSC_STATIC_ARRAY_LENGTH(convtests), "default", &indx, &flg)); 101885385478SLisandro Dalcin if (flg) { 101985385478SLisandro Dalcin switch (indx) { 1020d71ae5a4SJacob Faibussowitsch case 0: 1021d71ae5a4SJacob Faibussowitsch PetscCall(SNESSetConvergenceTest(snes, SNESConvergedDefault, NULL, NULL)); 1022d71ae5a4SJacob Faibussowitsch break; 1023d71ae5a4SJacob Faibussowitsch case 1: 1024d71ae5a4SJacob Faibussowitsch PetscCall(SNESSetConvergenceTest(snes, SNESConvergedSkip, NULL, NULL)); 1025d71ae5a4SJacob Faibussowitsch break; 1026d71ae5a4SJacob Faibussowitsch case 2: 1027d71ae5a4SJacob Faibussowitsch PetscCall(SNESSetConvergenceTest(snes, SNESConvergedCorrectPressure, NULL, NULL)); 1028d71ae5a4SJacob Faibussowitsch break; 102985385478SLisandro Dalcin } 103085385478SLisandro Dalcin } 103185385478SLisandro Dalcin 10329566063dSJacob Faibussowitsch PetscCall(PetscOptionsEList("-snes_norm_schedule", "SNES Norm schedule", "SNESSetNormSchedule", SNESNormSchedules, 5, "function", &indx, &flg)); 10339566063dSJacob Faibussowitsch if (flg) PetscCall(SNESSetNormSchedule(snes, (SNESNormSchedule)indx)); 1034fdacfa88SPeter Brune 10359566063dSJacob Faibussowitsch PetscCall(PetscOptionsEList("-snes_function_type", "SNES Norm schedule", "SNESSetFunctionType", SNESFunctionTypes, 2, "unpreconditioned", &indx, &flg)); 10369566063dSJacob Faibussowitsch if (flg) PetscCall(SNESSetFunctionType(snes, (SNESFunctionType)indx)); 1037186905e3SBarry Smith 103885385478SLisandro Dalcin kctx = (SNESKSPEW *)snes->kspconvctx; 103985385478SLisandro Dalcin 10409566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_ksp_ew", "Use Eisentat-Walker linear system convergence test", "SNESKSPSetUseEW", snes->ksp_ewconv, &snes->ksp_ewconv, NULL)); 1041186905e3SBarry Smith 10420f0abf79SStefano Zampini PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 10430f0abf79SStefano Zampini PetscCall(PetscSNPrintf(ewprefix, sizeof(ewprefix), "%s%s", optionsprefix ? optionsprefix : "", "snes_")); 1044a4598233SStefano Zampini PetscCall(SNESEWSetFromOptions_Private(kctx, PETSC_TRUE, PetscObjectComm((PetscObject)snes), ewprefix)); 1045186905e3SBarry Smith 104690d69ab7SBarry Smith flg = PETSC_FALSE; 10479566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_monitor_cancel", "Remove all monitors", "SNESMonitorCancel", flg, &flg, &set)); 10489566063dSJacob Faibussowitsch if (set && flg) PetscCall(SNESMonitorCancel(snes)); 1049eabae89aSBarry Smith 10509566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor", "Monitor norm of function", "SNESMonitorDefault", SNESMonitorDefault, SNESMonitorDefaultSetUp)); 10519566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_short", "Monitor norm of function with fewer digits", "SNESMonitorDefaultShort", SNESMonitorDefaultShort, NULL)); 10529566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_range", "Monitor range of elements of function", "SNESMonitorRange", SNESMonitorRange, NULL)); 1053eabae89aSBarry Smith 10549566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_ratio", "Monitor ratios of the norm of function for consecutive steps", "SNESMonitorRatio", SNESMonitorRatio, SNESMonitorRatioSetUp)); 10559566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_field", "Monitor norm of function (split into fields)", "SNESMonitorDefaultField", SNESMonitorDefaultField, NULL)); 10569566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution", "View solution at each iteration", "SNESMonitorSolution", SNESMonitorSolution, NULL)); 10579566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution_update", "View correction at each iteration", "SNESMonitorSolutionUpdate", SNESMonitorSolutionUpdate, NULL)); 10589566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_residual", "View residual at each iteration", "SNESMonitorResidual", SNESMonitorResidual, NULL)); 10599566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_jacupdate_spectrum", "Print the change in the spectrum of the Jacobian", "SNESMonitorJacUpdateSpectrum", SNESMonitorJacUpdateSpectrum, NULL)); 10609566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_fields", "Monitor norm of function per field", "SNESMonitorSet", SNESMonitorFields, NULL)); 10619566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_monitor_pause_final", "Pauses all draw monitors at the final iterate", "SNESMonitorPauseFinal_Internal", PETSC_FALSE, &snes->pauseFinal, NULL)); 10622db13446SMatthew G. Knepley 10639566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-snes_monitor_python", "Use Python function", "SNESMonitorSet", NULL, monfilename, sizeof(monfilename), &flg)); 10649566063dSJacob Faibussowitsch if (flg) PetscCall(PetscPythonMonitorSet((PetscObject)snes, monfilename)); 10655180491cSLisandro Dalcin 106690d69ab7SBarry Smith flg = PETSC_FALSE; 10679566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_monitor_lg_range", "Plot function range at each iteration", "SNESMonitorLGRange", flg, &flg, NULL)); 1068459f5d12SBarry Smith if (flg) { 1069459f5d12SBarry Smith PetscViewer ctx; 1070e24b481bSBarry Smith 10719566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &ctx)); 10729566063dSJacob Faibussowitsch PetscCall(SNESMonitorSet(snes, SNESMonitorLGRange, ctx, (PetscErrorCode(*)(void **))PetscViewerDestroy)); 1073459f5d12SBarry Smith } 10742e7541e6SPeter Brune 107590d69ab7SBarry Smith flg = PETSC_FALSE; 10769566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_converged_reason_view_cancel", "Remove all converged reason viewers", "SNESConvergedReasonViewCancel", flg, &flg, &set)); 10779566063dSJacob Faibussowitsch if (set && flg) PetscCall(SNESConvergedReasonViewCancel(snes)); 1078c4421ceaSFande Kong 1079c4421ceaSFande Kong flg = PETSC_FALSE; 10809566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_fd", "Use finite differences (slow) to compute Jacobian", "SNESComputeJacobianDefault", flg, &flg, NULL)); 10814b27c08aSLois Curfman McInnes if (flg) { 10826cab3a1bSJed Brown void *functx; 1083b1f624c7SBarry Smith DM dm; 10849566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 1085800f99ffSJeremy L Thompson PetscCall(DMSNESUnsetJacobianContext_Internal(dm)); 10869566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, NULL, &functx)); 10879566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefault, functx)); 10889566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Setting default finite difference Jacobian matrix\n")); 10899b94acceSBarry Smith } 1090639f9d9dSBarry Smith 109144848bc4SPeter Brune flg = PETSC_FALSE; 10929566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_fd_function", "Use finite differences (slow) to compute function from user objective", "SNESObjectiveComputeFunctionDefaultFD", flg, &flg, NULL)); 10931baa6e33SBarry Smith if (flg) PetscCall(SNESSetFunction(snes, NULL, SNESObjectiveComputeFunctionDefaultFD, NULL)); 109497584545SPeter Brune 109597584545SPeter Brune flg = PETSC_FALSE; 10969566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_fd_color", "Use finite differences with coloring to compute Jacobian", "SNESComputeJacobianDefaultColor", flg, &flg, NULL)); 109744848bc4SPeter Brune if (flg) { 1098c52e227fSPeter Brune DM dm; 10999566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 1100800f99ffSJeremy L Thompson PetscCall(DMSNESUnsetJacobianContext_Internal(dm)); 11019566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefaultColor, NULL)); 11029566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Setting default finite difference coloring Jacobian matrix\n")); 110344848bc4SPeter Brune } 110444848bc4SPeter Brune 1105aa3661deSLisandro Dalcin flg = PETSC_FALSE; 11069566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_mf_operator", "Use a Matrix-Free Jacobian with user-provided preconditioner matrix", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf_operator, &flg)); 1107d8f46077SPeter Brune if (flg && snes->mf_operator) { 1108a8248277SBarry Smith snes->mf_operator = PETSC_TRUE; 1109d8f46077SPeter Brune snes->mf = PETSC_TRUE; 1110a8248277SBarry Smith } 1111aa3661deSLisandro Dalcin flg = PETSC_FALSE; 11129566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_mf", "Use a Matrix-Free Jacobian with no preconditioner matrix", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf, &flg)); 1113d8f46077SPeter Brune if (!flg && snes->mf_operator) snes->mf = PETSC_TRUE; 11149566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_mf_version", "Matrix-Free routines version 1 or 2", "None", snes->mf_version, &snes->mf_version, NULL)); 1115d28543b3SPeter Brune 1116c40d0f55SPeter Brune flg = PETSC_FALSE; 11179566063dSJacob Faibussowitsch PetscCall(SNESGetNPCSide(snes, &pcside)); 11189566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-snes_npc_side", "SNES nonlinear preconditioner side", "SNESSetNPCSide", PCSides, (PetscEnum)pcside, (PetscEnum *)&pcside, &flg)); 11199566063dSJacob Faibussowitsch if (flg) PetscCall(SNESSetNPCSide(snes, pcside)); 1120c40d0f55SPeter Brune 1121e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS) 11228a70d858SHong Zhang /* 11238a70d858SHong Zhang Publish convergence information using SAWs 11248a70d858SHong Zhang */ 11258a70d858SHong Zhang flg = PETSC_FALSE; 11269566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_monitor_saws", "Publish SNES progress using SAWs", "SNESMonitorSet", flg, &flg, NULL)); 11278a70d858SHong Zhang if (flg) { 11288a70d858SHong Zhang void *ctx; 11299566063dSJacob Faibussowitsch PetscCall(SNESMonitorSAWsCreate(snes, &ctx)); 11309566063dSJacob Faibussowitsch PetscCall(SNESMonitorSet(snes, SNESMonitorSAWs, ctx, SNESMonitorSAWsDestroy)); 11318a70d858SHong Zhang } 11328a70d858SHong Zhang #endif 11338a70d858SHong Zhang #if defined(PETSC_HAVE_SAWS) 1134b90c6cbeSBarry Smith { 1135b90c6cbeSBarry Smith PetscBool set; 1136b90c6cbeSBarry Smith flg = PETSC_FALSE; 11379566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_saws_block", "Block for SAWs at end of SNESSolve", "PetscObjectSAWsBlock", ((PetscObject)snes)->amspublishblock, &flg, &set)); 11381baa6e33SBarry Smith if (set) PetscCall(PetscObjectSAWsSetBlock((PetscObject)snes, flg)); 1139b90c6cbeSBarry Smith } 1140b90c6cbeSBarry Smith #endif 1141b90c6cbeSBarry Smith 114248a46eb9SPierre Jolivet for (i = 0; i < numberofsetfromoptions; i++) PetscCall((*othersetfromoptions[i])(snes)); 114376b2cf59SMatthew Knepley 1144dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, setfromoptions, PetscOptionsObject); 11455d973c19SBarry Smith 11465d973c19SBarry Smith /* process any options handlers added with PetscObjectAddOptionsHandler() */ 1147dbbe0bcdSBarry Smith PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)snes, PetscOptionsObject)); 1148d0609cedSBarry Smith PetscOptionsEnd(); 11494bbc92c1SBarry Smith 1150d8d34be6SBarry Smith if (snes->linesearch) { 11519566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 11529566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetFromOptions(snes->linesearch)); 1153d8d34be6SBarry Smith } 11549e764e56SPeter Brune 11556aa5e7e9SBarry Smith if (snes->usesksp) { 11569566063dSJacob Faibussowitsch if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 11579566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(snes->ksp, snes->jacobian, snes->jacobian_pre)); 11589566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(snes->ksp)); 11596aa5e7e9SBarry Smith } 11606991f827SBarry Smith 1161b5badacbSBarry Smith /* if user has set the SNES NPC type via options database, create it. */ 11629566063dSJacob Faibussowitsch PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 11639566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)snes)->options, optionsprefix, "-npc_snes_type", &pcset)); 116448a46eb9SPierre Jolivet if (pcset && (!snes->npc)) PetscCall(SNESGetNPC(snes, &snes->npc)); 11651baa6e33SBarry Smith if (snes->npc) PetscCall(SNESSetFromOptions(snes->npc)); 1166b3cd9a81SMatthew G. Knepley snes->setfromoptionscalled++; 11673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1168b3cd9a81SMatthew G. Knepley } 1169b3cd9a81SMatthew G. Knepley 1170b3cd9a81SMatthew G. Knepley /*@ 1171420bcc1bSBarry Smith SNESResetFromOptions - Sets various `SNES` and `KSP` parameters from user options ONLY if the `SNESSetFromOptions()` was previously called 1172b3cd9a81SMatthew G. Knepley 1173c3339decSBarry Smith Collective 1174b3cd9a81SMatthew G. Knepley 1175b3cd9a81SMatthew G. Knepley Input Parameter: 1176f6dfbefdSBarry Smith . snes - the `SNES` context 1177b3cd9a81SMatthew G. Knepley 1178420bcc1bSBarry Smith Level: advanced 1179b3cd9a81SMatthew G. Knepley 11801cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESSetOptionsPrefix()` 1181b3cd9a81SMatthew G. Knepley @*/ 1182d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESResetFromOptions(SNES snes) 1183d71ae5a4SJacob Faibussowitsch { 1184b3cd9a81SMatthew G. Knepley PetscFunctionBegin; 11859566063dSJacob Faibussowitsch if (snes->setfromoptionscalled) PetscCall(SNESSetFromOptions(snes)); 11863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11879b94acceSBarry Smith } 11889b94acceSBarry Smith 1189bb9467b5SJed Brown /*@C 1190d25893d9SBarry Smith SNESSetComputeApplicationContext - Sets an optional function to compute a user-defined context for 1191d25893d9SBarry Smith the nonlinear solvers. 1192d25893d9SBarry Smith 1193dc4c0fb0SBarry Smith Logically Collective; No Fortran Support 1194d25893d9SBarry Smith 1195d25893d9SBarry Smith Input Parameters: 1196f6dfbefdSBarry Smith + snes - the `SNES` context 1197d25893d9SBarry Smith . compute - function to compute the context 1198d25893d9SBarry Smith - destroy - function to destroy the context 1199d25893d9SBarry Smith 1200420bcc1bSBarry Smith Calling sequence of `compute`: 1201420bcc1bSBarry Smith + snes - the `SNES` context 1202420bcc1bSBarry Smith - ctx - context to be computed 1203420bcc1bSBarry Smith 1204420bcc1bSBarry Smith Calling sequence of `destroy`: 1205420bcc1bSBarry Smith . ctx - context to be computed by `compute()` 1206420bcc1bSBarry Smith 1207d25893d9SBarry Smith Level: intermediate 1208d25893d9SBarry Smith 1209f6dfbefdSBarry Smith Note: 1210f6dfbefdSBarry Smith This routine is useful if you are performing grid sequencing or using `SNESFAS` and need the appropriate context generated for each level. 1211f6dfbefdSBarry Smith 1212f6dfbefdSBarry Smith Use `SNESSetApplicationContext()` to see the context immediately 1213f6dfbefdSBarry Smith 121442747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNESGetApplicationContext()`, `SNESSetApplicationContext()` 1215d25893d9SBarry Smith @*/ 1216420bcc1bSBarry Smith PetscErrorCode SNESSetComputeApplicationContext(SNES snes, PetscErrorCode (*compute)(SNES snes, void **ctx), PetscErrorCode (*destroy)(void **ctx)) 1217d71ae5a4SJacob Faibussowitsch { 1218d25893d9SBarry Smith PetscFunctionBegin; 1219d25893d9SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1220d25893d9SBarry Smith snes->ops->usercompute = compute; 1221d25893d9SBarry Smith snes->ops->userdestroy = destroy; 12223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1223d25893d9SBarry Smith } 1224a847f771SSatish Balay 1225b07ff414SBarry Smith /*@ 1226f6dfbefdSBarry Smith SNESSetApplicationContext - Sets the optional user-defined context for the nonlinear solvers. 12279b94acceSBarry Smith 1228c3339decSBarry Smith Logically Collective 1229fee21e36SBarry Smith 1230c7afd0dbSLois Curfman McInnes Input Parameters: 1231f6dfbefdSBarry Smith + snes - the `SNES` context 1232c7afd0dbSLois Curfman McInnes - usrP - optional user context 1233c7afd0dbSLois Curfman McInnes 123436851e7fSLois Curfman McInnes Level: intermediate 123536851e7fSLois Curfman McInnes 1236f6dfbefdSBarry Smith Notes: 1237f6dfbefdSBarry Smith Users can provide a context when constructing the `SNES` options and then access it inside their function, Jacobian, or other evaluation function 1238f6dfbefdSBarry Smith with `SNESGetApplicationContext()` 1239f6dfbefdSBarry Smith 1240f6dfbefdSBarry Smith To provide a function that computes the context for you use `SNESSetComputeApplicationContext()` 1241f6dfbefdSBarry Smith 1242420bcc1bSBarry Smith Fortran Note: 1243dc4c0fb0SBarry Smith You must write a Fortran interface definition for this 1244420bcc1bSBarry Smith function that tells Fortran the Fortran derived data type that you are passing in as the `usrP` argument. 1245daf670e6SBarry Smith 12461cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetComputeApplicationContext()`, `SNESGetApplicationContext()` 12479b94acceSBarry Smith @*/ 1248d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetApplicationContext(SNES snes, void *usrP) 1249d71ae5a4SJacob Faibussowitsch { 1250b07ff414SBarry Smith KSP ksp; 12511b2093e4SBarry Smith 12523a40ed3dSBarry Smith PetscFunctionBegin; 12530700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 12549566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 12559566063dSJacob Faibussowitsch PetscCall(KSPSetApplicationContext(ksp, usrP)); 12569b94acceSBarry Smith snes->user = usrP; 12573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12589b94acceSBarry Smith } 125974679c65SBarry Smith 1260b07ff414SBarry Smith /*@ 12619b94acceSBarry Smith SNESGetApplicationContext - Gets the user-defined context for the 1262420bcc1bSBarry Smith nonlinear solvers set with `SNESGetApplicationContext()` or `SNESSetComputeApplicationContext()` 12639b94acceSBarry Smith 1264c7afd0dbSLois Curfman McInnes Not Collective 1265c7afd0dbSLois Curfman McInnes 12669b94acceSBarry Smith Input Parameter: 1267f6dfbefdSBarry Smith . snes - `SNES` context 12689b94acceSBarry Smith 12699b94acceSBarry Smith Output Parameter: 12709b94acceSBarry Smith . usrP - user context 12719b94acceSBarry Smith 127236851e7fSLois Curfman McInnes Level: intermediate 127336851e7fSLois Curfman McInnes 1274420bcc1bSBarry Smith Fortran Note: 1275dc4c0fb0SBarry Smith You must write a Fortran interface definition for this 1276420bcc1bSBarry Smith function that tells Fortran the Fortran derived data type that you are passing in as the `usrP` argument. 1277dc4c0fb0SBarry Smith 1278420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESSetApplicationContext()`, `SNESSetComputeApplicationContext()` 12799b94acceSBarry Smith @*/ 1280d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetApplicationContext(SNES snes, void *usrP) 1281d71ae5a4SJacob Faibussowitsch { 12823a40ed3dSBarry Smith PetscFunctionBegin; 12830700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1284e71120c6SJed Brown *(void **)usrP = snes->user; 12853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12869b94acceSBarry Smith } 128774679c65SBarry Smith 12889b94acceSBarry Smith /*@ 1289420bcc1bSBarry Smith SNESSetUseMatrixFree - indicates that `SNES` should use matrix-free finite difference matrix-vector products to apply the Jacobian. 12903565c898SBarry Smith 1291dc4c0fb0SBarry Smith Logically Collective 12923565c898SBarry Smith 12933565c898SBarry Smith Input Parameters: 1294f6dfbefdSBarry Smith + snes - `SNES` context 1295f6dfbefdSBarry Smith . mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used 1296f6dfbefdSBarry 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 1297420bcc1bSBarry Smith this option no matrix-element based preconditioners can be used in the linear solve since the matrix won't be explicitly available 12983565c898SBarry Smith 1299f6dfbefdSBarry Smith Options Database Keys: 130001c1178eSBarry Smith + -snes_mf_operator - use matrix-free only for the mat operator 1301f6dfbefdSBarry Smith . -snes_mf - use matrix-free for both the mat and pmat operator 1302ec5066bdSBarry Smith . -snes_fd_color - compute the Jacobian via coloring and finite differences. 1303ec5066bdSBarry Smith - -snes_fd - compute the Jacobian via finite differences (slow) 13043565c898SBarry Smith 13053565c898SBarry Smith Level: intermediate 13063565c898SBarry Smith 1307f6dfbefdSBarry Smith Note: 1308420bcc1bSBarry Smith `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`, 1309420bcc1bSBarry Smith and computing explicitly with 1310f6dfbefdSBarry Smith finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object. 1311ec5066bdSBarry Smith 1312420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetUseMatrixFree()`, `MatCreateSNESMF()`, `SNESComputeJacobianDefaultColor()`, `MatFDColoring` 13133565c898SBarry Smith @*/ 1314d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUseMatrixFree(SNES snes, PetscBool mf_operator, PetscBool mf) 1315d71ae5a4SJacob Faibussowitsch { 13163565c898SBarry Smith PetscFunctionBegin; 13173565c898SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 131888b4c220SStefano Zampini PetscValidLogicalCollectiveBool(snes, mf_operator, 2); 131988b4c220SStefano Zampini PetscValidLogicalCollectiveBool(snes, mf, 3); 13204ddffce6SLisandro Dalcin snes->mf = mf_operator ? PETSC_TRUE : mf; 13213565c898SBarry Smith snes->mf_operator = mf_operator; 13223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13233565c898SBarry Smith } 13243565c898SBarry Smith 13253565c898SBarry Smith /*@ 1326dc4c0fb0SBarry Smith SNESGetUseMatrixFree - indicates if the `SNES` uses matrix-free finite difference matrix vector products to apply the Jacobian. 13273565c898SBarry Smith 1328420bcc1bSBarry Smith Not Collective, but the resulting flags will be the same on all MPI processes 13293565c898SBarry Smith 13303565c898SBarry Smith Input Parameter: 1331f6dfbefdSBarry Smith . snes - `SNES` context 13323565c898SBarry Smith 13333565c898SBarry Smith Output Parameters: 1334f6dfbefdSBarry Smith + mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used 1335f6dfbefdSBarry 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 13363565c898SBarry Smith 13373565c898SBarry Smith Level: intermediate 13383565c898SBarry Smith 13391cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUseMatrixFree()`, `MatCreateSNESMF()` 13403565c898SBarry Smith @*/ 1341d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUseMatrixFree(SNES snes, PetscBool *mf_operator, PetscBool *mf) 1342d71ae5a4SJacob Faibussowitsch { 13433565c898SBarry Smith PetscFunctionBegin; 13443565c898SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 13453565c898SBarry Smith if (mf) *mf = snes->mf; 13463565c898SBarry Smith if (mf_operator) *mf_operator = snes->mf_operator; 13473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13483565c898SBarry Smith } 13493565c898SBarry Smith 13503565c898SBarry Smith /*@ 1351420bcc1bSBarry Smith SNESGetIterationNumber - Gets the number of nonlinear iterations completed in the current or most recent `SNESSolve()` 13529b94acceSBarry Smith 1353c7afd0dbSLois Curfman McInnes Not Collective 1354c7afd0dbSLois Curfman McInnes 13559b94acceSBarry Smith Input Parameter: 1356f6dfbefdSBarry Smith . snes - `SNES` context 13579b94acceSBarry Smith 13589b94acceSBarry Smith Output Parameter: 13599b94acceSBarry Smith . iter - iteration number 13609b94acceSBarry Smith 1361dc4c0fb0SBarry Smith Level: intermediate 1362dc4c0fb0SBarry Smith 1363c8228a4eSBarry Smith Notes: 1364c8228a4eSBarry Smith For example, during the computation of iteration 2 this would return 1. 1365c8228a4eSBarry Smith 1366c8228a4eSBarry Smith This is useful for using lagged Jacobians (where one does not recompute the 1367f6dfbefdSBarry Smith Jacobian at each `SNES` iteration). For example, the code 136808405cd6SLois Curfman McInnes .vb 136908405cd6SLois Curfman McInnes ierr = SNESGetIterationNumber(snes,&it); 137008405cd6SLois Curfman McInnes if (!(it % 2)) { 137108405cd6SLois Curfman McInnes [compute Jacobian here] 137208405cd6SLois Curfman McInnes } 137308405cd6SLois Curfman McInnes .ve 1374f6dfbefdSBarry Smith can be used in your function that computes the Jacobian to cause the Jacobian to be 1375f6dfbefdSBarry Smith recomputed every second `SNES` iteration. See also `SNESSetLagJacobian()` 1376c8228a4eSBarry Smith 1377f6dfbefdSBarry Smith After the `SNES` solve is complete this will return the number of nonlinear iterations used. 1378c04deec6SBarry Smith 1379420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetLagJacobian()`, `SNESGetLinearSolveIterations()`, `SNESSetMonitor()` 13809b94acceSBarry Smith @*/ 1381d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetIterationNumber(SNES snes, PetscInt *iter) 1382d71ae5a4SJacob Faibussowitsch { 13833a40ed3dSBarry Smith PetscFunctionBegin; 13840700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 13854f572ea9SToby Isaac PetscAssertPointer(iter, 2); 13869b94acceSBarry Smith *iter = snes->iter; 13873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13889b94acceSBarry Smith } 138974679c65SBarry Smith 1390360c497dSPeter Brune /*@ 1391360c497dSPeter Brune SNESSetIterationNumber - Sets the current iteration number. 1392360c497dSPeter Brune 1393360c497dSPeter Brune Not Collective 1394360c497dSPeter Brune 1395d8d19677SJose E. Roman Input Parameters: 1396f6dfbefdSBarry Smith + snes - `SNES` context 1397a2b725a8SWilliam Gropp - iter - iteration number 1398360c497dSPeter Brune 1399360c497dSPeter Brune Level: developer 1400360c497dSPeter Brune 1401420bcc1bSBarry Smith Note: 1402420bcc1bSBarry Smith This should only be called inside a `SNES` nonlinear solver. 1403420bcc1bSBarry Smith 14041cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetLinearSolveIterations()` 1405360c497dSPeter Brune @*/ 1406d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetIterationNumber(SNES snes, PetscInt iter) 1407d71ae5a4SJacob Faibussowitsch { 1408360c497dSPeter Brune PetscFunctionBegin; 1409360c497dSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 14109566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes)); 1411360c497dSPeter Brune snes->iter = iter; 14129566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes)); 14133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1414360c497dSPeter Brune } 1415360c497dSPeter Brune 14169b94acceSBarry Smith /*@ 1417b850b91aSLisandro Dalcin SNESGetNonlinearStepFailures - Gets the number of unsuccessful steps 1418420bcc1bSBarry Smith attempted by the nonlinear solver in the current or most recent `SNESSolve()` . 14199b94acceSBarry Smith 1420c7afd0dbSLois Curfman McInnes Not Collective 1421c7afd0dbSLois Curfman McInnes 14229b94acceSBarry Smith Input Parameter: 1423f6dfbefdSBarry Smith . snes - `SNES` context 14249b94acceSBarry Smith 14259b94acceSBarry Smith Output Parameter: 14269b94acceSBarry Smith . nfails - number of unsuccessful steps attempted 14279b94acceSBarry Smith 1428dc4c0fb0SBarry Smith Level: intermediate 1429dc4c0fb0SBarry Smith 1430f6dfbefdSBarry Smith Note: 1431f6dfbefdSBarry Smith This counter is reset to zero for each successive call to `SNESSolve()`. 1432c96a6f78SLois Curfman McInnes 14331cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, 1434db781477SPatrick Sanan `SNESSetMaxNonlinearStepFailures()`, `SNESGetMaxNonlinearStepFailures()` 14359b94acceSBarry Smith @*/ 1436d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNonlinearStepFailures(SNES snes, PetscInt *nfails) 1437d71ae5a4SJacob Faibussowitsch { 14383a40ed3dSBarry Smith PetscFunctionBegin; 14390700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 14404f572ea9SToby Isaac PetscAssertPointer(nfails, 2); 144150ffb88aSMatthew Knepley *nfails = snes->numFailures; 14423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 144350ffb88aSMatthew Knepley } 144450ffb88aSMatthew Knepley 144550ffb88aSMatthew Knepley /*@ 1446b850b91aSLisandro Dalcin SNESSetMaxNonlinearStepFailures - Sets the maximum number of unsuccessful steps 1447420bcc1bSBarry Smith attempted by the nonlinear solver before it gives up and returns unconverged or generates an error 144850ffb88aSMatthew Knepley 144950ffb88aSMatthew Knepley Not Collective 145050ffb88aSMatthew Knepley 145150ffb88aSMatthew Knepley Input Parameters: 1452f6dfbefdSBarry Smith + snes - `SNES` context 145350ffb88aSMatthew Knepley - maxFails - maximum of unsuccessful steps 145450ffb88aSMatthew Knepley 1455420bcc1bSBarry Smith Options Database Key: 1456420bcc1bSBarry Smith . -snes_max_fail <n> - maximum number of unsuccessful steps allowed 1457420bcc1bSBarry Smith 145850ffb88aSMatthew Knepley Level: intermediate 145950ffb88aSMatthew Knepley 1460420bcc1bSBarry Smith Developer Note: 1461420bcc1bSBarry Smith The options database key is wrong for this function name 1462420bcc1bSBarry Smith 14631cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, 1464db781477SPatrick Sanan `SNESGetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()` 146550ffb88aSMatthew Knepley @*/ 1466d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxNonlinearStepFailures(SNES snes, PetscInt maxFails) 1467d71ae5a4SJacob Faibussowitsch { 146850ffb88aSMatthew Knepley PetscFunctionBegin; 14690700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 147050ffb88aSMatthew Knepley snes->maxFailures = maxFails; 14713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 147250ffb88aSMatthew Knepley } 147350ffb88aSMatthew Knepley 147450ffb88aSMatthew Knepley /*@ 1475b850b91aSLisandro Dalcin SNESGetMaxNonlinearStepFailures - Gets the maximum number of unsuccessful steps 1476420bcc1bSBarry Smith attempted by the nonlinear solver before it gives up and returns unconverged or generates an error 147750ffb88aSMatthew Knepley 147850ffb88aSMatthew Knepley Not Collective 147950ffb88aSMatthew Knepley 148050ffb88aSMatthew Knepley Input Parameter: 148120f4b53cSBarry Smith . snes - `SNES` context 148250ffb88aSMatthew Knepley 148350ffb88aSMatthew Knepley Output Parameter: 148450ffb88aSMatthew Knepley . maxFails - maximum of unsuccessful steps 148550ffb88aSMatthew Knepley 148650ffb88aSMatthew Knepley Level: intermediate 148750ffb88aSMatthew Knepley 14881cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, 1489db781477SPatrick Sanan `SNESSetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()` 149050ffb88aSMatthew Knepley @*/ 1491d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxNonlinearStepFailures(SNES snes, PetscInt *maxFails) 1492d71ae5a4SJacob Faibussowitsch { 149350ffb88aSMatthew Knepley PetscFunctionBegin; 14940700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 14954f572ea9SToby Isaac PetscAssertPointer(maxFails, 2); 149650ffb88aSMatthew Knepley *maxFails = snes->maxFailures; 14973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14989b94acceSBarry Smith } 1499a847f771SSatish Balay 15002541af92SBarry Smith /*@ 15012541af92SBarry Smith SNESGetNumberFunctionEvals - Gets the number of user provided function evaluations 1502420bcc1bSBarry Smith done by the `SNES` object in the current or most recent `SNESSolve()` 15032541af92SBarry Smith 15042541af92SBarry Smith Not Collective 15052541af92SBarry Smith 15062541af92SBarry Smith Input Parameter: 1507f6dfbefdSBarry Smith . snes - `SNES` context 15082541af92SBarry Smith 15092541af92SBarry Smith Output Parameter: 15102541af92SBarry Smith . nfuncs - number of evaluations 15112541af92SBarry Smith 15122541af92SBarry Smith Level: intermediate 15132541af92SBarry Smith 1514f6dfbefdSBarry Smith Note: 1515f6dfbefdSBarry Smith Reset every time `SNESSolve()` is called unless `SNESSetCountersReset()` is used. 1516971e163fSPeter Brune 15171cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, `SNESSetCountersReset()` 15182541af92SBarry Smith @*/ 1519d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNumberFunctionEvals(SNES snes, PetscInt *nfuncs) 1520d71ae5a4SJacob Faibussowitsch { 15212541af92SBarry Smith PetscFunctionBegin; 15220700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 15234f572ea9SToby Isaac PetscAssertPointer(nfuncs, 2); 15242541af92SBarry Smith *nfuncs = snes->nfuncs; 15253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15262541af92SBarry Smith } 15272541af92SBarry Smith 15283d4c4710SBarry Smith /*@ 15293d4c4710SBarry Smith SNESGetLinearSolveFailures - Gets the number of failed (non-converged) 1530420bcc1bSBarry Smith linear solvers in the current or most recent `SNESSolve()` 15313d4c4710SBarry Smith 15323d4c4710SBarry Smith Not Collective 15333d4c4710SBarry Smith 15343d4c4710SBarry Smith Input Parameter: 1535f6dfbefdSBarry Smith . snes - `SNES` context 15363d4c4710SBarry Smith 15373d4c4710SBarry Smith Output Parameter: 15383d4c4710SBarry Smith . nfails - number of failed solves 15393d4c4710SBarry Smith 1540f6dfbefdSBarry Smith Options Database Key: 15419d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated 15429d85da0cSMatthew G. Knepley 1543f6dfbefdSBarry Smith Level: intermediate 1544f6dfbefdSBarry Smith 1545f6dfbefdSBarry Smith Note: 1546f6dfbefdSBarry Smith This counter is reset to zero for each successive call to `SNESSolve()`. 15473d4c4710SBarry Smith 15481cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()` 15493d4c4710SBarry Smith @*/ 1550d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveFailures(SNES snes, PetscInt *nfails) 1551d71ae5a4SJacob Faibussowitsch { 15523d4c4710SBarry Smith PetscFunctionBegin; 15530700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 15544f572ea9SToby Isaac PetscAssertPointer(nfails, 2); 15553d4c4710SBarry Smith *nfails = snes->numLinearSolveFailures; 15563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15573d4c4710SBarry Smith } 15583d4c4710SBarry Smith 15593d4c4710SBarry Smith /*@ 15603d4c4710SBarry Smith SNESSetMaxLinearSolveFailures - the number of failed linear solve attempts 1561f6dfbefdSBarry Smith allowed before `SNES` returns with a diverged reason of `SNES_DIVERGED_LINEAR_SOLVE` 15623d4c4710SBarry Smith 1563c3339decSBarry Smith Logically Collective 15643d4c4710SBarry Smith 15653d4c4710SBarry Smith Input Parameters: 1566f6dfbefdSBarry Smith + snes - `SNES` context 15673d4c4710SBarry Smith - maxFails - maximum allowed linear solve failures 15683d4c4710SBarry Smith 1569f6dfbefdSBarry Smith Options Database Key: 15709d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated 15719d85da0cSMatthew G. Knepley 1572dc4c0fb0SBarry Smith Level: intermediate 1573dc4c0fb0SBarry Smith 1574f6dfbefdSBarry Smith Note: 1575f6dfbefdSBarry Smith By default this is 0; that is `SNES` returns on the first failed linear solve 15763d4c4710SBarry Smith 1577420bcc1bSBarry Smith Developer Note: 1578420bcc1bSBarry Smith The options database key is wrong for this function name 1579420bcc1bSBarry Smith 15801cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()` 15813d4c4710SBarry Smith @*/ 1582d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxLinearSolveFailures(SNES snes, PetscInt maxFails) 1583d71ae5a4SJacob Faibussowitsch { 15843d4c4710SBarry Smith PetscFunctionBegin; 15850700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1586c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, maxFails, 2); 15873d4c4710SBarry Smith snes->maxLinearSolveFailures = maxFails; 15883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15893d4c4710SBarry Smith } 15903d4c4710SBarry Smith 15913d4c4710SBarry Smith /*@ 15923d4c4710SBarry Smith SNESGetMaxLinearSolveFailures - gets the maximum number of linear solve failures that 1593f6dfbefdSBarry Smith are allowed before `SNES` returns as unsuccessful 15943d4c4710SBarry Smith 15953d4c4710SBarry Smith Not Collective 15963d4c4710SBarry Smith 15973d4c4710SBarry Smith Input Parameter: 1598f6dfbefdSBarry Smith . snes - `SNES` context 15993d4c4710SBarry Smith 16003d4c4710SBarry Smith Output Parameter: 16013d4c4710SBarry Smith . maxFails - maximum of unsuccessful solves allowed 16023d4c4710SBarry Smith 16033d4c4710SBarry Smith Level: intermediate 16043d4c4710SBarry Smith 1605f6dfbefdSBarry Smith Note: 1606f6dfbefdSBarry Smith By default this is 1; that is `SNES` returns on the first failed linear solve 16073d4c4710SBarry Smith 16081cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, 16093d4c4710SBarry Smith @*/ 1610d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxLinearSolveFailures(SNES snes, PetscInt *maxFails) 1611d71ae5a4SJacob Faibussowitsch { 16123d4c4710SBarry Smith PetscFunctionBegin; 16130700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 16144f572ea9SToby Isaac PetscAssertPointer(maxFails, 2); 16153d4c4710SBarry Smith *maxFails = snes->maxLinearSolveFailures; 16163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16173d4c4710SBarry Smith } 16183d4c4710SBarry Smith 1619c96a6f78SLois Curfman McInnes /*@ 1620b850b91aSLisandro Dalcin SNESGetLinearSolveIterations - Gets the total number of linear iterations 1621420bcc1bSBarry Smith used by the nonlinear solver in the most recent `SNESSolve()` 1622c96a6f78SLois Curfman McInnes 1623c7afd0dbSLois Curfman McInnes Not Collective 1624c7afd0dbSLois Curfman McInnes 1625c96a6f78SLois Curfman McInnes Input Parameter: 1626f6dfbefdSBarry Smith . snes - `SNES` context 1627c96a6f78SLois Curfman McInnes 1628c96a6f78SLois Curfman McInnes Output Parameter: 1629c96a6f78SLois Curfman McInnes . lits - number of linear iterations 1630c96a6f78SLois Curfman McInnes 1631dc4c0fb0SBarry Smith Level: intermediate 1632dc4c0fb0SBarry Smith 1633c96a6f78SLois Curfman McInnes Notes: 1634f6dfbefdSBarry Smith This counter is reset to zero for each successive call to `SNESSolve()` unless `SNESSetCountersReset()` is used. 1635c96a6f78SLois Curfman McInnes 1636f6dfbefdSBarry 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 1637f6dfbefdSBarry Smith then call `KSPGetIterationNumber()` after the failed solve. 1638010be392SBarry Smith 16391cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetIterationNumber()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESSetCountersReset()` 1640c96a6f78SLois Curfman McInnes @*/ 1641d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveIterations(SNES snes, PetscInt *lits) 1642d71ae5a4SJacob Faibussowitsch { 16433a40ed3dSBarry Smith PetscFunctionBegin; 16440700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 16454f572ea9SToby Isaac PetscAssertPointer(lits, 2); 1646c96a6f78SLois Curfman McInnes *lits = snes->linear_its; 16473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1648c96a6f78SLois Curfman McInnes } 1649c96a6f78SLois Curfman McInnes 1650971e163fSPeter Brune /*@ 1651971e163fSPeter Brune SNESSetCountersReset - Sets whether or not the counters for linear iterations and function evaluations 1652f6dfbefdSBarry Smith are reset every time `SNESSolve()` is called. 1653971e163fSPeter Brune 1654c3339decSBarry Smith Logically Collective 1655971e163fSPeter Brune 1656d8d19677SJose E. Roman Input Parameters: 1657f6dfbefdSBarry Smith + snes - `SNES` context 1658f6dfbefdSBarry Smith - reset - whether to reset the counters or not, defaults to `PETSC_TRUE` 1659971e163fSPeter Brune 1660971e163fSPeter Brune Level: developer 1661971e163fSPeter Brune 16621cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()` 1663971e163fSPeter Brune @*/ 1664d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCountersReset(SNES snes, PetscBool reset) 1665d71ae5a4SJacob Faibussowitsch { 1666971e163fSPeter Brune PetscFunctionBegin; 1667971e163fSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1668971e163fSPeter Brune PetscValidLogicalCollectiveBool(snes, reset, 2); 1669971e163fSPeter Brune snes->counters_reset = reset; 16703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1671971e163fSPeter Brune } 1672971e163fSPeter Brune 16732999313aSBarry Smith /*@ 1674f6dfbefdSBarry Smith SNESSetKSP - Sets a `KSP` context for the `SNES` object to use 16752999313aSBarry Smith 1676420bcc1bSBarry Smith Not Collective, but the `SNES` and `KSP` objects must live on the same `MPI_Comm` 16772999313aSBarry Smith 16782999313aSBarry Smith Input Parameters: 1679f6dfbefdSBarry Smith + snes - the `SNES` context 1680f6dfbefdSBarry Smith - ksp - the `KSP` context 16812999313aSBarry Smith 1682dc4c0fb0SBarry Smith Level: developer 1683dc4c0fb0SBarry Smith 16842999313aSBarry Smith Notes: 1685f6dfbefdSBarry Smith The `SNES` object already has its `KSP` object, you can obtain with `SNESGetKSP()` 16862999313aSBarry Smith so this routine is rarely needed. 16872999313aSBarry Smith 1688f6dfbefdSBarry Smith The `KSP` object that is already in the `SNES` object has its reference count 1689420bcc1bSBarry Smith decreased by one when this is called. 16902999313aSBarry Smith 169142747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `KSP`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()` 16922999313aSBarry Smith @*/ 1693d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetKSP(SNES snes, KSP ksp) 1694d71ae5a4SJacob Faibussowitsch { 16952999313aSBarry Smith PetscFunctionBegin; 16960700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 16970700a824SBarry Smith PetscValidHeaderSpecific(ksp, KSP_CLASSID, 2); 16982999313aSBarry Smith PetscCheckSameComm(snes, 1, ksp, 2); 16999566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)ksp)); 17009566063dSJacob Faibussowitsch if (snes->ksp) PetscCall(PetscObjectDereference((PetscObject)snes->ksp)); 17012999313aSBarry Smith snes->ksp = ksp; 17023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17032999313aSBarry Smith } 17042999313aSBarry Smith 170552baeb72SSatish Balay /*@ 1706dc4c0fb0SBarry Smith SNESCreate - Creates a nonlinear solver context used to manage a set of nonlinear solves 17079b94acceSBarry Smith 1708d083f849SBarry Smith Collective 1709c7afd0dbSLois Curfman McInnes 1710f6dfbefdSBarry Smith Input Parameter: 1711906ed7ccSBarry Smith . comm - MPI communicator 17129b94acceSBarry Smith 17139b94acceSBarry Smith Output Parameter: 171420f4b53cSBarry Smith . outsnes - the new `SNES` context 17159b94acceSBarry Smith 1716c7afd0dbSLois Curfman McInnes Options Database Keys: 1717dc4c0fb0SBarry Smith + -snes_mf - Activates default matrix-free Jacobian-vector products, and no preconditioning matrix 1718dc4c0fb0SBarry Smith . -snes_mf_operator - Activates default matrix-free Jacobian-vector products, and a user-provided preconditioning matrix 1719dc4c0fb0SBarry Smith as set by `SNESSetJacobian()` 1720dc4c0fb0SBarry Smith . -snes_fd_coloring - uses a relative fast computation of the Jacobian using finite differences and a graph coloring 1721c7afd0dbSLois Curfman McInnes - -snes_fd - Uses (slow!) finite differences to compute Jacobian 1722c1f60f51SBarry Smith 172336851e7fSLois Curfman McInnes Level: beginner 172436851e7fSLois Curfman McInnes 172595452b02SPatrick Sanan Developer Notes: 1726f6dfbefdSBarry Smith `SNES` always creates a `KSP` object even though many `SNES` methods do not use it. This is 1727efd4aadfSBarry Smith unfortunate and should be fixed at some point. The flag snes->usesksp indicates if the 1728f6dfbefdSBarry Smith particular method does use `KSP` and regulates if the information about the `KSP` is printed 1729f6dfbefdSBarry Smith in `SNESView()`. 1730efd4aadfSBarry Smith 1731f6dfbefdSBarry Smith `TSSetFromOptions()` does call `SNESSetFromOptions()` which can lead to users being confused 1732f6dfbefdSBarry Smith by help messages about meaningless `SNES` options. 1733f6dfbefdSBarry Smith 1734dc4c0fb0SBarry Smith `SNES` always creates the snes->kspconvctx even though it is used by only one type. This should be fixed. 1735efd4aadfSBarry Smith 1736e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()` 17379b94acceSBarry Smith @*/ 1738d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESCreate(MPI_Comm comm, SNES *outsnes) 1739d71ae5a4SJacob Faibussowitsch { 17409b94acceSBarry Smith SNES snes; 1741fa9f3622SBarry Smith SNESKSPEW *kctx; 174237fcc0dbSBarry Smith 17433a40ed3dSBarry Smith PetscFunctionBegin; 17444f572ea9SToby Isaac PetscAssertPointer(outsnes, 2); 17450298fd71SBarry Smith *outsnes = NULL; 17469566063dSJacob Faibussowitsch PetscCall(SNESInitializePackage()); 17478ba1e511SMatthew Knepley 17489566063dSJacob Faibussowitsch PetscCall(PetscHeaderCreate(snes, SNES_CLASSID, "SNES", "Nonlinear solver", "SNES", comm, SNESDestroy, SNESView)); 17497adad957SLisandro Dalcin 17508d359177SBarry Smith snes->ops->converged = SNESConvergedDefault; 17512c155ee1SBarry Smith snes->usesksp = PETSC_TRUE; 175288976e71SPeter Brune snes->tolerancesset = PETSC_FALSE; 17539b94acceSBarry Smith snes->max_its = 50; 17549750a799SBarry Smith snes->max_funcs = 10000; 17559b94acceSBarry Smith snes->norm = 0.0; 1756c1e67a49SFande Kong snes->xnorm = 0.0; 1757c1e67a49SFande Kong snes->ynorm = 0.0; 1758365a6726SPeter Brune snes->normschedule = SNES_NORM_ALWAYS; 17596c67d002SPeter Brune snes->functype = SNES_FUNCTION_DEFAULT; 17608ca48ce9SPierre Jolivet snes->rtol = PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8; 1761b4874afaSBarry Smith snes->ttol = 0.0; 17628ca48ce9SPierre Jolivet snes->abstol = PetscDefined(USE_REAL_SINGLE) ? 1.e-25 : 1.e-50; 17638ca48ce9SPierre Jolivet snes->stol = PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8; 17648ca48ce9SPierre Jolivet snes->deltatol = PetscDefined(USE_REAL_SINGLE) ? 1.e-6 : 1.e-12; 1765e37c518bSBarry Smith snes->divtol = 1.e4; 1766e37c518bSBarry Smith snes->rnorm0 = 0; 17679b94acceSBarry Smith snes->nfuncs = 0; 176850ffb88aSMatthew Knepley snes->numFailures = 0; 176950ffb88aSMatthew Knepley snes->maxFailures = 1; 17707a00f4a9SLois Curfman McInnes snes->linear_its = 0; 1771e35cf81dSBarry Smith snes->lagjacobian = 1; 177237ec4e1aSPeter Brune snes->jac_iter = 0; 177337ec4e1aSPeter Brune snes->lagjac_persist = PETSC_FALSE; 1774a8054027SBarry Smith snes->lagpreconditioner = 1; 177537ec4e1aSPeter Brune snes->pre_iter = 0; 177637ec4e1aSPeter Brune snes->lagpre_persist = PETSC_FALSE; 1777639f9d9dSBarry Smith snes->numbermonitors = 0; 1778c4421ceaSFande Kong snes->numberreasonviews = 0; 17799e5d0892SLisandro Dalcin snes->data = NULL; 17804dc4c822SBarry Smith snes->setupcalled = PETSC_FALSE; 1781186905e3SBarry Smith snes->ksp_ewconv = PETSC_FALSE; 17826f24a144SLois Curfman McInnes snes->nwork = 0; 17839e5d0892SLisandro Dalcin snes->work = NULL; 178458c9b817SLisandro Dalcin snes->nvwork = 0; 17859e5d0892SLisandro Dalcin snes->vwork = NULL; 1786758f92a0SBarry Smith snes->conv_hist_len = 0; 1787758f92a0SBarry Smith snes->conv_hist_max = 0; 17880298fd71SBarry Smith snes->conv_hist = NULL; 17890298fd71SBarry Smith snes->conv_hist_its = NULL; 1790758f92a0SBarry Smith snes->conv_hist_reset = PETSC_TRUE; 1791971e163fSPeter Brune snes->counters_reset = PETSC_TRUE; 1792e4ed7901SPeter Brune snes->vec_func_init_set = PETSC_FALSE; 1793184914b5SBarry Smith snes->reason = SNES_CONVERGED_ITERATING; 1794efd4aadfSBarry Smith snes->npcside = PC_RIGHT; 1795b3cd9a81SMatthew G. Knepley snes->setfromoptionscalled = 0; 1796c40d0f55SPeter Brune 1797d8f46077SPeter Brune snes->mf = PETSC_FALSE; 1798d8f46077SPeter Brune snes->mf_operator = PETSC_FALSE; 1799d8f46077SPeter Brune snes->mf_version = 1; 1800d8f46077SPeter Brune 18013d4c4710SBarry Smith snes->numLinearSolveFailures = 0; 18023d4c4710SBarry Smith snes->maxLinearSolveFailures = 1; 18033d4c4710SBarry Smith 1804349187a7SBarry Smith snes->vizerotolerance = 1.e-8; 180576bd3646SJed Brown snes->checkjacdomainerror = PetscDefined(USE_DEBUG) ? PETSC_TRUE : PETSC_FALSE; 1806349187a7SBarry Smith 18074fc747eaSLawrence Mitchell /* Set this to true if the implementation of SNESSolve_XXX does compute the residual at the final solution. */ 18084fc747eaSLawrence Mitchell snes->alwayscomputesfinalresidual = PETSC_FALSE; 18094fc747eaSLawrence Mitchell 18109b94acceSBarry Smith /* Create context to compute Eisenstat-Walker relative tolerance for KSP */ 18114dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&kctx)); 1812f5af7f23SKarl Rupp 18139b94acceSBarry Smith snes->kspconvctx = (void *)kctx; 18149b94acceSBarry Smith kctx->version = 2; 18150f0abf79SStefano Zampini kctx->rtol_0 = 0.3; /* Eisenstat and Walker suggest rtol_0=.5, but 18169b94acceSBarry Smith this was too large for some test cases */ 181775567043SBarry Smith kctx->rtol_last = 0.0; 18180f0abf79SStefano Zampini kctx->rtol_max = 0.9; 18199b94acceSBarry Smith kctx->gamma = 1.0; 18200f0abf79SStefano Zampini kctx->alpha = 0.5 * (1.0 + PetscSqrtReal(5.0)); 182171f87433Sdalcinl kctx->alpha2 = kctx->alpha; 18220f0abf79SStefano Zampini kctx->threshold = 0.1; 182375567043SBarry Smith kctx->lresid_last = 0.0; 182475567043SBarry Smith kctx->norm_last = 0.0; 18259b94acceSBarry Smith 18260f0abf79SStefano Zampini kctx->rk_last = 0.0; 18270f0abf79SStefano Zampini kctx->rk_last_2 = 0.0; 18280f0abf79SStefano Zampini kctx->rtol_last_2 = 0.0; 18290f0abf79SStefano Zampini kctx->v4_p1 = 0.1; 18300f0abf79SStefano Zampini kctx->v4_p2 = 0.4; 18310f0abf79SStefano Zampini kctx->v4_p3 = 0.7; 18320f0abf79SStefano Zampini kctx->v4_m1 = 0.8; 18330f0abf79SStefano Zampini kctx->v4_m2 = 0.5; 18340f0abf79SStefano Zampini kctx->v4_m3 = 0.1; 18350f0abf79SStefano Zampini kctx->v4_m4 = 0.5; 18360f0abf79SStefano Zampini 18379b94acceSBarry Smith *outsnes = snes; 18383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18399b94acceSBarry Smith } 18409b94acceSBarry Smith 18419b94acceSBarry Smith /*@C 18429b94acceSBarry Smith SNESSetFunction - Sets the function evaluation routine and function 1843f6dfbefdSBarry Smith vector for use by the `SNES` routines in solving systems of nonlinear 18449b94acceSBarry Smith equations. 18459b94acceSBarry Smith 1846c3339decSBarry Smith Logically Collective 1847fee21e36SBarry Smith 1848c7afd0dbSLois Curfman McInnes Input Parameters: 1849f6dfbefdSBarry Smith + snes - the `SNES` context 1850dc4c0fb0SBarry Smith . r - vector to store function values, may be `NULL` 18518434afd1SBarry Smith . f - function evaluation routine; for calling sequence see `SNESFunctionFn` 1852c7afd0dbSLois Curfman McInnes - ctx - [optional] user-defined context for private data for the 1853dc4c0fb0SBarry Smith function evaluation routine (may be `NULL`) 18549b94acceSBarry Smith 185536851e7fSLois Curfman McInnes Level: beginner 185636851e7fSLois Curfman McInnes 18578434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetPicard()`, `SNESFunctionFn` 18589b94acceSBarry Smith @*/ 18598434afd1SBarry Smith PetscErrorCode SNESSetFunction(SNES snes, Vec r, SNESFunctionFn *f, void *ctx) 1860d71ae5a4SJacob Faibussowitsch { 18616cab3a1bSJed Brown DM dm; 18626cab3a1bSJed Brown 18633a40ed3dSBarry Smith PetscFunctionBegin; 18640700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1865d2a683ecSLisandro Dalcin if (r) { 1866d2a683ecSLisandro Dalcin PetscValidHeaderSpecific(r, VEC_CLASSID, 2); 1867d2a683ecSLisandro Dalcin PetscCheckSameComm(snes, 1, r, 2); 18689566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)r)); 18699566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_func)); 187085385478SLisandro Dalcin snes->vec_func = r; 1871d2a683ecSLisandro Dalcin } 18729566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 18739566063dSJacob Faibussowitsch PetscCall(DMSNESSetFunction(dm, f, ctx)); 187448a46eb9SPierre Jolivet if (f == SNESPicardComputeFunction) PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx)); 18753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18769b94acceSBarry Smith } 18779b94acceSBarry Smith 1878e4ed7901SPeter Brune /*@C 18790b4db180SJacob Faibussowitsch SNESSetInitialFunction - Set an already computed function evaluation at the initial guess to be reused by `SNESSolve()`. 1880e4ed7901SPeter Brune 1881c3339decSBarry Smith Logically Collective 1882e4ed7901SPeter Brune 1883e4ed7901SPeter Brune Input Parameters: 1884f6dfbefdSBarry Smith + snes - the `SNES` context 1885e4ed7901SPeter Brune - f - vector to store function value 1886e4ed7901SPeter Brune 1887dc4c0fb0SBarry Smith Level: developer 1888dc4c0fb0SBarry Smith 1889e4ed7901SPeter Brune Notes: 1890e4ed7901SPeter Brune This should not be modified during the solution procedure. 1891e4ed7901SPeter Brune 1892f6dfbefdSBarry Smith This is used extensively in the `SNESFAS` hierarchy and in nonlinear preconditioning. 1893e4ed7901SPeter Brune 18941cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetInitialFunctionNorm()` 1895e4ed7901SPeter Brune @*/ 1896d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetInitialFunction(SNES snes, Vec f) 1897d71ae5a4SJacob Faibussowitsch { 1898e4ed7901SPeter Brune Vec vec_func; 1899e4ed7901SPeter Brune 1900e4ed7901SPeter Brune PetscFunctionBegin; 1901e4ed7901SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1902e4ed7901SPeter Brune PetscValidHeaderSpecific(f, VEC_CLASSID, 2); 1903e4ed7901SPeter Brune PetscCheckSameComm(snes, 1, f, 2); 1904efd4aadfSBarry Smith if (snes->npcside == PC_LEFT && snes->functype == SNES_FUNCTION_PRECONDITIONED) { 1905902f982fSPeter Brune snes->vec_func_init_set = PETSC_FALSE; 19063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1907902f982fSPeter Brune } 19089566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &vec_func, NULL, NULL)); 19099566063dSJacob Faibussowitsch PetscCall(VecCopy(f, vec_func)); 1910f5af7f23SKarl Rupp 1911217b9c2eSPeter Brune snes->vec_func_init_set = PETSC_TRUE; 19123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1913e4ed7901SPeter Brune } 1914e4ed7901SPeter Brune 1915534ebe21SPeter Brune /*@ 1916f6dfbefdSBarry Smith SNESSetNormSchedule - Sets the `SNESNormSchedule` used in convergence and monitoring 1917f6dfbefdSBarry Smith of the `SNES` method, when norms are computed in the solving process 1918534ebe21SPeter Brune 1919c3339decSBarry Smith Logically Collective 1920534ebe21SPeter Brune 1921534ebe21SPeter Brune Input Parameters: 1922f6dfbefdSBarry Smith + snes - the `SNES` context 1923365a6726SPeter Brune - normschedule - the frequency of norm computation 1924534ebe21SPeter Brune 1925517f1916SMatthew G. Knepley Options Database Key: 192667b8a455SSatish Balay . -snes_norm_schedule <none, always, initialonly, finalonly, initialfinalonly> - set the schedule 1927517f1916SMatthew G. Knepley 1928dc4c0fb0SBarry Smith Level: advanced 1929dc4c0fb0SBarry Smith 1930534ebe21SPeter Brune Notes: 1931f6dfbefdSBarry Smith Only certain `SNES` methods support certain `SNESNormSchedules`. Most require evaluation 1932534ebe21SPeter Brune of the nonlinear function and the taking of its norm at every iteration to 1933534ebe21SPeter Brune even ensure convergence at all. However, methods such as custom Gauss-Seidel methods 1934f6dfbefdSBarry Smith `SNESNGS` and the like do not require the norm of the function to be computed, and therefore 1935534ebe21SPeter Brune may either be monitored for convergence or not. As these are often used as nonlinear 1936534ebe21SPeter Brune preconditioners, monitoring the norm of their error is not a useful enterprise within 1937534ebe21SPeter Brune their solution. 1938534ebe21SPeter Brune 1939e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNESNormSchedule`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()` 1940534ebe21SPeter Brune @*/ 1941d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNormSchedule(SNES snes, SNESNormSchedule normschedule) 1942d71ae5a4SJacob Faibussowitsch { 1943534ebe21SPeter Brune PetscFunctionBegin; 1944534ebe21SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1945365a6726SPeter Brune snes->normschedule = normschedule; 19463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1947534ebe21SPeter Brune } 1948534ebe21SPeter Brune 1949534ebe21SPeter Brune /*@ 1950f6dfbefdSBarry Smith SNESGetNormSchedule - Gets the `SNESNormSchedule` used in convergence and monitoring 1951f6dfbefdSBarry Smith of the `SNES` method. 1952534ebe21SPeter Brune 1953c3339decSBarry Smith Logically Collective 1954534ebe21SPeter Brune 1955534ebe21SPeter Brune Input Parameters: 1956f6dfbefdSBarry Smith + snes - the `SNES` context 1957365a6726SPeter Brune - normschedule - the type of the norm used 1958534ebe21SPeter Brune 1959534ebe21SPeter Brune Level: advanced 1960534ebe21SPeter Brune 19611cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 1962534ebe21SPeter Brune @*/ 1963d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNormSchedule(SNES snes, SNESNormSchedule *normschedule) 1964d71ae5a4SJacob Faibussowitsch { 1965534ebe21SPeter Brune PetscFunctionBegin; 1966534ebe21SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1967365a6726SPeter Brune *normschedule = snes->normschedule; 19683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1969534ebe21SPeter Brune } 1970534ebe21SPeter Brune 1971c5ce4427SMatthew G. Knepley /*@ 1972c5ce4427SMatthew G. Knepley SNESSetFunctionNorm - Sets the last computed residual norm. 1973c5ce4427SMatthew G. Knepley 1974c3339decSBarry Smith Logically Collective 1975c5ce4427SMatthew G. Knepley 1976c5ce4427SMatthew G. Knepley Input Parameters: 1977f6dfbefdSBarry Smith + snes - the `SNES` context 1978f6dfbefdSBarry Smith - norm - the value of the norm 1979c5ce4427SMatthew G. Knepley 1980c5ce4427SMatthew G. Knepley Level: developer 1981c5ce4427SMatthew G. Knepley 19821cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 1983c5ce4427SMatthew G. Knepley @*/ 1984d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionNorm(SNES snes, PetscReal norm) 1985d71ae5a4SJacob Faibussowitsch { 1986c5ce4427SMatthew G. Knepley PetscFunctionBegin; 1987c5ce4427SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1988c5ce4427SMatthew G. Knepley snes->norm = norm; 19893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1990c5ce4427SMatthew G. Knepley } 1991c5ce4427SMatthew G. Knepley 1992c5ce4427SMatthew G. Knepley /*@ 1993c5ce4427SMatthew G. Knepley SNESGetFunctionNorm - Gets the last computed norm of the residual 1994c5ce4427SMatthew G. Knepley 1995c5ce4427SMatthew G. Knepley Not Collective 1996c5ce4427SMatthew G. Knepley 1997c5ce4427SMatthew G. Knepley Input Parameter: 1998f6dfbefdSBarry Smith . snes - the `SNES` context 1999c5ce4427SMatthew G. Knepley 2000c5ce4427SMatthew G. Knepley Output Parameter: 2001c5ce4427SMatthew G. Knepley . norm - the last computed residual norm 2002c5ce4427SMatthew G. Knepley 2003c5ce4427SMatthew G. Knepley Level: developer 2004c5ce4427SMatthew G. Knepley 20051cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 2006c5ce4427SMatthew G. Knepley @*/ 2007d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionNorm(SNES snes, PetscReal *norm) 2008d71ae5a4SJacob Faibussowitsch { 2009c5ce4427SMatthew G. Knepley PetscFunctionBegin; 2010c5ce4427SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 20114f572ea9SToby Isaac PetscAssertPointer(norm, 2); 2012c5ce4427SMatthew G. Knepley *norm = snes->norm; 20133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2014c5ce4427SMatthew G. Knepley } 2015c5ce4427SMatthew G. Knepley 2016c1e67a49SFande Kong /*@ 2017f6dfbefdSBarry Smith SNESGetUpdateNorm - Gets the last computed norm of the solution update 2018c1e67a49SFande Kong 2019c1e67a49SFande Kong Not Collective 2020c1e67a49SFande Kong 2021c1e67a49SFande Kong Input Parameter: 2022f6dfbefdSBarry Smith . snes - the `SNES` context 2023c1e67a49SFande Kong 2024c1e67a49SFande Kong Output Parameter: 2025c1e67a49SFande Kong . ynorm - the last computed update norm 2026c1e67a49SFande Kong 2027c1e67a49SFande Kong Level: developer 2028c1e67a49SFande Kong 2029f6dfbefdSBarry Smith Note: 2030f6dfbefdSBarry Smith The new solution is the current solution plus the update, so this norm is an indication of the size of the update 2031f6dfbefdSBarry Smith 20321cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()` 2033c1e67a49SFande Kong @*/ 2034d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUpdateNorm(SNES snes, PetscReal *ynorm) 2035d71ae5a4SJacob Faibussowitsch { 2036c1e67a49SFande Kong PetscFunctionBegin; 2037c1e67a49SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 20384f572ea9SToby Isaac PetscAssertPointer(ynorm, 2); 2039c1e67a49SFande Kong *ynorm = snes->ynorm; 20403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2041c1e67a49SFande Kong } 2042c1e67a49SFande Kong 2043c1e67a49SFande Kong /*@ 20444591eaf2SFande Kong SNESGetSolutionNorm - Gets the last computed norm of the solution 2045c1e67a49SFande Kong 2046c1e67a49SFande Kong Not Collective 2047c1e67a49SFande Kong 2048c1e67a49SFande Kong Input Parameter: 2049f6dfbefdSBarry Smith . snes - the `SNES` context 2050c1e67a49SFande Kong 2051c1e67a49SFande Kong Output Parameter: 2052c1e67a49SFande Kong . xnorm - the last computed solution norm 2053c1e67a49SFande Kong 2054c1e67a49SFande Kong Level: developer 2055c1e67a49SFande Kong 20561cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`, `SNESGetUpdateNorm()` 2057c1e67a49SFande Kong @*/ 2058d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionNorm(SNES snes, PetscReal *xnorm) 2059d71ae5a4SJacob Faibussowitsch { 2060c1e67a49SFande Kong PetscFunctionBegin; 2061c1e67a49SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 20624f572ea9SToby Isaac PetscAssertPointer(xnorm, 2); 2063c1e67a49SFande Kong *xnorm = snes->xnorm; 20643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2065c1e67a49SFande Kong } 2066c1e67a49SFande Kong 2067cc4c1da9SBarry Smith /*@ 2068f6dfbefdSBarry Smith SNESSetFunctionType - Sets the `SNESFunctionType` 2069f6dfbefdSBarry Smith of the `SNES` method. 207047073ea2SPeter Brune 2071c3339decSBarry Smith Logically Collective 207247073ea2SPeter Brune 207347073ea2SPeter Brune Input Parameters: 2074f6dfbefdSBarry Smith + snes - the `SNES` context 2075f6dfbefdSBarry Smith - type - the function type 207647073ea2SPeter Brune 207747073ea2SPeter Brune Level: developer 207847073ea2SPeter Brune 2079420bcc1bSBarry Smith Values of the function type\: 2080f6dfbefdSBarry Smith + `SNES_FUNCTION_DEFAULT` - the default for the given `SNESType` 2081f6dfbefdSBarry Smith . `SNES_FUNCTION_UNPRECONDITIONED` - an unpreconditioned function evaluation (this is the function provided with `SNESSetFunction()` 2082f6dfbefdSBarry Smith - `SNES_FUNCTION_PRECONDITIONED` - a transformation of the function provided with `SNESSetFunction()` 2083f6dfbefdSBarry Smith 2084420bcc1bSBarry Smith Note: 2085f6dfbefdSBarry Smith Different `SNESType`s use this value in different ways 2086f6dfbefdSBarry Smith 20871cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFunctionType`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 208847073ea2SPeter Brune @*/ 2089d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionType(SNES snes, SNESFunctionType type) 2090d71ae5a4SJacob Faibussowitsch { 209147073ea2SPeter Brune PetscFunctionBegin; 209247073ea2SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 209347073ea2SPeter Brune snes->functype = type; 20943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 209547073ea2SPeter Brune } 209647073ea2SPeter Brune 2097cc4c1da9SBarry Smith /*@ 2098f6dfbefdSBarry Smith SNESGetFunctionType - Gets the `SNESFunctionType` used in convergence and monitoring set with `SNESSetFunctionType()` 209947073ea2SPeter Brune of the SNES method. 210047073ea2SPeter Brune 2101c3339decSBarry Smith Logically Collective 210247073ea2SPeter Brune 210347073ea2SPeter Brune Input Parameters: 2104f6dfbefdSBarry Smith + snes - the `SNES` context 2105f6dfbefdSBarry Smith - type - the type of the function evaluation, see `SNESSetFunctionType()` 210647073ea2SPeter Brune 210747073ea2SPeter Brune Level: advanced 210847073ea2SPeter Brune 21091cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetFunctionType()`, `SNESFunctionType`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 211047073ea2SPeter Brune @*/ 2111d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionType(SNES snes, SNESFunctionType *type) 2112d71ae5a4SJacob Faibussowitsch { 211347073ea2SPeter Brune PetscFunctionBegin; 211447073ea2SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 211547073ea2SPeter Brune *type = snes->functype; 21163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2117534ebe21SPeter Brune } 2118534ebe21SPeter Brune 2119c79ef259SPeter Brune /*@C 2120be95d8f1SBarry Smith SNESSetNGS - Sets the user nonlinear Gauss-Seidel routine for 2121c79ef259SPeter Brune use with composed nonlinear solvers. 2122c79ef259SPeter Brune 2123c79ef259SPeter Brune Input Parameters: 21249bcc50f1SBarry Smith + snes - the `SNES` context, usually of the `SNESType` `SNESNGS` 21258434afd1SBarry Smith . f - function evaluation routine to apply Gauss-Seidel, see `SNESNGSFn` for calling sequence 2126c79ef259SPeter Brune - ctx - [optional] user-defined context for private data for the 2127dc4c0fb0SBarry Smith smoother evaluation routine (may be `NULL`) 2128c79ef259SPeter Brune 2129dc4c0fb0SBarry Smith Level: intermediate 2130dc4c0fb0SBarry Smith 2131f6dfbefdSBarry Smith Note: 2132f6dfbefdSBarry Smith The `SNESNGS` routines are used by the composed nonlinear solver to generate 2133f6dfbefdSBarry Smith a problem appropriate update to the solution, particularly `SNESFAS`. 2134c79ef259SPeter Brune 21358434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGS`, `SNESGetNGS()`, `SNESNCG`, `SNESGetFunction()`, `SNESComputeNGS()`, `SNESNGSFn` 2136c79ef259SPeter Brune @*/ 21378434afd1SBarry Smith PetscErrorCode SNESSetNGS(SNES snes, SNESNGSFn *f, void *ctx) 2138d71ae5a4SJacob Faibussowitsch { 21396cab3a1bSJed Brown DM dm; 21406cab3a1bSJed Brown 2141646217ecSPeter Brune PetscFunctionBegin; 21426cab3a1bSJed Brown PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 21439566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 21449566063dSJacob Faibussowitsch PetscCall(DMSNESSetNGS(dm, f, ctx)); 21453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2146646217ecSPeter Brune } 2147646217ecSPeter Brune 2148bbc1464cSBarry Smith /* 2149bbc1464cSBarry Smith This is used for -snes_mf_operator; it uses a duplicate of snes->jacobian_pre because snes->jacobian_pre cannot be 2150bbc1464cSBarry Smith changed during the KSPSolve() 2151bbc1464cSBarry Smith */ 2152d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeMFFunction(SNES snes, Vec x, Vec f, void *ctx) 2153d71ae5a4SJacob Faibussowitsch { 2154bbc1464cSBarry Smith DM dm; 2155bbc1464cSBarry Smith DMSNES sdm; 2156bbc1464cSBarry Smith 2157bbc1464cSBarry Smith PetscFunctionBegin; 21589566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 21599566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 2160bbc1464cSBarry Smith /* A(x)*x - b(x) */ 2161bbc1464cSBarry Smith if (sdm->ops->computepfunction) { 2162792fecdfSBarry Smith PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx)); 21639566063dSJacob Faibussowitsch PetscCall(VecScale(f, -1.0)); 21640df40c35SBarry Smith /* Cannot share nonzero pattern because of the possible use of SNESComputeJacobianDefault() */ 2165ef1023bdSBarry Smith if (!snes->picard) PetscCall(MatDuplicate(snes->jacobian_pre, MAT_DO_NOT_COPY_VALUES, &snes->picard)); 2166792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx)); 21679566063dSJacob Faibussowitsch PetscCall(MatMultAdd(snes->picard, x, f, f)); 2168bbc1464cSBarry Smith } else { 2169792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx)); 21709566063dSJacob Faibussowitsch PetscCall(MatMult(snes->picard, x, f)); 2171bbc1464cSBarry Smith } 21723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2173bbc1464cSBarry Smith } 2174bbc1464cSBarry Smith 2175d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeFunction(SNES snes, Vec x, Vec f, void *ctx) 2176d71ae5a4SJacob Faibussowitsch { 2177e03ab78fSPeter Brune DM dm; 2178942e3340SBarry Smith DMSNES sdm; 21796cab3a1bSJed Brown 21808b0a5094SBarry Smith PetscFunctionBegin; 21819566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 21829566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 21838b0a5094SBarry Smith /* A(x)*x - b(x) */ 2184bbc1464cSBarry Smith if (sdm->ops->computepfunction) { 2185792fecdfSBarry Smith PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx)); 21869566063dSJacob Faibussowitsch PetscCall(VecScale(f, -1.0)); 2187792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx)); 21889566063dSJacob Faibussowitsch PetscCall(MatMultAdd(snes->jacobian_pre, x, f, f)); 2189bbc1464cSBarry Smith } else { 2190792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx)); 21919566063dSJacob Faibussowitsch PetscCall(MatMult(snes->jacobian_pre, x, f)); 2192bbc1464cSBarry Smith } 21933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 21948b0a5094SBarry Smith } 21958b0a5094SBarry Smith 2196d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeJacobian(SNES snes, Vec x1, Mat J, Mat B, void *ctx) 2197d71ae5a4SJacob Faibussowitsch { 21988b0a5094SBarry Smith PetscFunctionBegin; 2199e03ab78fSPeter Brune /* the jacobian matrix should be pre-filled in SNESPicardComputeFunction */ 2200bbc1464cSBarry Smith /* must assembly if matrix-free to get the last SNES solution */ 22019566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 22029566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 22033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22048b0a5094SBarry Smith } 22058b0a5094SBarry Smith 22068b0a5094SBarry Smith /*@C 22071d27aa22SBarry Smith SNESSetPicard - Use `SNES` to solve the system $A(x) x = bp(x) + b $ via a Picard type iteration (Picard linearization) 22088b0a5094SBarry Smith 2209c3339decSBarry Smith Logically Collective 22108b0a5094SBarry Smith 22118b0a5094SBarry Smith Input Parameters: 2212f6dfbefdSBarry Smith + snes - the `SNES` context 2213dc4c0fb0SBarry Smith . r - vector to store function values, may be `NULL` 22148434afd1SBarry Smith . bp - function evaluation routine, may be `NULL`, for the calling sequence see `SNESFunctionFn` 22156b7fb656SBarry Smith . Amat - matrix with which A(x) x - bp(x) - b is to be computed 2216dc4c0fb0SBarry Smith . Pmat - matrix from which preconditioner is computed (usually the same as `Amat`) 22178434afd1SBarry Smith . J - function to compute matrix values, for the calling sequence see `SNESJacobianFn` 2218dc4c0fb0SBarry Smith - ctx - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`) 2219dc4c0fb0SBarry Smith 2220dc4c0fb0SBarry Smith Level: intermediate 22218b0a5094SBarry Smith 22228b0a5094SBarry Smith Notes: 22236b7fb656SBarry Smith It is often better to provide the nonlinear function F() and some approximation to its Jacobian directly and use 2224f450aa47SBarry 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. 2225f450aa47SBarry Smith 2226f6dfbefdSBarry Smith One can call `SNESSetPicard()` or `SNESSetFunction()` (and possibly `SNESSetJacobian()`) but cannot call both 22278b0a5094SBarry Smith 22281d27aa22SBarry 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}$. 22291d27aa22SBarry Smith When an exact solver is used this corresponds to the "classic" Picard $A(x^{n}) x^{n+1} = bp(x^{n}) + b$ iteration. 22308b0a5094SBarry Smith 2231dc4c0fb0SBarry Smith Run with `-snes_mf_operator` to solve the system with Newton's method using A(x^{n}) to construct the preconditioner. 22328b0a5094SBarry Smith 22330d04baf8SBarry Smith We implement the defect correction form of the Picard iteration because it converges much more generally when inexact linear solvers are used then 22341d27aa22SBarry Smith the direct Picard iteration $A(x^n) x^{n+1} = bp(x^n) + b$ 22358b0a5094SBarry Smith 22368b0a5094SBarry 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 22371d27aa22SBarry 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 22381d27aa22SBarry Smith different please contact us at petsc-dev@mcs.anl.gov and we'll have an entirely new argument \:-). 22398b0a5094SBarry Smith 22401d27aa22SBarry 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 2241f6dfbefdSBarry Smith A(x^{n}) is used to build the preconditioner 22426b7fb656SBarry Smith 224315229ffcSPierre 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. 22446b7fb656SBarry Smith 2245dc4c0fb0SBarry 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 22466b7fb656SBarry 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 2247f6dfbefdSBarry 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`. 2248aaa8cc7dSPierre Jolivet See the comment in src/snes/tutorials/ex15.c. 2249bbc1464cSBarry Smith 22509bcc50f1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESGetPicard()`, `SNESLineSearchPreCheckPicard()`, 22518434afd1SBarry Smith `SNESFunctionFn`, `SNESJacobianFn` 22528b0a5094SBarry Smith @*/ 22538434afd1SBarry Smith PetscErrorCode SNESSetPicard(SNES snes, Vec r, SNESFunctionFn *bp, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx) 2254d71ae5a4SJacob Faibussowitsch { 2255e03ab78fSPeter Brune DM dm; 2256e03ab78fSPeter Brune 22578b0a5094SBarry Smith PetscFunctionBegin; 22588b0a5094SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 22599566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 22609566063dSJacob Faibussowitsch PetscCall(DMSNESSetPicard(dm, bp, J, ctx)); 22619566063dSJacob Faibussowitsch PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx)); 22629566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes, r, SNESPicardComputeFunction, ctx)); 22639566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESPicardComputeJacobian, ctx)); 22643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22658b0a5094SBarry Smith } 22668b0a5094SBarry Smith 22677971a8bfSPeter Brune /*@C 22687971a8bfSPeter Brune SNESGetPicard - Returns the context for the Picard iteration 22697971a8bfSPeter Brune 2270f6dfbefdSBarry Smith Not Collective, but `Vec` is parallel if `SNES` is parallel. Collective if `Vec` is requested, but has not been created yet. 22717971a8bfSPeter Brune 22727971a8bfSPeter Brune Input Parameter: 2273f6dfbefdSBarry Smith . snes - the `SNES` context 22747971a8bfSPeter Brune 2275d8d19677SJose E. Roman Output Parameters: 2276dc4c0fb0SBarry Smith + r - the function (or `NULL`) 22778434afd1SBarry Smith . f - the function (or `NULL`); for calling sequence see `SNESFunctionFn` 2278dc4c0fb0SBarry Smith . Amat - the matrix used to defined the operation A(x) x - b(x) (or `NULL`) 2279dc4c0fb0SBarry Smith . Pmat - the matrix from which the preconditioner will be constructed (or `NULL`) 22808434afd1SBarry Smith . J - the function for matrix evaluation (or `NULL`); for calling sequence see `SNESJacobianFn` 2281dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`) 22827971a8bfSPeter Brune 22837971a8bfSPeter Brune Level: advanced 22847971a8bfSPeter Brune 22858434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetFunction()`, `SNESSetPicard()`, `SNESGetFunction()`, `SNESGetJacobian()`, `SNESGetDM()`, `SNESFunctionFn`, `SNESJacobianFn` 22867971a8bfSPeter Brune @*/ 22878434afd1SBarry Smith PetscErrorCode SNESGetPicard(SNES snes, Vec *r, SNESFunctionFn **f, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx) 2288d71ae5a4SJacob Faibussowitsch { 22897971a8bfSPeter Brune DM dm; 22907971a8bfSPeter Brune 22917971a8bfSPeter Brune PetscFunctionBegin; 22927971a8bfSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 22939566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, r, NULL, NULL)); 22949566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL)); 22959566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 22969566063dSJacob Faibussowitsch PetscCall(DMSNESGetPicard(dm, f, J, ctx)); 22973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22987971a8bfSPeter Brune } 22997971a8bfSPeter Brune 2300d25893d9SBarry Smith /*@C 2301dc4c0fb0SBarry Smith SNESSetComputeInitialGuess - Sets a routine used to compute an initial guess for the nonlinear problem 2302d25893d9SBarry Smith 2303c3339decSBarry Smith Logically Collective 2304d25893d9SBarry Smith 2305d25893d9SBarry Smith Input Parameters: 2306f6dfbefdSBarry Smith + snes - the `SNES` context 23078434afd1SBarry Smith . func - function evaluation routine, see `SNESInitialGuessFn` for the calling sequence 2308d25893d9SBarry Smith - ctx - [optional] user-defined context for private data for the 2309dc4c0fb0SBarry Smith function evaluation routine (may be `NULL`) 2310d25893d9SBarry Smith 2311d25893d9SBarry Smith Level: intermediate 2312d25893d9SBarry Smith 23138434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESInitialGuessFn` 2314d25893d9SBarry Smith @*/ 23158434afd1SBarry Smith PetscErrorCode SNESSetComputeInitialGuess(SNES snes, SNESInitialGuessFn *func, void *ctx) 2316d71ae5a4SJacob Faibussowitsch { 2317d25893d9SBarry Smith PetscFunctionBegin; 2318d25893d9SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2319d25893d9SBarry Smith if (func) snes->ops->computeinitialguess = func; 2320d25893d9SBarry Smith if (ctx) snes->initialguessP = ctx; 23213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2322d25893d9SBarry Smith } 2323d25893d9SBarry Smith 23241096aae1SMatthew Knepley /*@C 2325dc4c0fb0SBarry Smith SNESGetRhs - Gets the vector for solving F(x) = `rhs`. If `rhs` is not set 2326dd8e379bSPierre Jolivet it assumes a zero right-hand side. 23271096aae1SMatthew Knepley 2328c3339decSBarry Smith Logically Collective 23291096aae1SMatthew Knepley 23301096aae1SMatthew Knepley Input Parameter: 2331f6dfbefdSBarry Smith . snes - the `SNES` context 23321096aae1SMatthew Knepley 23331096aae1SMatthew Knepley Output Parameter: 2334dd8e379bSPierre Jolivet . rhs - the right-hand side vector or `NULL` if there is no right-hand side vector 23351096aae1SMatthew Knepley 23361096aae1SMatthew Knepley Level: intermediate 23371096aae1SMatthew Knepley 23381cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetFunction()` 23391096aae1SMatthew Knepley @*/ 2340d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetRhs(SNES snes, Vec *rhs) 2341d71ae5a4SJacob Faibussowitsch { 23421096aae1SMatthew Knepley PetscFunctionBegin; 23430700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 23444f572ea9SToby Isaac PetscAssertPointer(rhs, 2); 234585385478SLisandro Dalcin *rhs = snes->vec_rhs; 23463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23471096aae1SMatthew Knepley } 23481096aae1SMatthew Knepley 23499b94acceSBarry Smith /*@ 2350f6dfbefdSBarry Smith SNESComputeFunction - Calls the function that has been set with `SNESSetFunction()`. 23519b94acceSBarry Smith 2352c3339decSBarry Smith Collective 2353c7afd0dbSLois Curfman McInnes 23549b94acceSBarry Smith Input Parameters: 2355f6dfbefdSBarry Smith + snes - the `SNES` context 2356c7afd0dbSLois Curfman McInnes - x - input vector 23579b94acceSBarry Smith 23589b94acceSBarry Smith Output Parameter: 2359f6dfbefdSBarry Smith . y - function vector, as set by `SNESSetFunction()` 23609b94acceSBarry Smith 2361dc4c0fb0SBarry Smith Level: developer 2362dc4c0fb0SBarry Smith 236300677de2SStefano Zampini Notes: 2364f6dfbefdSBarry Smith `SNESComputeFunction()` is typically used within nonlinear solvers 2365bbc1464cSBarry Smith implementations, so users would not generally call this routine themselves. 236636851e7fSLois Curfman McInnes 236700677de2SStefano Zampini When solving for $F(x) = b$, this routine computes $y = F(x) - b$. 236800677de2SStefano Zampini 23691cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeMFFunction()` 23709b94acceSBarry Smith @*/ 2371d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeFunction(SNES snes, Vec x, Vec y) 2372d71ae5a4SJacob Faibussowitsch { 23736cab3a1bSJed Brown DM dm; 2374942e3340SBarry Smith DMSNES sdm; 23759b94acceSBarry Smith 23763a40ed3dSBarry Smith PetscFunctionBegin; 23770700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 23780700a824SBarry Smith PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 23790700a824SBarry Smith PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2380c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, x, 2); 2381c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, y, 3); 2382e0f629ddSJacob Faibussowitsch PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2383184914b5SBarry Smith 23849566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 23859566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 23860fdf79fbSJacob 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()."); 238732f3f7c2SPeter Brune if (sdm->ops->computefunction) { 238848a46eb9SPierre Jolivet if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0)); 23899566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(x)); 23908ddeebeaSSteve Benbow /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */ 23918ddeebeaSSteve Benbow snes->domainerror = PETSC_FALSE; 2392800f99ffSJeremy L Thompson { 2393800f99ffSJeremy L Thompson void *ctx; 23948434afd1SBarry Smith SNESFunctionFn *computefunction; 2395800f99ffSJeremy L Thompson PetscCall(DMSNESGetFunction(dm, &computefunction, &ctx)); 2396800f99ffSJeremy L Thompson PetscCallBack("SNES callback function", (*computefunction)(snes, x, y, ctx)); 2397800f99ffSJeremy L Thompson } 23989566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(x)); 239948a46eb9SPierre Jolivet if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0)); 24000fdf79fbSJacob Faibussowitsch } else /* if (snes->vec_rhs) */ { 24019566063dSJacob Faibussowitsch PetscCall(MatMult(snes->jacobian, x, y)); 24020fdf79fbSJacob Faibussowitsch } 24031baa6e33SBarry Smith if (snes->vec_rhs) PetscCall(VecAXPY(y, -1.0, snes->vec_rhs)); 2404ae3c334cSLois Curfman McInnes snes->nfuncs++; 2405422a814eSBarry Smith /* 2406422a814eSBarry Smith domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will 2407422a814eSBarry Smith propagate the value to all processes 2408422a814eSBarry Smith */ 24091baa6e33SBarry Smith if (snes->domainerror) PetscCall(VecSetInf(y)); 24103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24119b94acceSBarry Smith } 24129b94acceSBarry Smith 2413c79ef259SPeter Brune /*@ 2414f6dfbefdSBarry Smith SNESComputeMFFunction - Calls the function that has been set with `SNESSetMFFunction()`. 2415bbc1464cSBarry Smith 2416c3339decSBarry Smith Collective 2417bbc1464cSBarry Smith 2418bbc1464cSBarry Smith Input Parameters: 2419f6dfbefdSBarry Smith + snes - the `SNES` context 2420bbc1464cSBarry Smith - x - input vector 2421bbc1464cSBarry Smith 2422bbc1464cSBarry Smith Output Parameter: 2423f6dfbefdSBarry Smith . y - function vector, as set by `SNESSetMFFunction()` 2424bbc1464cSBarry Smith 2425dc4c0fb0SBarry Smith Level: developer 2426dc4c0fb0SBarry Smith 2427bbc1464cSBarry Smith Notes: 2428420bcc1bSBarry Smith `SNESComputeMFFunction()` is used within the matrix-vector products called by the matrix created with `MatCreateSNESMF()` 2429bbc1464cSBarry Smith so users would not generally call this routine themselves. 2430bbc1464cSBarry Smith 2431dd8e379bSPierre Jolivet Since this function is intended for use with finite differencing it does not subtract the right-hand side vector provided with `SNESSolve()` 2432f6dfbefdSBarry Smith while `SNESComputeFunction()` does. As such, this routine cannot be used with `MatMFFDSetBase()` with a provided F function value even if it applies the 2433dd8e379bSPierre 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. 2434bbc1464cSBarry Smith 24351cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `MatCreateSNESMF` 2436bbc1464cSBarry Smith @*/ 2437d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeMFFunction(SNES snes, Vec x, Vec y) 2438d71ae5a4SJacob Faibussowitsch { 2439bbc1464cSBarry Smith DM dm; 2440bbc1464cSBarry Smith DMSNES sdm; 2441bbc1464cSBarry Smith 2442bbc1464cSBarry Smith PetscFunctionBegin; 2443bbc1464cSBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2444bbc1464cSBarry Smith PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2445bbc1464cSBarry Smith PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2446bbc1464cSBarry Smith PetscCheckSameComm(snes, 1, x, 2); 2447bbc1464cSBarry Smith PetscCheckSameComm(snes, 1, y, 3); 2448e0f629ddSJacob Faibussowitsch PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2449bbc1464cSBarry Smith 24509566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 24519566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 24529566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0)); 24539566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(x)); 2454bbc1464cSBarry Smith /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */ 2455bbc1464cSBarry Smith snes->domainerror = PETSC_FALSE; 2456792fecdfSBarry Smith PetscCallBack("SNES callback function", (*sdm->ops->computemffunction)(snes, x, y, sdm->mffunctionctx)); 24579566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(x)); 24589566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0)); 2459bbc1464cSBarry Smith snes->nfuncs++; 2460bbc1464cSBarry Smith /* 2461bbc1464cSBarry Smith domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will 2462bbc1464cSBarry Smith propagate the value to all processes 2463bbc1464cSBarry Smith */ 24641baa6e33SBarry Smith if (snes->domainerror) PetscCall(VecSetInf(y)); 24653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2466bbc1464cSBarry Smith } 2467bbc1464cSBarry Smith 2468bbc1464cSBarry Smith /*@ 2469f6dfbefdSBarry Smith SNESComputeNGS - Calls the Gauss-Seidel function that has been set with `SNESSetNGS()`. 2470c79ef259SPeter Brune 2471c3339decSBarry Smith Collective 2472c79ef259SPeter Brune 2473c79ef259SPeter Brune Input Parameters: 2474f6dfbefdSBarry Smith + snes - the `SNES` context 2475c79ef259SPeter Brune . x - input vector 2476c79ef259SPeter Brune - b - rhs vector 2477c79ef259SPeter Brune 2478c79ef259SPeter Brune Output Parameter: 2479c79ef259SPeter Brune . x - new solution vector 2480c79ef259SPeter Brune 2481dc4c0fb0SBarry Smith Level: developer 2482dc4c0fb0SBarry Smith 2483f6dfbefdSBarry Smith Note: 2484f6dfbefdSBarry Smith `SNESComputeNGS()` is typically used within composed nonlinear solver 2485c79ef259SPeter Brune implementations, so most users would not generally call this routine 2486c79ef259SPeter Brune themselves. 2487c79ef259SPeter Brune 24888434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGSFn`, `SNESSetNGS()`, `SNESComputeFunction()`, `SNESNGS` 2489c79ef259SPeter Brune @*/ 2490d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeNGS(SNES snes, Vec b, Vec x) 2491d71ae5a4SJacob Faibussowitsch { 24926cab3a1bSJed Brown DM dm; 2493942e3340SBarry Smith DMSNES sdm; 2494646217ecSPeter Brune 2495646217ecSPeter Brune PetscFunctionBegin; 2496646217ecSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2497064a246eSJacob Faibussowitsch PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 2498064a246eSJacob Faibussowitsch if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 2499064a246eSJacob Faibussowitsch PetscCheckSameComm(snes, 1, x, 3); 2500064a246eSJacob Faibussowitsch if (b) PetscCheckSameComm(snes, 1, b, 2); 2501e0f629ddSJacob Faibussowitsch if (b) PetscCall(VecValidValues_Internal(b, 2, PETSC_TRUE)); 25029566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_NGSEval, snes, x, b, 0)); 25039566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 25049566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 25050fdf79fbSJacob Faibussowitsch PetscCheck(sdm->ops->computegs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetNGS() before SNESComputeNGS(), likely called from SNESSolve()."); 25069566063dSJacob Faibussowitsch if (b) PetscCall(VecLockReadPush(b)); 2507792fecdfSBarry Smith PetscCallBack("SNES callback NGS", (*sdm->ops->computegs)(snes, x, b, sdm->gsctx)); 25089566063dSJacob Faibussowitsch if (b) PetscCall(VecLockReadPop(b)); 25099566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_NGSEval, snes, x, b, 0)); 25103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2511646217ecSPeter Brune } 2512646217ecSPeter Brune 2513494a190aSStefano Zampini static PetscErrorCode SNESComputeFunction_FD(SNES snes, Vec Xin, Vec G) 2514494a190aSStefano Zampini { 2515494a190aSStefano Zampini Vec X; 2516494a190aSStefano Zampini PetscScalar *g; 2517494a190aSStefano Zampini PetscReal f, f2; 2518494a190aSStefano Zampini PetscInt low, high, N, i; 2519494a190aSStefano Zampini PetscBool flg; 2520494a190aSStefano Zampini PetscReal h = .5 * PETSC_SQRT_MACHINE_EPSILON; 2521494a190aSStefano Zampini 2522494a190aSStefano Zampini PetscFunctionBegin; 2523494a190aSStefano Zampini PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_fd_delta", &h, &flg)); 2524494a190aSStefano Zampini PetscCall(VecDuplicate(Xin, &X)); 2525494a190aSStefano Zampini PetscCall(VecCopy(Xin, X)); 2526494a190aSStefano Zampini PetscCall(VecGetSize(X, &N)); 2527494a190aSStefano Zampini PetscCall(VecGetOwnershipRange(X, &low, &high)); 2528494a190aSStefano Zampini PetscCall(VecSetOption(X, VEC_IGNORE_OFF_PROC_ENTRIES, PETSC_TRUE)); 2529494a190aSStefano Zampini PetscCall(VecGetArray(G, &g)); 2530494a190aSStefano Zampini for (i = 0; i < N; i++) { 2531494a190aSStefano Zampini PetscCall(VecSetValue(X, i, -h, ADD_VALUES)); 2532494a190aSStefano Zampini PetscCall(VecAssemblyBegin(X)); 2533494a190aSStefano Zampini PetscCall(VecAssemblyEnd(X)); 2534494a190aSStefano Zampini PetscCall(SNESComputeObjective(snes, X, &f)); 2535494a190aSStefano Zampini PetscCall(VecSetValue(X, i, 2.0 * h, ADD_VALUES)); 2536494a190aSStefano Zampini PetscCall(VecAssemblyBegin(X)); 2537494a190aSStefano Zampini PetscCall(VecAssemblyEnd(X)); 2538494a190aSStefano Zampini PetscCall(SNESComputeObjective(snes, X, &f2)); 2539494a190aSStefano Zampini PetscCall(VecSetValue(X, i, -h, ADD_VALUES)); 2540494a190aSStefano Zampini PetscCall(VecAssemblyBegin(X)); 2541494a190aSStefano Zampini PetscCall(VecAssemblyEnd(X)); 2542494a190aSStefano Zampini if (i >= low && i < high) g[i - low] = (f2 - f) / (2.0 * h); 2543494a190aSStefano Zampini } 2544494a190aSStefano Zampini PetscCall(VecRestoreArray(G, &g)); 2545494a190aSStefano Zampini PetscCall(VecDestroy(&X)); 2546494a190aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2547494a190aSStefano Zampini } 2548494a190aSStefano Zampini 2549494a190aSStefano Zampini PetscErrorCode SNESTestFunction(SNES snes) 2550494a190aSStefano Zampini { 2551494a190aSStefano Zampini Vec x, g1, g2, g3; 2552494a190aSStefano Zampini PetscBool complete_print = PETSC_FALSE, test = PETSC_FALSE; 2553494a190aSStefano Zampini PetscReal hcnorm, fdnorm, hcmax, fdmax, diffmax, diffnorm; 2554494a190aSStefano Zampini PetscScalar dot; 2555494a190aSStefano Zampini MPI_Comm comm; 2556494a190aSStefano Zampini PetscViewer viewer, mviewer; 2557494a190aSStefano Zampini PetscViewerFormat format; 2558494a190aSStefano Zampini PetscInt tabs; 2559494a190aSStefano Zampini static PetscBool directionsprinted = PETSC_FALSE; 25608434afd1SBarry Smith SNESObjectiveFn *objective; 2561494a190aSStefano Zampini 2562494a190aSStefano Zampini PetscFunctionBegin; 2563494a190aSStefano Zampini PetscCall(SNESGetObjective(snes, &objective, NULL)); 2564494a190aSStefano Zampini if (!objective) PetscFunctionReturn(PETSC_SUCCESS); 2565494a190aSStefano Zampini 2566494a190aSStefano Zampini PetscObjectOptionsBegin((PetscObject)snes); 2567494a190aSStefano Zampini PetscCall(PetscOptionsName("-snes_test_function", "Compare hand-coded and finite difference function", "None", &test)); 2568494a190aSStefano Zampini PetscCall(PetscOptionsViewer("-snes_test_function_view", "View difference between hand-coded and finite difference function element entries", "None", &mviewer, &format, &complete_print)); 2569494a190aSStefano Zampini PetscOptionsEnd(); 2570494a190aSStefano Zampini if (!test) { 2571494a190aSStefano Zampini if (complete_print) PetscCall(PetscViewerDestroy(&mviewer)); 2572494a190aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2573494a190aSStefano Zampini } 2574494a190aSStefano Zampini 2575494a190aSStefano Zampini PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 2576494a190aSStefano Zampini PetscCall(PetscViewerASCIIGetStdout(comm, &viewer)); 2577494a190aSStefano Zampini PetscCall(PetscViewerASCIIGetTab(viewer, &tabs)); 2578494a190aSStefano Zampini PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel)); 2579494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Function -------------\n")); 2580494a190aSStefano Zampini if (!complete_print && !directionsprinted) { 2581494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Run with -snes_test_function_view and optionally -snes_test_function <threshold> to show difference\n")); 2582494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " of hand-coded and finite difference function entries greater than <threshold>.\n")); 2583494a190aSStefano Zampini } 2584494a190aSStefano Zampini if (!directionsprinted) { 2585494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Testing hand-coded Function, if (for double precision runs) ||F - Ffd||/||F|| is\n")); 2586494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " O(1.e-8), the hand-coded Function is probably correct.\n")); 2587494a190aSStefano Zampini directionsprinted = PETSC_TRUE; 2588494a190aSStefano Zampini } 2589494a190aSStefano Zampini if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format)); 2590494a190aSStefano Zampini 2591494a190aSStefano Zampini PetscCall(SNESGetSolution(snes, &x)); 2592494a190aSStefano Zampini PetscCall(VecDuplicate(x, &g1)); 2593494a190aSStefano Zampini PetscCall(VecDuplicate(x, &g2)); 2594494a190aSStefano Zampini PetscCall(VecDuplicate(x, &g3)); 2595494a190aSStefano Zampini PetscCall(SNESComputeFunction(snes, x, g1)); 2596494a190aSStefano Zampini PetscCall(SNESComputeFunction_FD(snes, x, g2)); 2597494a190aSStefano Zampini 2598494a190aSStefano Zampini PetscCall(VecNorm(g2, NORM_2, &fdnorm)); 2599494a190aSStefano Zampini PetscCall(VecNorm(g1, NORM_2, &hcnorm)); 2600494a190aSStefano Zampini PetscCall(VecNorm(g2, NORM_INFINITY, &fdmax)); 2601494a190aSStefano Zampini PetscCall(VecNorm(g1, NORM_INFINITY, &hcmax)); 2602494a190aSStefano Zampini PetscCall(VecDot(g1, g2, &dot)); 2603494a190aSStefano Zampini PetscCall(VecCopy(g1, g3)); 2604494a190aSStefano Zampini PetscCall(VecAXPY(g3, -1.0, g2)); 2605494a190aSStefano Zampini PetscCall(VecNorm(g3, NORM_2, &diffnorm)); 2606494a190aSStefano Zampini PetscCall(VecNorm(g3, NORM_INFINITY, &diffmax)); 2607494a190aSStefano 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)))); 2608494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " 2-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffnorm / PetscMax(hcnorm, fdnorm)), (double)diffnorm)); 2609494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " max-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffmax / PetscMax(hcmax, fdmax)), (double)diffmax)); 2610494a190aSStefano Zampini 2611494a190aSStefano Zampini if (complete_print) { 2612494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded function ----------\n")); 2613494a190aSStefano Zampini PetscCall(VecView(g1, mviewer)); 2614494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Finite difference function ----------\n")); 2615494a190aSStefano Zampini PetscCall(VecView(g2, mviewer)); 2616494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded minus finite-difference function ----------\n")); 2617494a190aSStefano Zampini PetscCall(VecView(g3, mviewer)); 2618494a190aSStefano Zampini } 2619494a190aSStefano Zampini PetscCall(VecDestroy(&g1)); 2620494a190aSStefano Zampini PetscCall(VecDestroy(&g2)); 2621494a190aSStefano Zampini PetscCall(VecDestroy(&g3)); 2622494a190aSStefano Zampini 2623494a190aSStefano Zampini if (complete_print) { 2624494a190aSStefano Zampini PetscCall(PetscViewerPopFormat(mviewer)); 2625494a190aSStefano Zampini PetscCall(PetscViewerDestroy(&mviewer)); 2626494a190aSStefano Zampini } 2627494a190aSStefano Zampini PetscCall(PetscViewerASCIISetTab(viewer, tabs)); 2628494a190aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2629494a190aSStefano Zampini } 2630494a190aSStefano Zampini 2631d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestJacobian(SNES snes) 2632d71ae5a4SJacob Faibussowitsch { 263312837594SBarry Smith Mat A, B, C, D, jacobian; 26344df93895SStefano Zampini Vec x = snes->vec_sol, f; 2635e885f1abSBarry Smith PetscReal nrm, gnorm; 263681e7118cSBarry Smith PetscReal threshold = 1.e-5; 26370e276705SLisandro Dalcin MatType mattype; 2638e885f1abSBarry Smith PetscInt m, n, M, N; 2639e885f1abSBarry Smith void *functx; 26402cd624f9SStefano Zampini PetscBool complete_print = PETSC_FALSE, threshold_print = PETSC_FALSE, test = PETSC_FALSE, flg, istranspose; 26413325ff46SBarry Smith PetscViewer viewer, mviewer; 2642e885f1abSBarry Smith MPI_Comm comm; 2643e885f1abSBarry Smith PetscInt tabs; 264412837594SBarry Smith static PetscBool directionsprinted = PETSC_FALSE; 26453325ff46SBarry Smith PetscViewerFormat format; 2646e885f1abSBarry Smith 2647e885f1abSBarry Smith PetscFunctionBegin; 2648d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)snes); 26499566063dSJacob Faibussowitsch PetscCall(PetscOptionsName("-snes_test_jacobian", "Compare hand-coded and finite difference Jacobians", "None", &test)); 26509566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-snes_test_jacobian", "Threshold for element difference between hand-coded and finite difference being meaningful", "None", threshold, &threshold, NULL)); 26519566063dSJacob Faibussowitsch PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display", "-snes_test_jacobian_view", "3.13", NULL)); 26524ead3382SBarry Smith PetscCall(PetscOptionsViewer("-snes_test_jacobian_view", "View difference between hand-coded and finite difference Jacobians element entries", "None", &mviewer, &format, &complete_print)); 26539566063dSJacob Faibussowitsch PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display_threshold", "-snes_test_jacobian", "3.13", "-snes_test_jacobian accepts an optional threshold (since v3.10)")); 26549566063dSJacob 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)); 2655d0609cedSBarry Smith PetscOptionsEnd(); 26563ba16761SJacob Faibussowitsch if (!test) PetscFunctionReturn(PETSC_SUCCESS); 2657e885f1abSBarry Smith 26589566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 26599566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(comm, &viewer)); 26609566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetTab(viewer, &tabs)); 26619566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel)); 26629566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Jacobian -------------\n")); 266312837594SBarry Smith if (!complete_print && !directionsprinted) { 26649566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Run with -snes_test_jacobian_view and optionally -snes_test_jacobian <threshold> to show difference\n")); 26659566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " of hand-coded and finite difference Jacobian entries greater than <threshold>.\n")); 266612837594SBarry Smith } 266712837594SBarry Smith if (!directionsprinted) { 26689566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Testing hand-coded Jacobian, if (for double precision runs) ||J - Jfd||_F/||J||_F is\n")); 26699566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " O(1.e-8), the hand-coded Jacobian is probably correct.\n")); 267012837594SBarry Smith directionsprinted = PETSC_TRUE; 2671e885f1abSBarry Smith } 26721baa6e33SBarry Smith if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format)); 2673e885f1abSBarry Smith 26749566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes->jacobian, MATMFFD, &flg)); 267512837594SBarry Smith if (!flg) jacobian = snes->jacobian; 267612837594SBarry Smith else jacobian = snes->jacobian_pre; 267712837594SBarry Smith 26784df93895SStefano Zampini if (!x) PetscCall(MatCreateVecs(jacobian, &x, NULL)); 26794df93895SStefano Zampini else PetscCall(PetscObjectReference((PetscObject)x)); 26809566063dSJacob Faibussowitsch PetscCall(VecDuplicate(x, &f)); 26814df93895SStefano Zampini 2682a82339d0SMatthew G. Knepley /* evaluate the function at this point because SNESComputeJacobianDefault() assumes that the function has been evaluated and put into snes->vec_func */ 26839566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, x, f)); 26849566063dSJacob Faibussowitsch PetscCall(VecDestroy(&f)); 26859566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESKSPTRANSPOSEONLY, &istranspose)); 268612837594SBarry Smith while (jacobian) { 26872cd624f9SStefano Zampini Mat JT = NULL, Jsave = NULL; 26882cd624f9SStefano Zampini 26892cd624f9SStefano Zampini if (istranspose) { 26909566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(jacobian, &JT)); 26912cd624f9SStefano Zampini Jsave = jacobian; 26922cd624f9SStefano Zampini jacobian = JT; 26932cd624f9SStefano Zampini } 26949566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)jacobian, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, "")); 269512837594SBarry Smith if (flg) { 269612837594SBarry Smith A = jacobian; 26979566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 269812837594SBarry Smith } else { 26999566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(jacobian, MATAIJ, &A)); 270012837594SBarry Smith } 2701e885f1abSBarry Smith 27029566063dSJacob Faibussowitsch PetscCall(MatGetType(A, &mattype)); 27039566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &M, &N)); 27049566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &m, &n)); 27059566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B)); 27069566063dSJacob Faibussowitsch PetscCall(MatSetType(B, mattype)); 27079566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, m, n, M, N)); 27089566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(B, A, A)); 27099566063dSJacob Faibussowitsch PetscCall(MatSetUp(B)); 27109566063dSJacob Faibussowitsch PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 2711e885f1abSBarry Smith 27129566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, NULL, &functx)); 27139566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobianDefault(snes, x, B, B, functx)); 271412837594SBarry Smith 27159566063dSJacob Faibussowitsch PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &D)); 27169566063dSJacob Faibussowitsch PetscCall(MatAYPX(D, -1.0, A, DIFFERENT_NONZERO_PATTERN)); 27179566063dSJacob Faibussowitsch PetscCall(MatNorm(D, NORM_FROBENIUS, &nrm)); 27189566063dSJacob Faibussowitsch PetscCall(MatNorm(A, NORM_FROBENIUS, &gnorm)); 27199566063dSJacob Faibussowitsch PetscCall(MatDestroy(&D)); 272012837594SBarry Smith if (!gnorm) gnorm = 1; /* just in case */ 27219566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " ||J - Jfd||_F/||J||_F = %g, ||J - Jfd||_F = %g\n", (double)(nrm / gnorm), (double)nrm)); 272212837594SBarry Smith 2723e885f1abSBarry Smith if (complete_print) { 27249566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded Jacobian ----------\n")); 27259566063dSJacob Faibussowitsch PetscCall(MatView(A, mviewer)); 27269566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Finite difference Jacobian ----------\n")); 27279566063dSJacob Faibussowitsch PetscCall(MatView(B, mviewer)); 2728e885f1abSBarry Smith } 2729e885f1abSBarry Smith 2730df10fb39SFande Kong if (threshold_print || complete_print) { 2731e885f1abSBarry Smith PetscInt Istart, Iend, *ccols, bncols, cncols, j, row; 2732e885f1abSBarry Smith PetscScalar *cvals; 2733e885f1abSBarry Smith const PetscInt *bcols; 2734e885f1abSBarry Smith const PetscScalar *bvals; 2735e885f1abSBarry Smith 27369566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C)); 27379566063dSJacob Faibussowitsch PetscCall(MatSetType(C, mattype)); 27389566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, m, n, M, N)); 27399566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(C, A, A)); 27409566063dSJacob Faibussowitsch PetscCall(MatSetUp(C)); 27419566063dSJacob Faibussowitsch PetscCall(MatSetOption(C, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 27420e276705SLisandro Dalcin 27439566063dSJacob Faibussowitsch PetscCall(MatAYPX(B, -1.0, A, DIFFERENT_NONZERO_PATTERN)); 27449566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(B, &Istart, &Iend)); 2745e885f1abSBarry Smith 2746e885f1abSBarry Smith for (row = Istart; row < Iend; row++) { 27479566063dSJacob Faibussowitsch PetscCall(MatGetRow(B, row, &bncols, &bcols, &bvals)); 27489566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(bncols, &ccols, bncols, &cvals)); 2749e885f1abSBarry Smith for (j = 0, cncols = 0; j < bncols; j++) { 275023a52b1dSBarry Smith if (PetscAbsScalar(bvals[j]) > threshold) { 2751e885f1abSBarry Smith ccols[cncols] = bcols[j]; 2752e885f1abSBarry Smith cvals[cncols] = bvals[j]; 2753e885f1abSBarry Smith cncols += 1; 2754e885f1abSBarry Smith } 2755e885f1abSBarry Smith } 275648a46eb9SPierre Jolivet if (cncols) PetscCall(MatSetValues(C, 1, &row, cncols, ccols, cvals, INSERT_VALUES)); 27579566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(B, row, &bncols, &bcols, &bvals)); 27589566063dSJacob Faibussowitsch PetscCall(PetscFree2(ccols, cvals)); 2759e885f1abSBarry Smith } 27609566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 27619566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 27629566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded minus finite-difference Jacobian with tolerance %g ----------\n", (double)threshold)); 27639566063dSJacob Faibussowitsch PetscCall(MatView(C, complete_print ? mviewer : viewer)); 27649566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C)); 2765e885f1abSBarry Smith } 27669566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A)); 27679566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 27689566063dSJacob Faibussowitsch PetscCall(MatDestroy(&JT)); 27692cd624f9SStefano Zampini if (Jsave) jacobian = Jsave; 277012837594SBarry Smith if (jacobian != snes->jacobian_pre) { 277112837594SBarry Smith jacobian = snes->jacobian_pre; 27729566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Jacobian for preconditioner -------------\n")); 27739371c9d4SSatish Balay } else jacobian = NULL; 277412837594SBarry Smith } 27759566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); 27761baa6e33SBarry Smith if (complete_print) PetscCall(PetscViewerPopFormat(mviewer)); 2777cd791dc2SBarry Smith if (mviewer) PetscCall(PetscOptionsRestoreViewer(&mviewer)); 27789566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISetTab(viewer, tabs)); 27793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2780e885f1abSBarry Smith } 2781e885f1abSBarry Smith 278262fef451SLois Curfman McInnes /*@ 2783f6dfbefdSBarry Smith SNESComputeJacobian - Computes the Jacobian matrix that has been set with `SNESSetJacobian()`. 278462fef451SLois Curfman McInnes 2785c3339decSBarry Smith Collective 2786c7afd0dbSLois Curfman McInnes 278762fef451SLois Curfman McInnes Input Parameters: 2788f6dfbefdSBarry Smith + snes - the `SNES` context 2789e4094ef1SJacob Faibussowitsch - X - input vector 279062fef451SLois Curfman McInnes 279162fef451SLois Curfman McInnes Output Parameters: 2792c7afd0dbSLois Curfman McInnes + A - Jacobian matrix 2793420bcc1bSBarry Smith - B - optional matrix for building the preconditioner, usually the same as `A` 2794fee21e36SBarry Smith 2795e35cf81dSBarry Smith Options Database Keys: 279667b8a455SSatish Balay + -snes_lag_preconditioner <lag> - how often to rebuild preconditioner 279767b8a455SSatish Balay . -snes_lag_jacobian <lag> - how often to rebuild Jacobian 2798455a5933SJed 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. 2799455a5933SJed 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 2800693365a8SJed Brown . -snes_compare_explicit - Compare the computed Jacobian to the finite difference Jacobian and output the differences 2801693365a8SJed Brown . -snes_compare_explicit_draw - Compare the computed Jacobian to the finite difference Jacobian and draw the result 2802693365a8SJed Brown . -snes_compare_explicit_contour - Compare the computed Jacobian to the finite difference Jacobian and draw a contour plot with the result 28034c30e9fbSJed Brown . -snes_compare_operator - Make the comparison options above use the operator instead of the preconditioning matrix 280494d6a431SBarry Smith . -snes_compare_coloring - Compute the finite difference Jacobian using coloring and display norms of difference 2805a5b23f4aSJose E. Roman . -snes_compare_coloring_display - Compute the finite difference Jacobian using coloring and display verbose differences 2806c01495d3SJed Brown . -snes_compare_coloring_threshold - Display only those matrix entries that differ by more than a given threshold 2807dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_atol - Absolute tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold` 2808dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_rtol - Relative tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold` 2809a5b23f4aSJose E. Roman . -snes_compare_coloring_draw - Compute the finite difference Jacobian using coloring and draw differences 2810a5b23f4aSJose E. Roman - -snes_compare_coloring_draw_contour - Compute the finite difference Jacobian using coloring and show contours of matrices and differences 2811c01495d3SJed Brown 2812dc4c0fb0SBarry Smith Level: developer 2813dc4c0fb0SBarry Smith 2814f6dfbefdSBarry Smith Note: 281562fef451SLois Curfman McInnes Most users should not need to explicitly call this routine, as it 281662fef451SLois Curfman McInnes is used internally within the nonlinear solvers. 281762fef451SLois Curfman McInnes 2818420bcc1bSBarry Smith Developer Note: 2819dc4c0fb0SBarry 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 2820420bcc1bSBarry Smith with the `SNESType` of test that has been removed. 2821e885f1abSBarry Smith 28221cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetJacobian()`, `KSPSetOperators()`, `MatStructure`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()` 282362fef451SLois Curfman McInnes @*/ 2824d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeJacobian(SNES snes, Vec X, Mat A, Mat B) 2825d71ae5a4SJacob Faibussowitsch { 2826ace3abfcSBarry Smith PetscBool flag; 28276cab3a1bSJed Brown DM dm; 2828942e3340SBarry Smith DMSNES sdm; 2829e0e3a89bSBarry Smith KSP ksp; 28303a40ed3dSBarry Smith 28313a40ed3dSBarry Smith PetscFunctionBegin; 28320700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 28330700a824SBarry Smith PetscValidHeaderSpecific(X, VEC_CLASSID, 2); 2834c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, X, 2); 2835e0f629ddSJacob Faibussowitsch PetscCall(VecValidValues_Internal(X, 2, PETSC_TRUE)); 28369566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 28379566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 28383232da50SPeter Brune 283901c1178eSBarry Smith /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix-free */ 2840fe3ffe1eSBarry Smith if (snes->lagjacobian == -2) { 2841fe3ffe1eSBarry Smith snes->lagjacobian = -1; 2842f5af7f23SKarl Rupp 28439566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n")); 2844fe3ffe1eSBarry Smith } else if (snes->lagjacobian == -1) { 28459566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is -1\n")); 28469566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag)); 2847ebd3b9afSBarry Smith if (flag) { 28489566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 28499566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 2850ebd3b9afSBarry Smith } 28513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 285237ec4e1aSPeter Brune } else if (snes->lagjacobian > 1 && (snes->iter + snes->jac_iter) % snes->lagjacobian) { 285363a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagjacobian, snes->iter)); 28549566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag)); 2855ebd3b9afSBarry Smith if (flag) { 28569566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 28579566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 2858ebd3b9afSBarry Smith } 28593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2860e35cf81dSBarry Smith } 2861efd4aadfSBarry Smith if (snes->npc && snes->npcside == PC_LEFT) { 28629566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 28639566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 28643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2865d728fb7dSPeter Brune } 2866e35cf81dSBarry Smith 28679566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_JacobianEval, snes, X, A, B)); 28689566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(X)); 2869800f99ffSJeremy L Thompson { 2870800f99ffSJeremy L Thompson void *ctx; 28718434afd1SBarry Smith SNESJacobianFn *J; 2872800f99ffSJeremy L Thompson PetscCall(DMSNESGetJacobian(dm, &J, &ctx)); 2873800f99ffSJeremy L Thompson PetscCallBack("SNES callback Jacobian", (*J)(snes, X, A, B, ctx)); 2874800f99ffSJeremy L Thompson } 28759566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(X)); 28769566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_JacobianEval, snes, X, A, B)); 287728d58a37SPierre Jolivet 287828d58a37SPierre Jolivet /* attach latest linearization point to the preconditioning matrix */ 28799566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)B, "__SNES_latest_X", (PetscObject)X)); 2880a8054027SBarry Smith 2881e0e3a89bSBarry Smith /* the next line ensures that snes->ksp exists */ 28829566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 28833b4f5425SBarry Smith if (snes->lagpreconditioner == -2) { 28849566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Rebuilding preconditioner exactly once since lag is -2\n")); 28859566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE)); 28863b4f5425SBarry Smith snes->lagpreconditioner = -1; 28873b4f5425SBarry Smith } else if (snes->lagpreconditioner == -1) { 28889566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is -1\n")); 28899566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE)); 289037ec4e1aSPeter Brune } else if (snes->lagpreconditioner > 1 && (snes->iter + snes->pre_iter) % snes->lagpreconditioner) { 289163a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagpreconditioner, snes->iter)); 28929566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE)); 2893d1e9a80fSBarry Smith } else { 28949566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Rebuilding preconditioner\n")); 28959566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE)); 2896a8054027SBarry Smith } 2897a8054027SBarry Smith 28984df93895SStefano Zampini /* monkey business to allow testing Jacobians in multilevel solvers. 28994df93895SStefano Zampini This is needed because the SNESTestXXX interface does not accept vectors and matrices */ 29004df93895SStefano Zampini { 29014df93895SStefano Zampini Vec xsave = snes->vec_sol; 29024df93895SStefano Zampini Mat jacobiansave = snes->jacobian; 29034df93895SStefano Zampini Mat jacobian_presave = snes->jacobian_pre; 29044df93895SStefano Zampini 29054df93895SStefano Zampini snes->vec_sol = X; 29064df93895SStefano Zampini snes->jacobian = A; 29074df93895SStefano Zampini snes->jacobian_pre = B; 2908494a190aSStefano Zampini PetscCall(SNESTestFunction(snes)); 29099566063dSJacob Faibussowitsch PetscCall(SNESTestJacobian(snes)); 2910494a190aSStefano Zampini 29114df93895SStefano Zampini snes->vec_sol = xsave; 29124df93895SStefano Zampini snes->jacobian = jacobiansave; 29134df93895SStefano Zampini snes->jacobian_pre = jacobian_presave; 29144df93895SStefano Zampini } 29154df93895SStefano Zampini 2916693365a8SJed Brown { 2917693365a8SJed Brown PetscBool flag = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_operator = PETSC_FALSE; 29189566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit", NULL, NULL, &flag)); 29199566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw", NULL, NULL, &flag_draw)); 29209566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw_contour", NULL, NULL, &flag_contour)); 29219566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_operator", NULL, NULL, &flag_operator)); 2922693365a8SJed Brown if (flag || flag_draw || flag_contour) { 29230298fd71SBarry Smith Mat Bexp_mine = NULL, Bexp, FDexp; 2924693365a8SJed Brown PetscViewer vdraw, vstdout; 29256b3a5b13SJed Brown PetscBool flg; 2926693365a8SJed Brown if (flag_operator) { 29279566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(A, MATAIJ, &Bexp_mine)); 2928693365a8SJed Brown Bexp = Bexp_mine; 2929693365a8SJed Brown } else { 2930693365a8SJed Brown /* See if the preconditioning matrix can be viewed and added directly */ 29319566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)B, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPIBAIJ, "")); 293294ab13aaSBarry Smith if (flg) Bexp = B; 2933693365a8SJed Brown else { 2934693365a8SJed Brown /* If the "preconditioning" matrix is itself MATSHELL or some other type without direct support */ 29359566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(B, MATAIJ, &Bexp_mine)); 2936693365a8SJed Brown Bexp = Bexp_mine; 2937693365a8SJed Brown } 2938693365a8SJed Brown } 29399566063dSJacob Faibussowitsch PetscCall(MatConvert(Bexp, MATSAME, MAT_INITIAL_MATRIX, &FDexp)); 29409566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobianDefault(snes, X, FDexp, FDexp, NULL)); 29419566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout)); 2942693365a8SJed Brown if (flag_draw || flag_contour) { 29439566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Explicit Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw)); 29449566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 29450298fd71SBarry Smith } else vdraw = NULL; 29469566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit %s\n", flag_operator ? "Jacobian" : "preconditioning Jacobian")); 29479566063dSJacob Faibussowitsch if (flag) PetscCall(MatView(Bexp, vstdout)); 29489566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(Bexp, vdraw)); 29499566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Finite difference Jacobian\n")); 29509566063dSJacob Faibussowitsch if (flag) PetscCall(MatView(FDexp, vstdout)); 29519566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(FDexp, vdraw)); 29529566063dSJacob Faibussowitsch PetscCall(MatAYPX(FDexp, -1.0, Bexp, SAME_NONZERO_PATTERN)); 29539566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian\n")); 29549566063dSJacob Faibussowitsch if (flag) PetscCall(MatView(FDexp, vstdout)); 2955693365a8SJed Brown if (vdraw) { /* Always use contour for the difference */ 29569566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 29579566063dSJacob Faibussowitsch PetscCall(MatView(FDexp, vdraw)); 29589566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(vdraw)); 2959693365a8SJed Brown } 29609566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw)); 29619566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&vdraw)); 29629566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bexp_mine)); 29639566063dSJacob Faibussowitsch PetscCall(MatDestroy(&FDexp)); 2964693365a8SJed Brown } 2965693365a8SJed Brown } 29664c30e9fbSJed Brown { 29676719d8e4SJed Brown PetscBool flag = PETSC_FALSE, flag_display = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_threshold = PETSC_FALSE; 29686719d8e4SJed Brown PetscReal threshold_atol = PETSC_SQRT_MACHINE_EPSILON, threshold_rtol = 10 * PETSC_SQRT_MACHINE_EPSILON; 29699566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring", NULL, NULL, &flag)); 29709566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_display", NULL, NULL, &flag_display)); 29719566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw", NULL, NULL, &flag_draw)); 29729566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw_contour", NULL, NULL, &flag_contour)); 29739566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold", NULL, NULL, &flag_threshold)); 297427b0f280SBarry Smith if (flag_threshold) { 29759566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_rtol", &threshold_rtol, NULL)); 29769566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_atol", &threshold_atol, NULL)); 297727b0f280SBarry Smith } 29786719d8e4SJed Brown if (flag || flag_display || flag_draw || flag_contour || flag_threshold) { 29794c30e9fbSJed Brown Mat Bfd; 29804c30e9fbSJed Brown PetscViewer vdraw, vstdout; 2981335efc43SPeter Brune MatColoring coloring; 29824c30e9fbSJed Brown ISColoring iscoloring; 29834c30e9fbSJed Brown MatFDColoring matfdcoloring; 29848434afd1SBarry Smith SNESFunctionFn *func; 29854c30e9fbSJed Brown void *funcctx; 29866719d8e4SJed Brown PetscReal norm1, norm2, normmax; 29874c30e9fbSJed Brown 29889566063dSJacob Faibussowitsch PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &Bfd)); 29899566063dSJacob Faibussowitsch PetscCall(MatColoringCreate(Bfd, &coloring)); 29909566063dSJacob Faibussowitsch PetscCall(MatColoringSetType(coloring, MATCOLORINGSL)); 29919566063dSJacob Faibussowitsch PetscCall(MatColoringSetFromOptions(coloring)); 29929566063dSJacob Faibussowitsch PetscCall(MatColoringApply(coloring, &iscoloring)); 29939566063dSJacob Faibussowitsch PetscCall(MatColoringDestroy(&coloring)); 29949566063dSJacob Faibussowitsch PetscCall(MatFDColoringCreate(Bfd, iscoloring, &matfdcoloring)); 29959566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFromOptions(matfdcoloring)); 29969566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetUp(Bfd, iscoloring, matfdcoloring)); 29979566063dSJacob Faibussowitsch PetscCall(ISColoringDestroy(&iscoloring)); 29984c30e9fbSJed Brown 29994c30e9fbSJed Brown /* This method of getting the function is currently unreliable since it doesn't work for DM local functions. */ 30009566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, &func, &funcctx)); 30019566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFunction(matfdcoloring, (PetscErrorCode(*)(void))func, funcctx)); 30029566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)matfdcoloring, ((PetscObject)snes)->prefix)); 30039566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)matfdcoloring, "coloring_")); 30049566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFromOptions(matfdcoloring)); 30059566063dSJacob Faibussowitsch PetscCall(MatFDColoringApply(Bfd, matfdcoloring, X, snes)); 30069566063dSJacob Faibussowitsch PetscCall(MatFDColoringDestroy(&matfdcoloring)); 30074c30e9fbSJed Brown 30089566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout)); 30094c30e9fbSJed Brown if (flag_draw || flag_contour) { 30109566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Colored Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw)); 30119566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 30120298fd71SBarry Smith } else vdraw = NULL; 30139566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit preconditioning Jacobian\n")); 30149566063dSJacob Faibussowitsch if (flag_display) PetscCall(MatView(B, vstdout)); 30159566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(B, vdraw)); 30169566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Colored Finite difference Jacobian\n")); 30179566063dSJacob Faibussowitsch if (flag_display) PetscCall(MatView(Bfd, vstdout)); 30189566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(Bfd, vdraw)); 30199566063dSJacob Faibussowitsch PetscCall(MatAYPX(Bfd, -1.0, B, SAME_NONZERO_PATTERN)); 30209566063dSJacob Faibussowitsch PetscCall(MatNorm(Bfd, NORM_1, &norm1)); 30219566063dSJacob Faibussowitsch PetscCall(MatNorm(Bfd, NORM_FROBENIUS, &norm2)); 30229566063dSJacob Faibussowitsch PetscCall(MatNorm(Bfd, NORM_MAX, &normmax)); 30239566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian, norm1=%g normFrob=%g normmax=%g\n", (double)norm1, (double)norm2, (double)normmax)); 30249566063dSJacob Faibussowitsch if (flag_display) PetscCall(MatView(Bfd, vstdout)); 30254c30e9fbSJed Brown if (vdraw) { /* Always use contour for the difference */ 30269566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 30279566063dSJacob Faibussowitsch PetscCall(MatView(Bfd, vdraw)); 30289566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(vdraw)); 30294c30e9fbSJed Brown } 30309566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw)); 30316719d8e4SJed Brown 30326719d8e4SJed Brown if (flag_threshold) { 30336719d8e4SJed Brown PetscInt bs, rstart, rend, i; 30349566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(B, &bs)); 30359566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(B, &rstart, &rend)); 30366719d8e4SJed Brown for (i = rstart; i < rend; i++) { 30376719d8e4SJed Brown const PetscScalar *ba, *ca; 30386719d8e4SJed Brown const PetscInt *bj, *cj; 30396719d8e4SJed Brown PetscInt bn, cn, j, maxentrycol = -1, maxdiffcol = -1, maxrdiffcol = -1; 30406719d8e4SJed Brown PetscReal maxentry = 0, maxdiff = 0, maxrdiff = 0; 30419566063dSJacob Faibussowitsch PetscCall(MatGetRow(B, i, &bn, &bj, &ba)); 30429566063dSJacob Faibussowitsch PetscCall(MatGetRow(Bfd, i, &cn, &cj, &ca)); 30435f80ce2aSJacob Faibussowitsch PetscCheck(bn == cn, ((PetscObject)A)->comm, PETSC_ERR_PLIB, "Unexpected different nonzero pattern in -snes_compare_coloring_threshold"); 30446719d8e4SJed Brown for (j = 0; j < bn; j++) { 30456719d8e4SJed Brown PetscReal rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j])); 30466719d8e4SJed Brown if (PetscAbsScalar(ba[j]) > PetscAbs(maxentry)) { 30476719d8e4SJed Brown maxentrycol = bj[j]; 30486719d8e4SJed Brown maxentry = PetscRealPart(ba[j]); 30496719d8e4SJed Brown } 30506719d8e4SJed Brown if (PetscAbsScalar(ca[j]) > PetscAbs(maxdiff)) { 30516719d8e4SJed Brown maxdiffcol = bj[j]; 30526719d8e4SJed Brown maxdiff = PetscRealPart(ca[j]); 30536719d8e4SJed Brown } 30546719d8e4SJed Brown if (rdiff > maxrdiff) { 30556719d8e4SJed Brown maxrdiffcol = bj[j]; 30566719d8e4SJed Brown maxrdiff = rdiff; 30576719d8e4SJed Brown } 30586719d8e4SJed Brown } 30596719d8e4SJed Brown if (maxrdiff > 1) { 306063a3b9bcSJacob 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)); 30616719d8e4SJed Brown for (j = 0; j < bn; j++) { 30626719d8e4SJed Brown PetscReal rdiff; 30636719d8e4SJed Brown rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j])); 306448a46eb9SPierre Jolivet if (rdiff > 1) PetscCall(PetscViewerASCIIPrintf(vstdout, " (%" PetscInt_FMT ",%g:%g)", bj[j], (double)PetscRealPart(ba[j]), (double)PetscRealPart(ca[j]))); 30656719d8e4SJed Brown } 306663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "\n")); 30676719d8e4SJed Brown } 30689566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(B, i, &bn, &bj, &ba)); 30699566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(Bfd, i, &cn, &cj, &ca)); 30706719d8e4SJed Brown } 30716719d8e4SJed Brown } 30729566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&vdraw)); 30739566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bfd)); 30744c30e9fbSJed Brown } 30754c30e9fbSJed Brown } 30763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30779b94acceSBarry Smith } 30789b94acceSBarry Smith 30799b94acceSBarry Smith /*@C 30809b94acceSBarry Smith SNESSetJacobian - Sets the function to compute Jacobian as well as the 3081044dda88SLois Curfman McInnes location to store the matrix. 30829b94acceSBarry Smith 3083c3339decSBarry Smith Logically Collective 3084c7afd0dbSLois Curfman McInnes 30859b94acceSBarry Smith Input Parameters: 3086f6dfbefdSBarry Smith + snes - the `SNES` context 3087e5d3d808SBarry Smith . Amat - the matrix that defines the (approximate) Jacobian 3088dc4c0fb0SBarry Smith . Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`. 30898434afd1SBarry Smith . J - Jacobian evaluation routine (if `NULL` then `SNES` retains any previously set value), see `SNESJacobianFn` for details 3090c7afd0dbSLois Curfman McInnes - ctx - [optional] user-defined context for private data for the 3091dc4c0fb0SBarry Smith Jacobian evaluation routine (may be `NULL`) (if `NULL` then `SNES` retains any previously set value) 3092dc4c0fb0SBarry Smith 3093dc4c0fb0SBarry Smith Level: beginner 30949b94acceSBarry Smith 30959b94acceSBarry Smith Notes: 3096dc4c0fb0SBarry Smith If the `Amat` matrix and `Pmat` matrix are different you must call `MatAssemblyBegin()`/`MatAssemblyEnd()` on 309716913363SBarry Smith each matrix. 309816913363SBarry Smith 3099dc4c0fb0SBarry Smith If you know the operator `Amat` has a null space you can use `MatSetNullSpace()` and `MatSetTransposeNullSpace()` to supply the null 3100dc4c0fb0SBarry Smith space to `Amat` and the `KSP` solvers will automatically use that null space as needed during the solution process. 3101895c21f2SBarry Smith 3102dc4c0fb0SBarry Smith If using `SNESComputeJacobianDefaultColor()` to assemble a Jacobian, the `ctx` argument 3103f6dfbefdSBarry Smith must be a `MatFDColoring`. 3104a8a26c1eSJed Brown 3105c3cc8fd1SJed Brown Other defect-correction schemes can be used by computing a different matrix in place of the Jacobian. One common 3106f6dfbefdSBarry Smith example is to use the "Picard linearization" which only differentiates through the highest order parts of each term using `SNESSetPicard()` 3107c3cc8fd1SJed Brown 31081cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSPSetOperators()`, `SNESSetFunction()`, `MatMFFDComputeJacobian()`, `SNESComputeJacobianDefaultColor()`, `MatStructure`, 31098434afd1SBarry Smith `SNESSetPicard()`, `SNESJacobianFn`, `SNESFunctionFn` 31109b94acceSBarry Smith @*/ 31118434afd1SBarry Smith PetscErrorCode SNESSetJacobian(SNES snes, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx) 3112d71ae5a4SJacob Faibussowitsch { 31136cab3a1bSJed Brown DM dm; 31143a7fca6bSBarry Smith 31153a40ed3dSBarry Smith PetscFunctionBegin; 31160700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3117e5d3d808SBarry Smith if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2); 3118e5d3d808SBarry Smith if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3); 3119e5d3d808SBarry Smith if (Amat) PetscCheckSameComm(snes, 1, Amat, 2); 3120e5d3d808SBarry Smith if (Pmat) PetscCheckSameComm(snes, 1, Pmat, 3); 31219566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 31229566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, J, ctx)); 3123e5d3d808SBarry Smith if (Amat) { 31249566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)Amat)); 31259566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian)); 3126f5af7f23SKarl Rupp 3127e5d3d808SBarry Smith snes->jacobian = Amat; 31283a7fca6bSBarry Smith } 3129e5d3d808SBarry Smith if (Pmat) { 31309566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)Pmat)); 31319566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian_pre)); 3132f5af7f23SKarl Rupp 3133e5d3d808SBarry Smith snes->jacobian_pre = Pmat; 31343a7fca6bSBarry Smith } 31353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 31369b94acceSBarry Smith } 313762fef451SLois Curfman McInnes 3138c2aafc4cSSatish Balay /*@C 3139b4fd4287SBarry Smith SNESGetJacobian - Returns the Jacobian matrix and optionally the user 3140b4fd4287SBarry Smith provided context for evaluating the Jacobian. 3141b4fd4287SBarry Smith 3142420bcc1bSBarry Smith Not Collective, but `Mat` object will be parallel if `SNES` is 3143c7afd0dbSLois Curfman McInnes 3144b4fd4287SBarry Smith Input Parameter: 3145b4fd4287SBarry Smith . snes - the nonlinear solver context 3146b4fd4287SBarry Smith 3147b4fd4287SBarry Smith Output Parameters: 3148dc4c0fb0SBarry Smith + Amat - location to stash (approximate) Jacobian matrix (or `NULL`) 3149dc4c0fb0SBarry Smith . Pmat - location to stash matrix used to compute the preconditioner (or `NULL`) 31508434afd1SBarry Smith . J - location to put Jacobian function (or `NULL`), for calling sequence see `SNESJacobianFn` 3151dc4c0fb0SBarry Smith - ctx - location to stash Jacobian ctx (or `NULL`) 3152fee21e36SBarry Smith 315336851e7fSLois Curfman McInnes Level: advanced 315436851e7fSLois Curfman McInnes 31558434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `Mat`, `SNESSetJacobian()`, `SNESComputeJacobian()`, `SNESJacobianFn`, `SNESGetFunction()` 3156b4fd4287SBarry Smith @*/ 31578434afd1SBarry Smith PetscErrorCode SNESGetJacobian(SNES snes, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx) 3158d71ae5a4SJacob Faibussowitsch { 31596cab3a1bSJed Brown DM dm; 31606cab3a1bSJed Brown 31613a40ed3dSBarry Smith PetscFunctionBegin; 31620700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3163e5d3d808SBarry Smith if (Amat) *Amat = snes->jacobian; 3164e5d3d808SBarry Smith if (Pmat) *Pmat = snes->jacobian_pre; 31659566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 3166800f99ffSJeremy L Thompson PetscCall(DMSNESGetJacobian(dm, J, ctx)); 31673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3168b4fd4287SBarry Smith } 3169b4fd4287SBarry Smith 3170d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetDefaultComputeJacobian(SNES snes) 3171d71ae5a4SJacob Faibussowitsch { 317258b371f3SBarry Smith DM dm; 317358b371f3SBarry Smith DMSNES sdm; 317458b371f3SBarry Smith 317558b371f3SBarry Smith PetscFunctionBegin; 31769566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 31779566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 317858b371f3SBarry Smith if (!sdm->ops->computejacobian && snes->jacobian_pre) { 317958b371f3SBarry Smith DM dm; 318058b371f3SBarry Smith PetscBool isdense, ismf; 318158b371f3SBarry Smith 31829566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 31839566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &isdense, MATSEQDENSE, MATMPIDENSE, MATDENSE, NULL)); 31849566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &ismf, MATMFFD, MATSHELL, NULL)); 318558b371f3SBarry Smith if (isdense) { 31869566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefault, NULL)); 318758b371f3SBarry Smith } else if (!ismf) { 31889566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefaultColor, NULL)); 318958b371f3SBarry Smith } 319058b371f3SBarry Smith } 31913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 319258b371f3SBarry Smith } 319358b371f3SBarry Smith 31949b94acceSBarry Smith /*@ 31959b94acceSBarry Smith SNESSetUp - Sets up the internal data structures for the later use 3196272ac6f2SLois Curfman McInnes of a nonlinear solver. 31979b94acceSBarry Smith 3198c3339decSBarry Smith Collective 3199fee21e36SBarry Smith 32002fe279fdSBarry Smith Input Parameter: 3201f6dfbefdSBarry Smith . snes - the `SNES` context 3202c7afd0dbSLois Curfman McInnes 3203dc4c0fb0SBarry Smith Level: advanced 3204dc4c0fb0SBarry Smith 3205f6dfbefdSBarry Smith Note: 3206f6dfbefdSBarry Smith For basic use of the `SNES` solvers the user need not explicitly call 3207f6dfbefdSBarry Smith `SNESSetUp()`, since these actions will automatically occur during 3208f6dfbefdSBarry Smith the call to `SNESSolve()`. However, if one wishes to control this 3209f6dfbefdSBarry Smith phase separately, `SNESSetUp()` should be called after `SNESCreate()` 3210f6dfbefdSBarry Smith and optional routines of the form SNESSetXXX(), but before `SNESSolve()`. 3211272ac6f2SLois Curfman McInnes 32121cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`, `SNESDestroy()` 32139b94acceSBarry Smith @*/ 3214d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUp(SNES snes) 3215d71ae5a4SJacob Faibussowitsch { 32166cab3a1bSJed Brown DM dm; 3217942e3340SBarry Smith DMSNES sdm; 3218c35f09e5SBarry Smith SNESLineSearch linesearch, pclinesearch; 32196e2a1849SPeter Brune void *lsprectx, *lspostctx; 32209b5c1c08SStefano Zampini PetscBool mf_operator, mf; 32219b5c1c08SStefano Zampini Vec f, fpc; 32229b5c1c08SStefano Zampini void *funcctx; 32239b5c1c08SStefano Zampini void *jacctx, *appctx; 32249b5c1c08SStefano Zampini Mat j, jpre; 32256b2b7091SBarry Smith PetscErrorCode (*precheck)(SNESLineSearch, Vec, Vec, PetscBool *, void *); 32266b2b7091SBarry Smith PetscErrorCode (*postcheck)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *); 32278434afd1SBarry Smith SNESFunctionFn *func; 32288434afd1SBarry Smith SNESJacobianFn *jac; 32293a40ed3dSBarry Smith 32303a40ed3dSBarry Smith PetscFunctionBegin; 32310700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 32323ba16761SJacob Faibussowitsch if (snes->setupcalled) PetscFunctionReturn(PETSC_SUCCESS); 3233fc8bc0e3SRichard Tran Mills PetscCall(PetscLogEventBegin(SNES_SetUp, snes, 0, 0, 0)); 32349b94acceSBarry Smith 323548a46eb9SPierre Jolivet if (!((PetscObject)snes)->type_name) PetscCall(SNESSetType(snes, SNESNEWTONLS)); 323685385478SLisandro Dalcin 32379566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &snes->vec_func, NULL, NULL)); 323858c9b817SLisandro Dalcin 32399566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 32409566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 32419566063dSJacob Faibussowitsch PetscCall(SNESSetDefaultComputeJacobian(snes)); 324258b371f3SBarry Smith 324348a46eb9SPierre Jolivet if (!snes->vec_func) PetscCall(DMCreateGlobalVector(dm, &snes->vec_func)); 3244efd51863SBarry Smith 324548a46eb9SPierre Jolivet if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 3246b710008aSBarry Smith 3247d8d34be6SBarry Smith if (snes->linesearch) { 32489566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 32499566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetFunction(snes->linesearch, SNESComputeFunction)); 3250d8d34be6SBarry Smith } 32519e764e56SPeter Brune 32529b5c1c08SStefano Zampini PetscCall(SNESGetUseMatrixFree(snes, &mf_operator, &mf)); 3253b552625fSStefano Zampini if (snes->npc && snes->npcside == PC_LEFT) { 3254172a4300SPeter Brune snes->mf = PETSC_TRUE; 3255172a4300SPeter Brune snes->mf_operator = PETSC_FALSE; 3256172a4300SPeter Brune } 3257d8f46077SPeter Brune 3258efd4aadfSBarry Smith if (snes->npc) { 32596e2a1849SPeter Brune /* copy the DM over */ 32609566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 32619566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes->npc, dm)); 32626e2a1849SPeter Brune 32639566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &f, &func, &funcctx)); 32649566063dSJacob Faibussowitsch PetscCall(VecDuplicate(f, &fpc)); 32659566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes->npc, fpc, func, funcctx)); 32669566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, &j, &jpre, &jac, &jacctx)); 32679566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes->npc, j, jpre, jac, jacctx)); 32689566063dSJacob Faibussowitsch PetscCall(SNESGetApplicationContext(snes, &appctx)); 32699566063dSJacob Faibussowitsch PetscCall(SNESSetApplicationContext(snes->npc, appctx)); 32709b5c1c08SStefano Zampini PetscCall(SNESSetUseMatrixFree(snes->npc, mf_operator, mf)); 32719566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fpc)); 32726e2a1849SPeter Brune 32736e2a1849SPeter Brune /* copy the function pointers over */ 32749566063dSJacob Faibussowitsch PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)snes->npc)); 32756e2a1849SPeter Brune 32766e2a1849SPeter Brune /* default to 1 iteration */ 32779566063dSJacob Faibussowitsch PetscCall(SNESSetTolerances(snes->npc, 0.0, 0.0, 0.0, 1, snes->npc->max_funcs)); 3278efd4aadfSBarry Smith if (snes->npcside == PC_RIGHT) { 32799566063dSJacob Faibussowitsch PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_FINAL_ONLY)); 3280a9936a0cSPeter Brune } else { 32819566063dSJacob Faibussowitsch PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_NONE)); 3282a9936a0cSPeter Brune } 32839566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes->npc)); 32846e2a1849SPeter Brune 32856e2a1849SPeter Brune /* copy the line search context over */ 3286d8d34be6SBarry Smith if (snes->linesearch && snes->npc->linesearch) { 32879566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &linesearch)); 32889566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes->npc, &pclinesearch)); 32899566063dSJacob Faibussowitsch PetscCall(SNESLineSearchGetPreCheck(linesearch, &precheck, &lsprectx)); 32909566063dSJacob Faibussowitsch PetscCall(SNESLineSearchGetPostCheck(linesearch, &postcheck, &lspostctx)); 32919566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetPreCheck(pclinesearch, precheck, lsprectx)); 32929566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetPostCheck(pclinesearch, postcheck, lspostctx)); 32939566063dSJacob Faibussowitsch PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch)); 32946e2a1849SPeter Brune } 3295d8d34be6SBarry Smith } 32961baa6e33SBarry Smith if (snes->mf) PetscCall(SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version)); 32979927e4dfSBarry Smith if (snes->ops->usercompute && !snes->user) PetscCallBack("SNES callback compute application context", (*snes->ops->usercompute)(snes, (void **)&snes->user)); 32986e2a1849SPeter Brune 329937ec4e1aSPeter Brune snes->jac_iter = 0; 330037ec4e1aSPeter Brune snes->pre_iter = 0; 330137ec4e1aSPeter Brune 3302dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, setup); 330358c9b817SLisandro Dalcin 33049566063dSJacob Faibussowitsch PetscCall(SNESSetDefaultComputeJacobian(snes)); 330558b371f3SBarry Smith 3306b552625fSStefano Zampini if (snes->npc && snes->npcside == PC_LEFT) { 33076c67d002SPeter Brune if (snes->functype == SNES_FUNCTION_PRECONDITIONED) { 3308d8d34be6SBarry Smith if (snes->linesearch) { 33099566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &linesearch)); 33109566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunctionDefaultNPC)); 33116c67d002SPeter Brune } 33126c67d002SPeter Brune } 3313d8d34be6SBarry Smith } 3314fc8bc0e3SRichard Tran Mills PetscCall(PetscLogEventEnd(SNES_SetUp, snes, 0, 0, 0)); 33157aaed0d8SBarry Smith snes->setupcalled = PETSC_TRUE; 33163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 33179b94acceSBarry Smith } 33189b94acceSBarry Smith 331937596af1SLisandro Dalcin /*@ 3320f6dfbefdSBarry Smith SNESReset - Resets a `SNES` context to the snessetupcalled = 0 state and removes any allocated `Vec`s and `Mat`s 332137596af1SLisandro Dalcin 3322c3339decSBarry Smith Collective 332337596af1SLisandro Dalcin 332437596af1SLisandro Dalcin Input Parameter: 3325f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 332637596af1SLisandro Dalcin 3327d25893d9SBarry Smith Level: intermediate 3328d25893d9SBarry Smith 332995452b02SPatrick Sanan Notes: 3330f6dfbefdSBarry Smith Call this if you wish to reuse a `SNES` but with different size vectors 333137596af1SLisandro Dalcin 3332f6dfbefdSBarry Smith Also calls the application context destroy routine set with `SNESSetComputeApplicationContext()` 3333f6dfbefdSBarry Smith 33341cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESDestroy()`, `SNESCreate()`, `SNESSetUp()`, `SNESSolve()` 333537596af1SLisandro Dalcin @*/ 3336d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESReset(SNES snes) 3337d71ae5a4SJacob Faibussowitsch { 333837596af1SLisandro Dalcin PetscFunctionBegin; 333937596af1SLisandro Dalcin PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3340d25893d9SBarry Smith if (snes->ops->userdestroy && snes->user) { 33419927e4dfSBarry Smith PetscCallBack("SNES callback destroy application context", (*snes->ops->userdestroy)((void **)&snes->user)); 33420298fd71SBarry Smith snes->user = NULL; 3343d25893d9SBarry Smith } 33441baa6e33SBarry Smith if (snes->npc) PetscCall(SNESReset(snes->npc)); 33458a23116dSBarry Smith 3346dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, reset); 33471baa6e33SBarry Smith if (snes->ksp) PetscCall(KSPReset(snes->ksp)); 33489e764e56SPeter Brune 33491baa6e33SBarry Smith if (snes->linesearch) PetscCall(SNESLineSearchReset(snes->linesearch)); 33509e764e56SPeter Brune 33519566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_rhs)); 33529566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol)); 33539566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol_update)); 33549566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_func)); 33559566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian)); 33569566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian_pre)); 33579566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->picard)); 33589566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(snes->nwork, &snes->work)); 33599566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(snes->nvwork, &snes->vwork)); 3360f5af7f23SKarl Rupp 336140fdac6aSLawrence Mitchell snes->alwayscomputesfinalresidual = PETSC_FALSE; 336240fdac6aSLawrence Mitchell 336337596af1SLisandro Dalcin snes->nwork = snes->nvwork = 0; 336437596af1SLisandro Dalcin snes->setupcalled = PETSC_FALSE; 33653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 336637596af1SLisandro Dalcin } 336737596af1SLisandro Dalcin 336852baeb72SSatish Balay /*@ 3369420bcc1bSBarry Smith SNESConvergedReasonViewCancel - Clears all the reason view functions for a `SNES` object provided with `SNESConvergedReasonViewSet()` 3370c4421ceaSFande Kong 3371c3339decSBarry Smith Collective 3372c4421ceaSFande Kong 3373c4421ceaSFande Kong Input Parameter: 3374f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 3375c4421ceaSFande Kong 3376c4421ceaSFande Kong Level: intermediate 3377c4421ceaSFande Kong 3378420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESReset()`, `SNESConvergedReasonViewSet()` 3379c4421ceaSFande Kong @*/ 3380d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewCancel(SNES snes) 3381d71ae5a4SJacob Faibussowitsch { 3382c4421ceaSFande Kong PetscInt i; 3383c4421ceaSFande Kong 3384c4421ceaSFande Kong PetscFunctionBegin; 3385c4421ceaSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3386c4421ceaSFande Kong for (i = 0; i < snes->numberreasonviews; i++) { 338748a46eb9SPierre Jolivet if (snes->reasonviewdestroy[i]) PetscCall((*snes->reasonviewdestroy[i])(&snes->reasonviewcontext[i])); 3388c4421ceaSFande Kong } 3389c4421ceaSFande Kong snes->numberreasonviews = 0; 33903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3391c4421ceaSFande Kong } 3392c4421ceaSFande Kong 33931fb7b255SJunchao Zhang /*@C 33949b94acceSBarry Smith SNESDestroy - Destroys the nonlinear solver context that was created 3395f6dfbefdSBarry Smith with `SNESCreate()`. 33969b94acceSBarry Smith 3397c3339decSBarry Smith Collective 3398c7afd0dbSLois Curfman McInnes 33999b94acceSBarry Smith Input Parameter: 3400f6dfbefdSBarry Smith . snes - the `SNES` context 34019b94acceSBarry Smith 340236851e7fSLois Curfman McInnes Level: beginner 340336851e7fSLois Curfman McInnes 34041cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()` 34059b94acceSBarry Smith @*/ 3406d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESDestroy(SNES *snes) 3407d71ae5a4SJacob Faibussowitsch { 34083a40ed3dSBarry Smith PetscFunctionBegin; 34093ba16761SJacob Faibussowitsch if (!*snes) PetscFunctionReturn(PETSC_SUCCESS); 3410f4f49eeaSPierre Jolivet PetscValidHeaderSpecific(*snes, SNES_CLASSID, 1); 3411f4f49eeaSPierre Jolivet if (--((PetscObject)*snes)->refct > 0) { 34129371c9d4SSatish Balay *snes = NULL; 34133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 34149371c9d4SSatish Balay } 3415d4bb536fSBarry Smith 3416f4f49eeaSPierre Jolivet PetscCall(SNESReset(*snes)); 34179566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&(*snes)->npc)); 34186b8b9a38SLisandro Dalcin 3419e04113cfSBarry Smith /* if memory was published with SAWs then destroy it */ 34209566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsViewOff((PetscObject)*snes)); 3421f4f49eeaSPierre Jolivet PetscTryTypeMethod(*snes, destroy); 34226d4c513bSLisandro Dalcin 34239566063dSJacob Faibussowitsch if ((*snes)->dm) PetscCall(DMCoarsenHookRemove((*snes)->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, *snes)); 34249566063dSJacob Faibussowitsch PetscCall(DMDestroy(&(*snes)->dm)); 34259566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&(*snes)->ksp)); 34269566063dSJacob Faibussowitsch PetscCall(SNESLineSearchDestroy(&(*snes)->linesearch)); 34276b8b9a38SLisandro Dalcin 34289566063dSJacob Faibussowitsch PetscCall(PetscFree((*snes)->kspconvctx)); 342948a46eb9SPierre Jolivet if ((*snes)->ops->convergeddestroy) PetscCall((*(*snes)->ops->convergeddestroy)((*snes)->cnvP)); 343048a46eb9SPierre Jolivet if ((*snes)->conv_hist_alloc) PetscCall(PetscFree2((*snes)->conv_hist, (*snes)->conv_hist_its)); 3431f4f49eeaSPierre Jolivet PetscCall(SNESMonitorCancel(*snes)); 3432f4f49eeaSPierre Jolivet PetscCall(SNESConvergedReasonViewCancel(*snes)); 34339566063dSJacob Faibussowitsch PetscCall(PetscHeaderDestroy(snes)); 34343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 34359b94acceSBarry Smith } 34369b94acceSBarry Smith 34379b94acceSBarry Smith /* ----------- Routines to set solver parameters ---------- */ 34389b94acceSBarry Smith 3439a8054027SBarry Smith /*@ 3440a8054027SBarry Smith SNESSetLagPreconditioner - Determines when the preconditioner is rebuilt in the nonlinear solve. 3441a8054027SBarry Smith 3442c3339decSBarry Smith Logically Collective 3443a8054027SBarry Smith 3444a8054027SBarry Smith Input Parameters: 3445f6dfbefdSBarry Smith + snes - the `SNES` context 3446d8e291bfSBarry Smith - lag - 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time 34473b4f5425SBarry Smith the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that 3448a8054027SBarry Smith 3449a8054027SBarry Smith Options Database Keys: 3450420bcc1bSBarry Smith + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple `SNESSolve()` 34513d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 3452420bcc1bSBarry Smith . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple `SNESSolve()` 34533d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 3454a8054027SBarry Smith 3455dc4c0fb0SBarry Smith Level: intermediate 3456dc4c0fb0SBarry Smith 3457420bcc1bSBarry Smith Notes: 3458a8054027SBarry Smith The default is 1 3459420bcc1bSBarry Smith 3460f6dfbefdSBarry Smith The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagPreconditionerPersists()` was called 3461d8e291bfSBarry Smith 3462f6dfbefdSBarry Smith `SNESSetLagPreconditionerPersists()` allows using the same uniform lagging (for example every second linear solve) across multiple nonlinear solves. 3463a8054027SBarry Smith 34641cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetLagPreconditionerPersists()`, 3465f6dfbefdSBarry Smith `SNESSetLagJacobianPersists()`, `SNES`, `SNESSolve()` 3466a8054027SBarry Smith @*/ 3467d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditioner(SNES snes, PetscInt lag) 3468d71ae5a4SJacob Faibussowitsch { 3469a8054027SBarry Smith PetscFunctionBegin; 34700700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 34715f80ce2aSJacob Faibussowitsch PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater"); 34725f80ce2aSJacob Faibussowitsch PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0"); 3473c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, lag, 2); 3474a8054027SBarry Smith snes->lagpreconditioner = lag; 34753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3476a8054027SBarry Smith } 3477a8054027SBarry Smith 3478efd51863SBarry Smith /*@ 3479f6dfbefdSBarry Smith SNESSetGridSequence - sets the number of steps of grid sequencing that `SNES` will do 3480efd51863SBarry Smith 3481c3339decSBarry Smith Logically Collective 3482efd51863SBarry Smith 3483efd51863SBarry Smith Input Parameters: 3484f6dfbefdSBarry Smith + snes - the `SNES` context 3485efd51863SBarry Smith - steps - the number of refinements to do, defaults to 0 3486efd51863SBarry Smith 3487f6dfbefdSBarry Smith Options Database Key: 348867b8a455SSatish Balay . -snes_grid_sequence <steps> - Use grid sequencing to generate initial guess 3489efd51863SBarry Smith 3490efd51863SBarry Smith Level: intermediate 3491efd51863SBarry Smith 3492f6dfbefdSBarry Smith Note: 3493f6dfbefdSBarry Smith Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing. 3494c0df2a02SJed Brown 3495420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetGridSequence()`, 3496420bcc1bSBarry Smith `SNESetDM()` 3497efd51863SBarry Smith @*/ 3498d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetGridSequence(SNES snes, PetscInt steps) 3499d71ae5a4SJacob Faibussowitsch { 3500efd51863SBarry Smith PetscFunctionBegin; 3501efd51863SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3502efd51863SBarry Smith PetscValidLogicalCollectiveInt(snes, steps, 2); 3503efd51863SBarry Smith snes->gridsequence = steps; 35043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3505efd51863SBarry Smith } 3506efd51863SBarry Smith 3507fa19ca70SBarry Smith /*@ 3508f6dfbefdSBarry Smith SNESGetGridSequence - gets the number of steps of grid sequencing that `SNES` will do 3509fa19ca70SBarry Smith 3510c3339decSBarry Smith Logically Collective 3511fa19ca70SBarry Smith 3512fa19ca70SBarry Smith Input Parameter: 3513f6dfbefdSBarry Smith . snes - the `SNES` context 3514fa19ca70SBarry Smith 3515fa19ca70SBarry Smith Output Parameter: 3516fa19ca70SBarry Smith . steps - the number of refinements to do, defaults to 0 3517fa19ca70SBarry Smith 3518fa19ca70SBarry Smith Level: intermediate 3519fa19ca70SBarry Smith 35201cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetGridSequence()` 3521fa19ca70SBarry Smith @*/ 3522d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetGridSequence(SNES snes, PetscInt *steps) 3523d71ae5a4SJacob Faibussowitsch { 3524fa19ca70SBarry Smith PetscFunctionBegin; 3525fa19ca70SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3526fa19ca70SBarry Smith *steps = snes->gridsequence; 35273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3528fa19ca70SBarry Smith } 3529fa19ca70SBarry Smith 3530a8054027SBarry Smith /*@ 3531f6dfbefdSBarry Smith SNESGetLagPreconditioner - Return how often the preconditioner is rebuilt 3532a8054027SBarry Smith 35333f9fe445SBarry Smith Not Collective 3534a8054027SBarry Smith 3535a8054027SBarry Smith Input Parameter: 3536f6dfbefdSBarry Smith . snes - the `SNES` context 3537a8054027SBarry Smith 3538a8054027SBarry Smith Output Parameter: 3539a8054027SBarry 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 35403b4f5425SBarry Smith the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that 3541a8054027SBarry Smith 3542dc4c0fb0SBarry Smith Level: intermediate 3543dc4c0fb0SBarry Smith 3544a8054027SBarry Smith Notes: 3545a8054027SBarry Smith The default is 1 3546f6dfbefdSBarry Smith 3547a8054027SBarry Smith The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 3548a8054027SBarry Smith 35491cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3550a8054027SBarry Smith @*/ 3551d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagPreconditioner(SNES snes, PetscInt *lag) 3552d71ae5a4SJacob Faibussowitsch { 3553a8054027SBarry Smith PetscFunctionBegin; 35540700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3555a8054027SBarry Smith *lag = snes->lagpreconditioner; 35563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3557a8054027SBarry Smith } 3558a8054027SBarry Smith 3559e35cf81dSBarry Smith /*@ 3560f6dfbefdSBarry Smith SNESSetLagJacobian - Set when the Jacobian is rebuilt in the nonlinear solve. See `SNESSetLagPreconditioner()` for determining how 3561e35cf81dSBarry Smith often the preconditioner is rebuilt. 3562e35cf81dSBarry Smith 3563c3339decSBarry Smith Logically Collective 3564e35cf81dSBarry Smith 3565e35cf81dSBarry Smith Input Parameters: 3566f6dfbefdSBarry Smith + snes - the `SNES` context 3567e35cf81dSBarry 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 3568fe3ffe1eSBarry Smith the Jacobian is built etc. -2 means rebuild at next chance but then never again 3569e35cf81dSBarry Smith 3570e35cf81dSBarry Smith Options Database Keys: 357179a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 35723d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 357379a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 35743d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag. 3575e35cf81dSBarry Smith 3576dc4c0fb0SBarry Smith Level: intermediate 3577dc4c0fb0SBarry Smith 3578e35cf81dSBarry Smith Notes: 3579e35cf81dSBarry Smith The default is 1 3580f6dfbefdSBarry Smith 3581e35cf81dSBarry Smith The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 3582f6dfbefdSBarry Smith 3583fe3ffe1eSBarry 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 3584fe3ffe1eSBarry Smith at the next Newton step but never again (unless it is reset to another value) 3585e35cf81dSBarry Smith 35861cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagPreconditioner()`, `SNESGetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3587e35cf81dSBarry Smith @*/ 3588d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobian(SNES snes, PetscInt lag) 3589d71ae5a4SJacob Faibussowitsch { 3590e35cf81dSBarry Smith PetscFunctionBegin; 35910700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 35925f80ce2aSJacob Faibussowitsch PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater"); 35935f80ce2aSJacob Faibussowitsch PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0"); 3594c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, lag, 2); 3595e35cf81dSBarry Smith snes->lagjacobian = lag; 35963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3597e35cf81dSBarry Smith } 3598e35cf81dSBarry Smith 3599e35cf81dSBarry Smith /*@ 3600f6dfbefdSBarry Smith SNESGetLagJacobian - Get how often the Jacobian is rebuilt. See `SNESGetLagPreconditioner()` to determine when the preconditioner is rebuilt 3601e35cf81dSBarry Smith 36023f9fe445SBarry Smith Not Collective 3603e35cf81dSBarry Smith 3604e35cf81dSBarry Smith Input Parameter: 3605f6dfbefdSBarry Smith . snes - the `SNES` context 3606e35cf81dSBarry Smith 3607e35cf81dSBarry Smith Output Parameter: 3608e35cf81dSBarry 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 3609e35cf81dSBarry Smith the Jacobian is built etc. 3610e35cf81dSBarry Smith 3611dc4c0fb0SBarry Smith Level: intermediate 3612dc4c0fb0SBarry Smith 3613e35cf81dSBarry Smith Notes: 3614e35cf81dSBarry Smith The default is 1 3615f6dfbefdSBarry Smith 3616f6dfbefdSBarry Smith The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagJacobianPersists()` was called. 3617e35cf81dSBarry Smith 36181cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetLagJacobian()`, `SNESSetLagPreconditioner()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3619e35cf81dSBarry Smith 3620e35cf81dSBarry Smith @*/ 3621d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagJacobian(SNES snes, PetscInt *lag) 3622d71ae5a4SJacob Faibussowitsch { 3623e35cf81dSBarry Smith PetscFunctionBegin; 36240700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3625e35cf81dSBarry Smith *lag = snes->lagjacobian; 36263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3627e35cf81dSBarry Smith } 3628e35cf81dSBarry Smith 362937ec4e1aSPeter Brune /*@ 3630f6dfbefdSBarry Smith SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple nonlinear solves 363137ec4e1aSPeter Brune 3632c3339decSBarry Smith Logically collective 363337ec4e1aSPeter Brune 3634d8d19677SJose E. Roman Input Parameters: 3635f6dfbefdSBarry Smith + snes - the `SNES` context 36369d7e2deaSPeter Brune - flg - jacobian lagging persists if true 363737ec4e1aSPeter Brune 363837ec4e1aSPeter Brune Options Database Keys: 363979a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 36403d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 364179a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 36423d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 36433d5a8a6aSBarry Smith 3644dc4c0fb0SBarry Smith Level: advanced 3645dc4c0fb0SBarry Smith 364695452b02SPatrick Sanan Notes: 3647420bcc1bSBarry Smith Normally when `SNESSetLagJacobian()` is used, the Jacobian is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior 3648f6dfbefdSBarry Smith 364995452b02SPatrick Sanan This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by 365037ec4e1aSPeter Brune several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several 365137ec4e1aSPeter Brune timesteps may present huge efficiency gains. 365237ec4e1aSPeter Brune 365342747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditionerPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()` 365437ec4e1aSPeter Brune @*/ 3655d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobianPersists(SNES snes, PetscBool flg) 3656d71ae5a4SJacob Faibussowitsch { 365737ec4e1aSPeter Brune PetscFunctionBegin; 365837ec4e1aSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 365937ec4e1aSPeter Brune PetscValidLogicalCollectiveBool(snes, flg, 2); 366037ec4e1aSPeter Brune snes->lagjac_persist = flg; 36613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 366237ec4e1aSPeter Brune } 366337ec4e1aSPeter Brune 366437ec4e1aSPeter Brune /*@ 3665d8e291bfSBarry Smith SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple nonlinear solves 366637ec4e1aSPeter Brune 3667c3339decSBarry Smith Logically Collective 366837ec4e1aSPeter Brune 3669d8d19677SJose E. Roman Input Parameters: 3670f6dfbefdSBarry Smith + snes - the `SNES` context 36719d7e2deaSPeter Brune - flg - preconditioner lagging persists if true 367237ec4e1aSPeter Brune 367337ec4e1aSPeter Brune Options Database Keys: 367479a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 36753d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 367679a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 36773d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 367837ec4e1aSPeter Brune 3679dc4c0fb0SBarry Smith Level: developer 3680dc4c0fb0SBarry Smith 368195452b02SPatrick Sanan Notes: 3682420bcc1bSBarry Smith Normally when `SNESSetLagPreconditioner()` is used, the preconditioner is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior 3683f6dfbefdSBarry Smith 368495452b02SPatrick Sanan This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale 368537ec4e1aSPeter Brune by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over 368637ec4e1aSPeter Brune several timesteps may present huge efficiency gains. 368737ec4e1aSPeter Brune 36881cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobianPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagPreconditioner()` 368937ec4e1aSPeter Brune @*/ 3690d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes, PetscBool flg) 3691d71ae5a4SJacob Faibussowitsch { 369237ec4e1aSPeter Brune PetscFunctionBegin; 369337ec4e1aSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 369437ec4e1aSPeter Brune PetscValidLogicalCollectiveBool(snes, flg, 2); 369537ec4e1aSPeter Brune snes->lagpre_persist = flg; 36963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 369737ec4e1aSPeter Brune } 369837ec4e1aSPeter Brune 36999b94acceSBarry Smith /*@ 3700f6dfbefdSBarry Smith SNESSetForceIteration - force `SNESSolve()` to take at least one iteration regardless of the initial residual norm 3701be5caee7SBarry Smith 3702c3339decSBarry Smith Logically Collective 3703be5caee7SBarry Smith 3704be5caee7SBarry Smith Input Parameters: 3705f6dfbefdSBarry Smith + snes - the `SNES` context 3706f6dfbefdSBarry Smith - force - `PETSC_TRUE` require at least one iteration 3707be5caee7SBarry Smith 3708f6dfbefdSBarry Smith Options Database Key: 3709be5caee7SBarry Smith . -snes_force_iteration <force> - Sets forcing an iteration 3710be5caee7SBarry Smith 3711dc4c0fb0SBarry Smith Level: intermediate 3712dc4c0fb0SBarry Smith 3713f6dfbefdSBarry Smith Note: 3714f6dfbefdSBarry Smith This is used sometimes with `TS` to prevent `TS` from detecting a false steady state solution 3715be5caee7SBarry Smith 37161cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `TS`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()` 3717be5caee7SBarry Smith @*/ 3718d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetForceIteration(SNES snes, PetscBool force) 3719d71ae5a4SJacob Faibussowitsch { 3720be5caee7SBarry Smith PetscFunctionBegin; 3721be5caee7SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3722be5caee7SBarry Smith snes->forceiteration = force; 37233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3724be5caee7SBarry Smith } 3725be5caee7SBarry Smith 372685216dc7SFande Kong /*@ 3727f6dfbefdSBarry Smith SNESGetForceIteration - Check whether or not `SNESSolve()` take at least one iteration regardless of the initial residual norm 372885216dc7SFande Kong 3729c3339decSBarry Smith Logically Collective 373085216dc7SFande Kong 37312fe279fdSBarry Smith Input Parameter: 3732f6dfbefdSBarry Smith . snes - the `SNES` context 373385216dc7SFande Kong 373485216dc7SFande Kong Output Parameter: 3735dc4c0fb0SBarry Smith . force - `PETSC_TRUE` requires at least one iteration. 373685216dc7SFande Kong 373706dd6b0eSSatish Balay Level: intermediate 373806dd6b0eSSatish Balay 37391cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetForceIteration()`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()` 374085216dc7SFande Kong @*/ 3741d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetForceIteration(SNES snes, PetscBool *force) 3742d71ae5a4SJacob Faibussowitsch { 374385216dc7SFande Kong PetscFunctionBegin; 374485216dc7SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 374585216dc7SFande Kong *force = snes->forceiteration; 37463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 374785216dc7SFande Kong } 3748be5caee7SBarry Smith 3749be5caee7SBarry Smith /*@ 3750f6dfbefdSBarry Smith SNESSetTolerances - Sets `SNES` various parameters used in convergence tests. 37519b94acceSBarry Smith 3752c3339decSBarry Smith Logically Collective 3753c7afd0dbSLois Curfman McInnes 37549b94acceSBarry Smith Input Parameters: 3755f6dfbefdSBarry Smith + snes - the `SNES` context 375670441072SBarry Smith . abstol - absolute convergence tolerance 375733174efeSLois Curfman McInnes . rtol - relative convergence tolerance 37585358d0d4SBarry Smith . stol - convergence tolerance in terms of the norm of the change in the solution between steps, || delta x || < stol*|| x || 3759f6dfbefdSBarry Smith . maxit - maximum number of iterations, default 50. 3760f6dfbefdSBarry Smith - maxf - maximum number of function evaluations (-1 indicates no limit), default 1000 3761fee21e36SBarry Smith 376233174efeSLois Curfman McInnes Options Database Keys: 376370441072SBarry Smith + -snes_atol <abstol> - Sets abstol 3764c7afd0dbSLois Curfman McInnes . -snes_rtol <rtol> - Sets rtol 3765c7afd0dbSLois Curfman McInnes . -snes_stol <stol> - Sets stol 3766c7afd0dbSLois Curfman McInnes . -snes_max_it <maxit> - Sets maxit 3767c7afd0dbSLois Curfman McInnes - -snes_max_funcs <maxf> - Sets maxf 37689b94acceSBarry Smith 376936851e7fSLois Curfman McInnes Level: intermediate 377036851e7fSLois Curfman McInnes 377100677de2SStefano Zampini .seealso: [](ch_snes), `SNESSolve()`, `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()`, `SNESSetForceIteration()` 37729b94acceSBarry Smith @*/ 3773d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTolerances(SNES snes, PetscReal abstol, PetscReal rtol, PetscReal stol, PetscInt maxit, PetscInt maxf) 3774d71ae5a4SJacob Faibussowitsch { 37753a40ed3dSBarry Smith PetscFunctionBegin; 37760700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3777c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, abstol, 2); 3778c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, rtol, 3); 3779c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, stol, 4); 3780c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, maxit, 5); 3781c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, maxf, 6); 3782c5eb9154SBarry Smith 378313bcc0bdSJacob Faibussowitsch if (abstol != (PetscReal)PETSC_DEFAULT) { 37845f80ce2aSJacob Faibussowitsch PetscCheck(abstol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)abstol); 3785ab54825eSJed Brown snes->abstol = abstol; 3786ab54825eSJed Brown } 378713bcc0bdSJacob Faibussowitsch if (rtol != (PetscReal)PETSC_DEFAULT) { 37885f80ce2aSJacob 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); 3789ab54825eSJed Brown snes->rtol = rtol; 3790ab54825eSJed Brown } 379113bcc0bdSJacob Faibussowitsch if (stol != (PetscReal)PETSC_DEFAULT) { 37925f80ce2aSJacob Faibussowitsch PetscCheck(stol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Step tolerance %g must be non-negative", (double)stol); 3793c60f73f4SPeter Brune snes->stol = stol; 3794ab54825eSJed Brown } 3795ab54825eSJed Brown if (maxit != PETSC_DEFAULT) { 379663a3b9bcSJacob Faibussowitsch PetscCheck(maxit >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", maxit); 3797ab54825eSJed Brown snes->max_its = maxit; 3798ab54825eSJed Brown } 3799ab54825eSJed Brown if (maxf != PETSC_DEFAULT) { 380063a3b9bcSJacob Faibussowitsch PetscCheck(maxf >= -1, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations %" PetscInt_FMT " must be -1 or nonnegative", maxf); 3801ab54825eSJed Brown snes->max_funcs = maxf; 3802ab54825eSJed Brown } 380388976e71SPeter Brune snes->tolerancesset = PETSC_TRUE; 38043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 38059b94acceSBarry Smith } 38069b94acceSBarry Smith 3807e4d06f11SPatrick Farrell /*@ 3808f6dfbefdSBarry Smith SNESSetDivergenceTolerance - Sets the divergence tolerance used for the `SNES` divergence test. 3809e4d06f11SPatrick Farrell 3810c3339decSBarry Smith Logically Collective 3811e4d06f11SPatrick Farrell 3812e4d06f11SPatrick Farrell Input Parameters: 3813f6dfbefdSBarry Smith + snes - the `SNES` context 3814f6dfbefdSBarry Smith - divtol - the divergence tolerance. Use -1 to deactivate the test, default is 1e4 3815e4d06f11SPatrick Farrell 3816f6dfbefdSBarry Smith Options Database Key: 3817dc4c0fb0SBarry Smith . -snes_divergence_tolerance <divtol> - Sets `divtol` 3818e4d06f11SPatrick Farrell 3819e4d06f11SPatrick Farrell Level: intermediate 3820e4d06f11SPatrick Farrell 38211cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetTolerances()`, `SNESGetDivergenceTolerance` 3822e4d06f11SPatrick Farrell @*/ 3823d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDivergenceTolerance(SNES snes, PetscReal divtol) 3824d71ae5a4SJacob Faibussowitsch { 3825e4d06f11SPatrick Farrell PetscFunctionBegin; 3826e4d06f11SPatrick Farrell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3827e4d06f11SPatrick Farrell PetscValidLogicalCollectiveReal(snes, divtol, 2); 3828e4d06f11SPatrick Farrell 382913bcc0bdSJacob Faibussowitsch if (divtol != (PetscReal)PETSC_DEFAULT) { 3830e4d06f11SPatrick Farrell snes->divtol = divtol; 38319371c9d4SSatish Balay } else { 3832e4d06f11SPatrick Farrell snes->divtol = 1.0e4; 3833e4d06f11SPatrick Farrell } 38343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3835e4d06f11SPatrick Farrell } 3836e4d06f11SPatrick Farrell 38379b94acceSBarry Smith /*@ 383833174efeSLois Curfman McInnes SNESGetTolerances - Gets various parameters used in convergence tests. 383933174efeSLois Curfman McInnes 3840c7afd0dbSLois Curfman McInnes Not Collective 3841c7afd0dbSLois Curfman McInnes 384233174efeSLois Curfman McInnes Input Parameters: 3843f6dfbefdSBarry Smith + snes - the `SNES` context 384485385478SLisandro Dalcin . atol - absolute convergence tolerance 384533174efeSLois Curfman McInnes . rtol - relative convergence tolerance 384633174efeSLois Curfman McInnes . stol - convergence tolerance in terms of the norm 384733174efeSLois Curfman McInnes of the change in the solution between steps 384833174efeSLois Curfman McInnes . maxit - maximum number of iterations 3849c7afd0dbSLois Curfman McInnes - maxf - maximum number of function evaluations 3850fee21e36SBarry Smith 385136851e7fSLois Curfman McInnes Level: intermediate 385236851e7fSLois Curfman McInnes 3853dc4c0fb0SBarry Smith Note: 3854dc4c0fb0SBarry Smith The user can specify `NULL` for any parameter that is not needed. 3855dc4c0fb0SBarry Smith 38561cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTolerances()` 385733174efeSLois Curfman McInnes @*/ 3858d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetTolerances(SNES snes, PetscReal *atol, PetscReal *rtol, PetscReal *stol, PetscInt *maxit, PetscInt *maxf) 3859d71ae5a4SJacob Faibussowitsch { 38603a40ed3dSBarry Smith PetscFunctionBegin; 38610700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 386285385478SLisandro Dalcin if (atol) *atol = snes->abstol; 386333174efeSLois Curfman McInnes if (rtol) *rtol = snes->rtol; 3864c60f73f4SPeter Brune if (stol) *stol = snes->stol; 386533174efeSLois Curfman McInnes if (maxit) *maxit = snes->max_its; 386633174efeSLois Curfman McInnes if (maxf) *maxf = snes->max_funcs; 38673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 386833174efeSLois Curfman McInnes } 386933174efeSLois Curfman McInnes 3870e4d06f11SPatrick Farrell /*@ 3871e4d06f11SPatrick Farrell SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test. 3872e4d06f11SPatrick Farrell 3873e4d06f11SPatrick Farrell Not Collective 3874e4d06f11SPatrick Farrell 3875e4d06f11SPatrick Farrell Input Parameters: 3876f6dfbefdSBarry Smith + snes - the `SNES` context 3877e4d06f11SPatrick Farrell - divtol - divergence tolerance 3878e4d06f11SPatrick Farrell 3879e4d06f11SPatrick Farrell Level: intermediate 3880e4d06f11SPatrick Farrell 38811cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetDivergenceTolerance()` 3882e4d06f11SPatrick Farrell @*/ 3883d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDivergenceTolerance(SNES snes, PetscReal *divtol) 3884d71ae5a4SJacob Faibussowitsch { 3885e4d06f11SPatrick Farrell PetscFunctionBegin; 3886e4d06f11SPatrick Farrell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3887e4d06f11SPatrick Farrell if (divtol) *divtol = snes->divtol; 38883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3889e4d06f11SPatrick Farrell } 3890e4d06f11SPatrick Farrell 389133174efeSLois Curfman McInnes /*@ 38929b94acceSBarry Smith SNESSetTrustRegionTolerance - Sets the trust region parameter tolerance. 38939b94acceSBarry Smith 3894c3339decSBarry Smith Logically Collective 3895fee21e36SBarry Smith 3896c7afd0dbSLois Curfman McInnes Input Parameters: 3897f6dfbefdSBarry Smith + snes - the `SNES` context 3898c7afd0dbSLois Curfman McInnes - tol - tolerance 3899c7afd0dbSLois Curfman McInnes 39009b94acceSBarry Smith Options Database Key: 39014a221d59SStefano Zampini . -snes_tr_tol <tol> - Sets tol 39029b94acceSBarry Smith 390336851e7fSLois Curfman McInnes Level: intermediate 390436851e7fSLois Curfman McInnes 39059bcc50f1SBarry Smith Developer Note: 39069bcc50f1SBarry Smith Should be SNESTrustRegionSetTolerance() 39079bcc50f1SBarry Smith 39081cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNEWTONTR`, `SNESSetTolerances()` 39099b94acceSBarry Smith @*/ 3910d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTrustRegionTolerance(SNES snes, PetscReal tol) 3911d71ae5a4SJacob Faibussowitsch { 39123a40ed3dSBarry Smith PetscFunctionBegin; 39130700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3914c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, tol, 2); 39159b94acceSBarry Smith snes->deltatol = tol; 39163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 39179b94acceSBarry Smith } 39189b94acceSBarry Smith 39196ba87a44SLisandro Dalcin PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *); 39206ba87a44SLisandro Dalcin 3921d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorLGRange(SNES snes, PetscInt n, PetscReal rnorm, void *monctx) 3922d71ae5a4SJacob Faibussowitsch { 3923b271bb04SBarry Smith PetscDrawLG lg; 3924b271bb04SBarry Smith PetscReal x, y, per; 3925b271bb04SBarry Smith PetscViewer v = (PetscViewer)monctx; 3926b271bb04SBarry Smith static PetscReal prev; /* should be in the context */ 3927b271bb04SBarry Smith PetscDraw draw; 3928b271bb04SBarry Smith 3929459f5d12SBarry Smith PetscFunctionBegin; 39304d4332d5SBarry Smith PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 4); 39319566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 0, &lg)); 39329566063dSJacob Faibussowitsch if (!n) PetscCall(PetscDrawLGReset(lg)); 39339566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 39349566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "Residual norm")); 3935b271bb04SBarry Smith x = (PetscReal)n; 393677b4d14cSPeter Brune if (rnorm > 0.0) y = PetscLog10Real(rnorm); 393794c9c6d3SKarl Rupp else y = -15.0; 39389566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 39396934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 39409566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 39419566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 3942b271bb04SBarry Smith } 3943b271bb04SBarry Smith 39449566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 1, &lg)); 39459566063dSJacob Faibussowitsch if (!n) PetscCall(PetscDrawLGReset(lg)); 39469566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 3947aaa8cc7dSPierre Jolivet PetscCall(PetscDrawSetTitle(draw, "% elements > .2*max element")); 39489566063dSJacob Faibussowitsch PetscCall(SNESMonitorRange_Private(snes, n, &per)); 3949b271bb04SBarry Smith x = (PetscReal)n; 3950b271bb04SBarry Smith y = 100.0 * per; 39519566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 39526934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 39539566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 39549566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 3955b271bb04SBarry Smith } 3956b271bb04SBarry Smith 39579566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 2, &lg)); 39589371c9d4SSatish Balay if (!n) { 39599371c9d4SSatish Balay prev = rnorm; 39609371c9d4SSatish Balay PetscCall(PetscDrawLGReset(lg)); 39619371c9d4SSatish Balay } 39629566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 39639566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm")); 3964b271bb04SBarry Smith x = (PetscReal)n; 3965b271bb04SBarry Smith y = (prev - rnorm) / prev; 39669566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 39676934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 39689566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 39699566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 3970b271bb04SBarry Smith } 3971b271bb04SBarry Smith 39729566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 3, &lg)); 39739566063dSJacob Faibussowitsch if (!n) PetscCall(PetscDrawLGReset(lg)); 39749566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 39759566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm*(% > .2 max)")); 3976b271bb04SBarry Smith x = (PetscReal)n; 3977b271bb04SBarry Smith y = (prev - rnorm) / (prev * per); 3978b271bb04SBarry Smith if (n > 2) { /*skip initial crazy value */ 39799566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 3980b271bb04SBarry Smith } 39816934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 39829566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 39839566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 3984b271bb04SBarry Smith } 3985b271bb04SBarry Smith prev = rnorm; 39863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3987b271bb04SBarry Smith } 3988b271bb04SBarry Smith 3989228d79bcSJed Brown /*@ 39902d157150SStefano Zampini SNESConverged - Run the convergence test and update the `SNESConvergedReason`. 39912d157150SStefano Zampini 39922d157150SStefano Zampini Collective 39932d157150SStefano Zampini 39942d157150SStefano Zampini Input Parameters: 39952d157150SStefano Zampini + snes - the `SNES` context 39962d157150SStefano Zampini . it - current iteration 39972d157150SStefano Zampini . xnorm - 2-norm of current iterate 39982d157150SStefano Zampini . snorm - 2-norm of current step 39992d157150SStefano Zampini - fnorm - 2-norm of function 40002d157150SStefano Zampini 40012d157150SStefano Zampini Level: developer 40022d157150SStefano Zampini 40032d157150SStefano Zampini Note: 4004420bcc1bSBarry Smith This routine is called by the `SNESSolve()` implementations. 40052d157150SStefano Zampini It does not typically need to be called by the user. 40062d157150SStefano Zampini 4007be50c303SSatish Balay .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`, `SNESGetConvergenceTest()` 40082d157150SStefano Zampini @*/ 40092d157150SStefano Zampini PetscErrorCode SNESConverged(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm) 40102d157150SStefano Zampini { 40112d157150SStefano Zampini PetscFunctionBegin; 40122d157150SStefano Zampini if (!snes->reason) { 40132d157150SStefano Zampini if (snes->normschedule == SNES_NORM_ALWAYS) PetscUseTypeMethod(snes, converged, it, xnorm, snorm, fnorm, &snes->reason, snes->cnvP); 40142d157150SStefano Zampini if (it == snes->max_its && !snes->reason) { 40152d157150SStefano Zampini if (snes->normschedule == SNES_NORM_ALWAYS) { 40162d157150SStefano Zampini PetscCall(PetscInfo(snes, "Maximum number of iterations has been reached: %" PetscInt_FMT "\n", snes->max_its)); 40172d157150SStefano Zampini snes->reason = SNES_DIVERGED_MAX_IT; 40182d157150SStefano Zampini } else snes->reason = SNES_CONVERGED_ITS; 40192d157150SStefano Zampini } 40202d157150SStefano Zampini } 40212d157150SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 40222d157150SStefano Zampini } 40232d157150SStefano Zampini 40242d157150SStefano Zampini /*@ 4025228d79bcSJed Brown SNESMonitor - runs the user provided monitor routines, if they exist 4026228d79bcSJed Brown 4027c3339decSBarry Smith Collective 4028228d79bcSJed Brown 4029228d79bcSJed Brown Input Parameters: 4030f6dfbefdSBarry Smith + snes - nonlinear solver context obtained from `SNESCreate()` 4031228d79bcSJed Brown . iter - iteration number 4032228d79bcSJed Brown - rnorm - relative norm of the residual 4033228d79bcSJed Brown 4034dc4c0fb0SBarry Smith Level: developer 4035dc4c0fb0SBarry Smith 4036f6dfbefdSBarry Smith Note: 4037420bcc1bSBarry Smith This routine is called by the `SNESSolve()` implementations. 4038228d79bcSJed Brown It does not typically need to be called by the user. 4039228d79bcSJed Brown 40401cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorSet()` 4041228d79bcSJed Brown @*/ 4042d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitor(SNES snes, PetscInt iter, PetscReal rnorm) 4043d71ae5a4SJacob Faibussowitsch { 40447a03ce2fSLisandro Dalcin PetscInt i, n = snes->numbermonitors; 40457a03ce2fSLisandro Dalcin 40467a03ce2fSLisandro Dalcin PetscFunctionBegin; 40475f3c5e7aSBarry Smith if (n > 0) SNESCheckFunctionNorm(snes, rnorm); 40489566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(snes->vec_sol)); 404948a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall((*snes->monitor[i])(snes, iter, rnorm, snes->monitorcontext[i])); 40509566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(snes->vec_sol)); 40513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 40527a03ce2fSLisandro Dalcin } 40537a03ce2fSLisandro Dalcin 40549b94acceSBarry Smith /* ------------ Routines to set performance monitoring options ----------- */ 40559b94acceSBarry Smith 4056bf388a1fSBarry Smith /*MC 4057f6dfbefdSBarry Smith SNESMonitorFunction - functional form passed to `SNESMonitorSet()` to monitor convergence of nonlinear solver 4058bf388a1fSBarry Smith 4059bf388a1fSBarry Smith Synopsis: 4060aaa7dc30SBarry Smith #include <petscsnes.h> 406137fdd005SBarry Smith PetscErrorCode SNESMonitorFunction(SNES snes, PetscInt its, PetscReal norm, void *mctx) 4062bf388a1fSBarry Smith 4063c3339decSBarry Smith Collective 40641843f636SBarry Smith 40651843f636SBarry Smith Input Parameters: 4066f6dfbefdSBarry Smith + snes - the `SNES` context 4067bf388a1fSBarry Smith . its - iteration number 4068bf388a1fSBarry Smith . norm - 2-norm function value (may be estimated) 4069bf388a1fSBarry Smith - mctx - [optional] monitoring context 4070bf388a1fSBarry Smith 4071878cb397SSatish Balay Level: advanced 4072878cb397SSatish Balay 40731cc06b55SBarry Smith .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSet()`, `SNESMonitorGet()` 4074bf388a1fSBarry Smith M*/ 4075bf388a1fSBarry Smith 40769b94acceSBarry Smith /*@C 4077a6570f20SBarry Smith SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every 40789b94acceSBarry Smith iteration of the nonlinear solver to display the iteration's 40799b94acceSBarry Smith progress. 40809b94acceSBarry Smith 4081c3339decSBarry Smith Logically Collective 4082fee21e36SBarry Smith 4083c7afd0dbSLois Curfman McInnes Input Parameters: 4084f6dfbefdSBarry Smith + snes - the `SNES` context 408520f4b53cSBarry Smith . f - the monitor function, for the calling sequence see `SNESMonitorFunction` 4086420bcc1bSBarry Smith . mctx - [optional] user-defined context for private data for the monitor routine (use `NULL` if no context is desired) 4087dc4c0fb0SBarry Smith - monitordestroy - [optional] routine that frees monitor context (may be `NULL`) 40889b94acceSBarry Smith 40899665c990SLois Curfman McInnes Options Database Keys: 4090f6dfbefdSBarry Smith + -snes_monitor - sets `SNESMonitorDefault()` 4091798534f6SMatthew G. Knepley . -snes_monitor draw::draw_lg - sets line graph monitor, 4092dc4c0fb0SBarry 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 4093c7afd0dbSLois Curfman McInnes the options database. 40949665c990SLois Curfman McInnes 4095dc4c0fb0SBarry Smith Level: intermediate 4096dc4c0fb0SBarry Smith 4097f6dfbefdSBarry Smith Note: 40986bc08f3fSLois Curfman McInnes Several different monitoring routines may be set by calling 4099f6dfbefdSBarry Smith `SNESMonitorSet()` multiple times; all will be called in the 41006bc08f3fSLois Curfman McInnes order in which they were set. 4101639f9d9dSBarry Smith 4102420bcc1bSBarry Smith Fortran Note: 4103f6dfbefdSBarry Smith Only a single monitor function can be set for each `SNES` object 4104025f1a04SBarry Smith 41051cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESMonitorDefault()`, `SNESMonitorCancel()`, `SNESMonitorFunction` 41069b94acceSBarry Smith @*/ 4107d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorSet(SNES snes, PetscErrorCode (*f)(SNES, PetscInt, PetscReal, void *), void *mctx, PetscErrorCode (*monitordestroy)(void **)) 4108d71ae5a4SJacob Faibussowitsch { 4109b90d0a6eSBarry Smith PetscInt i; 411078064530SBarry Smith PetscBool identical; 4111b90d0a6eSBarry Smith 41123a40ed3dSBarry Smith PetscFunctionBegin; 41130700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4114b90d0a6eSBarry Smith for (i = 0; i < snes->numbermonitors; i++) { 41159566063dSJacob Faibussowitsch PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, mctx, monitordestroy, (PetscErrorCode(*)(void))snes->monitor[i], snes->monitorcontext[i], snes->monitordestroy[i], &identical)); 41163ba16761SJacob Faibussowitsch if (identical) PetscFunctionReturn(PETSC_SUCCESS); 4117649052a6SBarry Smith } 41185f80ce2aSJacob Faibussowitsch PetscCheck(snes->numbermonitors < MAXSNESMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set"); 41196e4dcb14SBarry Smith snes->monitor[snes->numbermonitors] = f; 4120b8a78c4aSBarry Smith snes->monitordestroy[snes->numbermonitors] = monitordestroy; 4121639f9d9dSBarry Smith snes->monitorcontext[snes->numbermonitors++] = (void *)mctx; 41223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 41239b94acceSBarry Smith } 41249b94acceSBarry Smith 4125a278d85bSSatish Balay /*@ 4126f6dfbefdSBarry Smith SNESMonitorCancel - Clears all the monitor functions for a `SNES` object. 41275cd90555SBarry Smith 4128c3339decSBarry Smith Logically Collective 4129c7afd0dbSLois Curfman McInnes 41302fe279fdSBarry Smith Input Parameter: 4131f6dfbefdSBarry Smith . snes - the `SNES` context 41325cd90555SBarry Smith 41331a480d89SAdministrator Options Database Key: 4134a6570f20SBarry Smith . -snes_monitor_cancel - cancels all monitors that have been hardwired 4135dc4c0fb0SBarry Smith into a code by calls to `SNESMonitorSet()`, but does not cancel those 4136c7afd0dbSLois Curfman McInnes set via the options database 41375cd90555SBarry Smith 4138dc4c0fb0SBarry Smith Level: intermediate 4139dc4c0fb0SBarry Smith 4140f6dfbefdSBarry Smith Note: 4141f6dfbefdSBarry Smith There is no way to clear one specific monitor from a `SNES` object. 41425cd90555SBarry Smith 41431cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorGet()`, `SNESMonitorDefault()`, `SNESMonitorSet()` 41445cd90555SBarry Smith @*/ 4145d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorCancel(SNES snes) 4146d71ae5a4SJacob Faibussowitsch { 4147d952e501SBarry Smith PetscInt i; 4148d952e501SBarry Smith 41495cd90555SBarry Smith PetscFunctionBegin; 41500700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4151d952e501SBarry Smith for (i = 0; i < snes->numbermonitors; i++) { 415248a46eb9SPierre Jolivet if (snes->monitordestroy[i]) PetscCall((*snes->monitordestroy[i])(&snes->monitorcontext[i])); 4153d952e501SBarry Smith } 41545cd90555SBarry Smith snes->numbermonitors = 0; 41553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 41565cd90555SBarry Smith } 41575cd90555SBarry Smith 4158bf388a1fSBarry Smith /*MC 4159bf388a1fSBarry Smith SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver 4160bf388a1fSBarry Smith 4161bf388a1fSBarry Smith Synopsis: 4162aaa7dc30SBarry Smith #include <petscsnes.h> 416337fdd005SBarry Smith PetscErrorCode SNESConvergenceTest(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *cctx) 4164bf388a1fSBarry Smith 4165c3339decSBarry Smith Collective 41661843f636SBarry Smith 41671843f636SBarry Smith Input Parameters: 4168f6dfbefdSBarry Smith + snes - the `SNES` context 4169bf388a1fSBarry Smith . it - current iteration (0 is the first and is before any Newton step) 4170bf388a1fSBarry Smith . xnorm - 2-norm of current iterate 4171bf388a1fSBarry Smith . gnorm - 2-norm of current step 41721843f636SBarry Smith . f - 2-norm of function 41731843f636SBarry Smith - cctx - [optional] convergence context 41741843f636SBarry Smith 41751843f636SBarry Smith Output Parameter: 41761843f636SBarry Smith . reason - reason for convergence/divergence, only needs to be set when convergence or divergence is detected 4177bf388a1fSBarry Smith 4178878cb397SSatish Balay Level: intermediate 4179bf388a1fSBarry Smith 41801cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`, `SNESGetConvergenceTest()` 4181bf388a1fSBarry Smith M*/ 4182bf388a1fSBarry Smith 41839b94acceSBarry Smith /*@C 41849b94acceSBarry Smith SNESSetConvergenceTest - Sets the function that is to be used 41859b94acceSBarry Smith to test for convergence of the nonlinear iterative solution. 41869b94acceSBarry Smith 4187c3339decSBarry Smith Logically Collective 4188fee21e36SBarry Smith 4189c7afd0dbSLois Curfman McInnes Input Parameters: 4190f6dfbefdSBarry Smith + snes - the `SNES` context 4191e4094ef1SJacob Faibussowitsch . SNESConvergenceTestFunction - routine to test for convergence 4192dc4c0fb0SBarry Smith . cctx - [optional] context for private data for the convergence routine (may be `NULL`) 4193dc4c0fb0SBarry Smith - destroy - [optional] destructor for the context (may be `NULL`; `PETSC_NULL_FUNCTION` in Fortran) 41949b94acceSBarry Smith 419536851e7fSLois Curfman McInnes Level: advanced 419636851e7fSLois Curfman McInnes 41971cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedDefault()`, `SNESConvergedSkip()`, `SNESConvergenceTestFunction` 41989b94acceSBarry Smith @*/ 4199d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceTest(SNES snes, PetscErrorCode (*SNESConvergenceTestFunction)(SNES, PetscInt, PetscReal, PetscReal, PetscReal, SNESConvergedReason *, void *), void *cctx, PetscErrorCode (*destroy)(void *)) 4200d71ae5a4SJacob Faibussowitsch { 42013a40ed3dSBarry Smith PetscFunctionBegin; 42020700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4203e2a6519dSDmitry Karpeev if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip; 42041baa6e33SBarry Smith if (snes->ops->convergeddestroy) PetscCall((*snes->ops->convergeddestroy)(snes->cnvP)); 4205bf388a1fSBarry Smith snes->ops->converged = SNESConvergenceTestFunction; 42067f7931b9SBarry Smith snes->ops->convergeddestroy = destroy; 420785385478SLisandro Dalcin snes->cnvP = cctx; 42083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 42099b94acceSBarry Smith } 42109b94acceSBarry Smith 421152baeb72SSatish Balay /*@ 4212f6dfbefdSBarry Smith SNESGetConvergedReason - Gets the reason the `SNES` iteration was stopped. 4213184914b5SBarry Smith 4214184914b5SBarry Smith Not Collective 4215184914b5SBarry Smith 4216184914b5SBarry Smith Input Parameter: 4217f6dfbefdSBarry Smith . snes - the `SNES` context 4218184914b5SBarry Smith 4219184914b5SBarry Smith Output Parameter: 4220f6dfbefdSBarry Smith . reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` for the individual convergence tests for complete lists 4221184914b5SBarry Smith 4222f6dfbefdSBarry Smith Options Database Key: 42236a4d7782SBarry Smith . -snes_converged_reason - prints the reason to standard out 42246a4d7782SBarry Smith 4225184914b5SBarry Smith Level: intermediate 4226184914b5SBarry Smith 4227f6dfbefdSBarry Smith Note: 4228f6dfbefdSBarry Smith Should only be called after the call the `SNESSolve()` is complete, if it is called earlier it returns the value `SNES__CONVERGED_ITERATING`. 4229184914b5SBarry Smith 42301cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESSetConvergedReason()`, `SNESConvergedReason`, `SNESGetConvergedReasonString()` 4231184914b5SBarry Smith @*/ 4232d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReason(SNES snes, SNESConvergedReason *reason) 4233d71ae5a4SJacob Faibussowitsch { 4234184914b5SBarry Smith PetscFunctionBegin; 42350700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 42364f572ea9SToby Isaac PetscAssertPointer(reason, 2); 4237184914b5SBarry Smith *reason = snes->reason; 42383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4239184914b5SBarry Smith } 4240184914b5SBarry Smith 4241c4421ceaSFande Kong /*@C 4242f6dfbefdSBarry Smith SNESGetConvergedReasonString - Return a human readable string for `SNESConvergedReason` 4243c4421ceaSFande Kong 4244c4421ceaSFande Kong Not Collective 4245c4421ceaSFande Kong 4246c4421ceaSFande Kong Input Parameter: 4247f6dfbefdSBarry Smith . snes - the `SNES` context 4248c4421ceaSFande Kong 4249c4421ceaSFande Kong Output Parameter: 4250dc4c0fb0SBarry Smith . strreason - a human readable string that describes `SNES` converged reason 4251c4421ceaSFande Kong 425299c90e12SSatish Balay Level: beginner 4253c4421ceaSFande Kong 42541cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetConvergedReason()` 4255c4421ceaSFande Kong @*/ 4256d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReasonString(SNES snes, const char **strreason) 4257d71ae5a4SJacob Faibussowitsch { 4258c4421ceaSFande Kong PetscFunctionBegin; 4259c4421ceaSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 42604f572ea9SToby Isaac PetscAssertPointer(strreason, 2); 4261c4421ceaSFande Kong *strreason = SNESConvergedReasons[snes->reason]; 42623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4263c4421ceaSFande Kong } 4264c4421ceaSFande Kong 426533866048SMatthew G. Knepley /*@ 4266f6dfbefdSBarry Smith SNESSetConvergedReason - Sets the reason the `SNES` iteration was stopped. 426733866048SMatthew G. Knepley 426833866048SMatthew G. Knepley Not Collective 426933866048SMatthew G. Knepley 427033866048SMatthew G. Knepley Input Parameters: 4271f6dfbefdSBarry Smith + snes - the `SNES` context 4272f6dfbefdSBarry Smith - reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` or the 427333866048SMatthew G. Knepley manual pages for the individual convergence tests for complete lists 427433866048SMatthew G. Knepley 4275f6dfbefdSBarry Smith Level: developer 4276f6dfbefdSBarry Smith 4277420bcc1bSBarry Smith Developer Note: 4278f6dfbefdSBarry Smith Called inside the various `SNESSolve()` implementations 427933866048SMatthew G. Knepley 42801cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetConvergedReason()`, `SNESSetConvergenceTest()`, `SNESConvergedReason` 428133866048SMatthew G. Knepley @*/ 4282d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergedReason(SNES snes, SNESConvergedReason reason) 4283d71ae5a4SJacob Faibussowitsch { 428433866048SMatthew G. Knepley PetscFunctionBegin; 428533866048SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 42865f3c5e7aSBarry Smith PetscCheck(!snes->errorifnotconverged || reason > 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "SNES code should have previously errored due to negative reason"); 428733866048SMatthew G. Knepley snes->reason = reason; 42883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 428933866048SMatthew G. Knepley } 429033866048SMatthew G. Knepley 4291c9005455SLois Curfman McInnes /*@ 4292420bcc1bSBarry Smith SNESSetConvergenceHistory - Sets the arrays used to hold the convergence history. 4293c9005455SLois Curfman McInnes 4294c3339decSBarry Smith Logically Collective 4295fee21e36SBarry Smith 4296c7afd0dbSLois Curfman McInnes Input Parameters: 4297f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 42988c7482ecSBarry Smith . a - array to hold history, this array will contain the function norms computed at each step 4299cd5578b5SBarry Smith . its - integer array holds the number of linear iterations for each solve. 4300420bcc1bSBarry Smith . na - size of `a` and `its` 4301f6dfbefdSBarry Smith - reset - `PETSC_TRUE` indicates each new nonlinear solve resets the history counter to zero, 4302758f92a0SBarry Smith else it continues storing new values for new nonlinear solves after the old ones 4303c7afd0dbSLois Curfman McInnes 4304dc4c0fb0SBarry Smith Level: intermediate 4305dc4c0fb0SBarry Smith 4306308dcc3eSBarry Smith Notes: 4307dc4c0fb0SBarry Smith If 'a' and 'its' are `NULL` then space is allocated for the history. If 'na' `PETSC_DECIDE` or `PETSC_DEFAULT` then a 4308308dcc3eSBarry Smith default array of length 10000 is allocated. 4309308dcc3eSBarry Smith 4310c9005455SLois Curfman McInnes This routine is useful, e.g., when running a code for purposes 4311c9005455SLois Curfman McInnes of accurate performance monitoring, when no I/O should be done 4312c9005455SLois Curfman McInnes during the section of code that is being timed. 4313c9005455SLois Curfman McInnes 4314420bcc1bSBarry Smith If the arrays run out of space after a number of iterations then the later values are not saved in the history 4315420bcc1bSBarry Smith 43161cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetConvergenceHistory()` 4317c9005455SLois Curfman McInnes @*/ 4318d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceHistory(SNES snes, PetscReal a[], PetscInt its[], PetscInt na, PetscBool reset) 4319d71ae5a4SJacob Faibussowitsch { 43203a40ed3dSBarry Smith PetscFunctionBegin; 43210700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 43224f572ea9SToby Isaac if (a) PetscAssertPointer(a, 2); 43234f572ea9SToby Isaac if (its) PetscAssertPointer(its, 3); 43247a1ec6d4SBarry Smith if (!a) { 4325308dcc3eSBarry Smith if (na == PETSC_DECIDE || na == PETSC_DEFAULT) na = 1000; 43269566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(na, &a, na, &its)); 4327071fcb05SBarry Smith snes->conv_hist_alloc = PETSC_TRUE; 4328308dcc3eSBarry Smith } 4329c9005455SLois Curfman McInnes snes->conv_hist = a; 4330758f92a0SBarry Smith snes->conv_hist_its = its; 4331115dd874SBarry Smith snes->conv_hist_max = (size_t)na; 4332a12bc48fSLisandro Dalcin snes->conv_hist_len = 0; 4333758f92a0SBarry Smith snes->conv_hist_reset = reset; 43343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4335758f92a0SBarry Smith } 4336758f92a0SBarry Smith 4337d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB) 4338c6db04a5SJed Brown #include <engine.h> /* MATLAB include file */ 4339c6db04a5SJed Brown #include <mex.h> /* MATLAB include file */ 434099e0435eSBarry Smith 4341d71ae5a4SJacob Faibussowitsch PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes) 4342d71ae5a4SJacob Faibussowitsch { 4343308dcc3eSBarry Smith mxArray *mat; 4344308dcc3eSBarry Smith PetscInt i; 4345308dcc3eSBarry Smith PetscReal *ar; 4346308dcc3eSBarry Smith 4347308dcc3eSBarry Smith mat = mxCreateDoubleMatrix(snes->conv_hist_len, 1, mxREAL); 4348308dcc3eSBarry Smith ar = (PetscReal *)mxGetData(mat); 4349f5af7f23SKarl Rupp for (i = 0; i < snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i]; 435011cc89d2SBarry Smith return mat; 4351308dcc3eSBarry Smith } 4352308dcc3eSBarry Smith #endif 4353308dcc3eSBarry Smith 43540c4c9dddSBarry Smith /*@C 4355420bcc1bSBarry Smith SNESGetConvergenceHistory - Gets the arrays used to hold the convergence history. 4356758f92a0SBarry Smith 43573f9fe445SBarry Smith Not Collective 4358758f92a0SBarry Smith 4359758f92a0SBarry Smith Input Parameter: 4360f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 4361758f92a0SBarry Smith 4362758f92a0SBarry Smith Output Parameters: 4363f6dfbefdSBarry Smith + a - array to hold history, usually was set with `SNESSetConvergenceHistory()` 4364758f92a0SBarry Smith . its - integer array holds the number of linear iterations (or 4365758f92a0SBarry Smith negative if not converged) for each solve. 436620f4b53cSBarry Smith - na - size of `a` and `its` 4367758f92a0SBarry Smith 4368dc4c0fb0SBarry Smith Level: intermediate 4369dc4c0fb0SBarry Smith 437020f4b53cSBarry Smith Note: 437120f4b53cSBarry Smith This routine is useful, e.g., when running a code for purposes 437220f4b53cSBarry Smith of accurate performance monitoring, when no I/O should be done 437320f4b53cSBarry Smith during the section of code that is being timed. 437420f4b53cSBarry Smith 4375420bcc1bSBarry Smith Fortran Note: 4376758f92a0SBarry Smith The calling sequence for this routine in Fortran is 4377dc4c0fb0SBarry Smith .vb 4378dc4c0fb0SBarry Smith call SNESGetConvergenceHistory(SNES snes, integer na, integer ierr) 4379dc4c0fb0SBarry Smith .ve 4380758f92a0SBarry Smith 43811cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceHistory()` 4382758f92a0SBarry Smith @*/ 4383d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergenceHistory(SNES snes, PetscReal *a[], PetscInt *its[], PetscInt *na) 4384d71ae5a4SJacob Faibussowitsch { 4385758f92a0SBarry Smith PetscFunctionBegin; 43860700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4387758f92a0SBarry Smith if (a) *a = snes->conv_hist; 4388758f92a0SBarry Smith if (its) *its = snes->conv_hist_its; 4389115dd874SBarry Smith if (na) *na = (PetscInt)snes->conv_hist_len; 43903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4391c9005455SLois Curfman McInnes } 4392c9005455SLois Curfman McInnes 4393ac226902SBarry Smith /*@C 439476b2cf59SMatthew Knepley SNESSetUpdate - Sets the general-purpose update function called 4395eec8f646SJed Brown at the beginning of every iteration of the nonlinear solve. Specifically 43967e4bb74cSBarry Smith it is called just before the Jacobian is "evaluated". 439776b2cf59SMatthew Knepley 4398c3339decSBarry Smith Logically Collective 439976b2cf59SMatthew Knepley 440076b2cf59SMatthew Knepley Input Parameters: 4401a2b725a8SWilliam Gropp + snes - The nonlinear solver context 4402a2b725a8SWilliam Gropp - func - The function 440376b2cf59SMatthew Knepley 440420f4b53cSBarry Smith Calling sequence of `func`: 440520f4b53cSBarry Smith + snes - the nonlinear solver context 440620f4b53cSBarry Smith - step - The current step of the iteration 440776b2cf59SMatthew Knepley 4408fe97e370SBarry Smith Level: advanced 4409fe97e370SBarry Smith 4410420bcc1bSBarry Smith Notes: 4411f6dfbefdSBarry 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 4412f6dfbefdSBarry Smith to `SNESSetFunction()`, or `SNESSetPicard()` 4413fe97e370SBarry Smith This is not used by most users. 441476b2cf59SMatthew Knepley 4415aaa8cc7dSPierre 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. 44166b7fb656SBarry Smith 4417e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetJacobian()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRSetPostCheck()`, 4418db781477SPatrick Sanan `SNESMonitorSet()`, `SNESSetDivergenceTest()` 441976b2cf59SMatthew Knepley @*/ 44200b4db180SJacob Faibussowitsch PetscErrorCode SNESSetUpdate(SNES snes, PetscErrorCode (*func)(SNES snes, PetscInt step)) 4421d71ae5a4SJacob Faibussowitsch { 442276b2cf59SMatthew Knepley PetscFunctionBegin; 44230700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4424e7788613SBarry Smith snes->ops->update = func; 44253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 442676b2cf59SMatthew Knepley } 442776b2cf59SMatthew Knepley 4428*ffeef943SBarry Smith /*@ 4429f6dfbefdSBarry Smith SNESConvergedReasonView - Displays the reason a `SNES` solve converged or diverged to a viewer 44302a359c20SBarry Smith 4431c3339decSBarry Smith Collective 44322a359c20SBarry Smith 4433e4094ef1SJacob Faibussowitsch Input Parameters: 4434f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 44352a359c20SBarry Smith - viewer - the viewer to display the reason 44362a359c20SBarry Smith 44372a359c20SBarry Smith Options Database Keys: 4438ee300463SSatish Balay + -snes_converged_reason - print reason for converged or diverged, also prints number of iterations 4439ee300463SSatish Balay - -snes_converged_reason ::failed - only print reason and number of iterations when diverged 4440eafd5ff0SAlex Lindsay 4441420bcc1bSBarry Smith Level: beginner 4442420bcc1bSBarry Smith 4443f6dfbefdSBarry Smith Note: 4444f6dfbefdSBarry Smith To change the format of the output call `PetscViewerPushFormat`(viewer,format) before this call. Use `PETSC_VIEWER_DEFAULT` for the default, 4445f6dfbefdSBarry Smith use `PETSC_VIEWER_FAILED` to only display a reason if it fails. 44462a359c20SBarry Smith 44471cc06b55SBarry Smith .seealso: [](ch_snes), `SNESConvergedReason`, `PetscViewer`, `SNES`, 4448f6dfbefdSBarry Smith `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, 4449f6dfbefdSBarry Smith `SNESConvergedReasonViewFromOptions()`, 4450db781477SPatrick Sanan `PetscViewerPushFormat()`, `PetscViewerPopFormat()` 44512a359c20SBarry Smith @*/ 4452d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonView(SNES snes, PetscViewer viewer) 4453d71ae5a4SJacob Faibussowitsch { 445475cca76cSMatthew G. Knepley PetscViewerFormat format; 44552a359c20SBarry Smith PetscBool isAscii; 44562a359c20SBarry Smith 44572a359c20SBarry Smith PetscFunctionBegin; 445819a666eeSBarry Smith if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)); 44599566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii)); 44602a359c20SBarry Smith if (isAscii) { 44619566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 446265bf60d2SBarry Smith PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel + 1)); 446375cca76cSMatthew G. Knepley if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 446475cca76cSMatthew G. Knepley DM dm; 446575cca76cSMatthew G. Knepley Vec u; 446675cca76cSMatthew G. Knepley PetscDS prob; 446775cca76cSMatthew G. Knepley PetscInt Nf, f; 446895cbbfd3SMatthew G. Knepley PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *); 446995cbbfd3SMatthew G. Knepley void **exactCtx; 447075cca76cSMatthew G. Knepley PetscReal error; 447175cca76cSMatthew G. Knepley 44729566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 44739566063dSJacob Faibussowitsch PetscCall(SNESGetSolution(snes, &u)); 44749566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob)); 44759566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(prob, &Nf)); 44769566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(Nf, &exactSol, Nf, &exactCtx)); 44779566063dSJacob Faibussowitsch for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f])); 44789566063dSJacob Faibussowitsch PetscCall(DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error)); 44799566063dSJacob Faibussowitsch PetscCall(PetscFree2(exactSol, exactCtx)); 44809566063dSJacob Faibussowitsch if (error < 1.0e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n")); 448163a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", (double)error)); 448275cca76cSMatthew G. Knepley } 4483eafd5ff0SAlex Lindsay if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) { 44842a359c20SBarry Smith if (((PetscObject)snes)->prefix) { 448563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter)); 44862a359c20SBarry Smith } else { 448763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve converged due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter)); 44882a359c20SBarry Smith } 4489eafd5ff0SAlex Lindsay } else if (snes->reason <= 0) { 44902a359c20SBarry Smith if (((PetscObject)snes)->prefix) { 449163a3b9bcSJacob 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)); 44922a359c20SBarry Smith } else { 449363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve did not converge due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter)); 44942a359c20SBarry Smith } 44952a359c20SBarry Smith } 449665bf60d2SBarry Smith PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel + 1)); 44972a359c20SBarry Smith } 44983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 44992a359c20SBarry Smith } 45002a359c20SBarry Smith 4501c4421ceaSFande Kong /*@C 4502c4421ceaSFande Kong SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the 4503aaa8cc7dSPierre Jolivet end of the nonlinear solver to display the convergence reason of the nonlinear solver. 4504c4421ceaSFande Kong 4505c3339decSBarry Smith Logically Collective 4506c4421ceaSFande Kong 4507c4421ceaSFande Kong Input Parameters: 4508f6dfbefdSBarry Smith + snes - the `SNES` context 4509420bcc1bSBarry Smith . f - the `SNESConvergedReason` view function 4510420bcc1bSBarry Smith . vctx - [optional] user-defined context for private data for the `SNESConvergedReason` view function (use `NULL` if no context is desired) 4511420bcc1bSBarry Smith - reasonviewdestroy - [optional] routine that frees the context (may be `NULL`) 4512420bcc1bSBarry Smith 4513420bcc1bSBarry Smith Calling sequence of `f`: 4514420bcc1bSBarry Smith + snes - the `SNES` context 4515420bcc1bSBarry Smith - vctx - [optional] user-defined context for private data for the function 4516420bcc1bSBarry Smith 4517420bcc1bSBarry Smith Calling sequence of `reasonviewerdestroy`: 4518420bcc1bSBarry Smith . vctx - [optional] user-defined context for private data for the function 4519c4421ceaSFande Kong 4520c4421ceaSFande Kong Options Database Keys: 4521f6dfbefdSBarry Smith + -snes_converged_reason - sets a default `SNESConvergedReasonView()` 4522420bcc1bSBarry Smith - -snes_converged_reason_view_cancel - cancels all converged reason viewers that have been hardwired into a code by 4523420bcc1bSBarry Smith calls to `SNESConvergedReasonViewSet()`, but does not cancel those set via the options database. 4524c4421ceaSFande Kong 4525dc4c0fb0SBarry Smith Level: intermediate 4526dc4c0fb0SBarry Smith 4527f6dfbefdSBarry Smith Note: 4528c4421ceaSFande Kong Several different converged reason view routines may be set by calling 4529f6dfbefdSBarry Smith `SNESConvergedReasonViewSet()` multiple times; all will be called in the 4530c4421ceaSFande Kong order in which they were set. 4531c4421ceaSFande Kong 45321cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`, `SNESConvergedReasonViewCancel()` 4533c4421ceaSFande Kong @*/ 4534420bcc1bSBarry Smith PetscErrorCode SNESConvergedReasonViewSet(SNES snes, PetscErrorCode (*f)(SNES snes, void *vctx), void *vctx, PetscErrorCode (*reasonviewdestroy)(void **vctx)) 4535d71ae5a4SJacob Faibussowitsch { 4536c4421ceaSFande Kong PetscInt i; 4537c4421ceaSFande Kong PetscBool identical; 4538c4421ceaSFande Kong 4539c4421ceaSFande Kong PetscFunctionBegin; 4540c4421ceaSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4541c4421ceaSFande Kong for (i = 0; i < snes->numberreasonviews; i++) { 45429566063dSJacob Faibussowitsch PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, vctx, reasonviewdestroy, (PetscErrorCode(*)(void))snes->reasonview[i], snes->reasonviewcontext[i], snes->reasonviewdestroy[i], &identical)); 45433ba16761SJacob Faibussowitsch if (identical) PetscFunctionReturn(PETSC_SUCCESS); 4544c4421ceaSFande Kong } 45455f80ce2aSJacob Faibussowitsch PetscCheck(snes->numberreasonviews < MAXSNESREASONVIEWS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many SNES reasonview set"); 4546c4421ceaSFande Kong snes->reasonview[snes->numberreasonviews] = f; 4547c4421ceaSFande Kong snes->reasonviewdestroy[snes->numberreasonviews] = reasonviewdestroy; 4548c4421ceaSFande Kong snes->reasonviewcontext[snes->numberreasonviews++] = (void *)vctx; 45493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4550c4421ceaSFande Kong } 4551c4421ceaSFande Kong 455291f3e32bSBarry Smith /*@ 4553420bcc1bSBarry Smith SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a `SNESConvergedReason` is to be viewed at the end of `SNESSolve()` 4554c4421ceaSFande Kong All the user-provided convergedReasonView routines will be involved as well, if they exist. 45552a359c20SBarry Smith 4556c3339decSBarry Smith Collective 45572a359c20SBarry Smith 45582fe279fdSBarry Smith Input Parameter: 4559f6dfbefdSBarry Smith . snes - the `SNES` object 45602a359c20SBarry Smith 4561f6dfbefdSBarry Smith Level: advanced 45622a359c20SBarry Smith 45631cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESConvergedReasonViewSet()`, `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, 4564f6dfbefdSBarry Smith `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()` 45652a359c20SBarry Smith @*/ 4566d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes) 4567d71ae5a4SJacob Faibussowitsch { 45682a359c20SBarry Smith PetscViewer viewer; 45692a359c20SBarry Smith PetscBool flg; 45702a359c20SBarry Smith static PetscBool incall = PETSC_FALSE; 45712a359c20SBarry Smith PetscViewerFormat format; 4572c4421ceaSFande Kong PetscInt i; 45732a359c20SBarry Smith 45742a359c20SBarry Smith PetscFunctionBegin; 45753ba16761SJacob Faibussowitsch if (incall) PetscFunctionReturn(PETSC_SUCCESS); 45762a359c20SBarry Smith incall = PETSC_TRUE; 4577c4421ceaSFande Kong 4578c4421ceaSFande Kong /* All user-provided viewers are called first, if they exist. */ 457948a46eb9SPierre Jolivet for (i = 0; i < snes->numberreasonviews; i++) PetscCall((*snes->reasonview[i])(snes, snes->reasonviewcontext[i])); 4580c4421ceaSFande Kong 4581c4421ceaSFande Kong /* Call PETSc default routine if users ask for it */ 45829566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_converged_reason", &viewer, &format, &flg)); 45832a359c20SBarry Smith if (flg) { 45849566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(viewer, format)); 45859566063dSJacob Faibussowitsch PetscCall(SNESConvergedReasonView(snes, viewer)); 45869566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer)); 4587cd791dc2SBarry Smith PetscCall(PetscOptionsRestoreViewer(&viewer)); 45882a359c20SBarry Smith } 45892a359c20SBarry Smith incall = PETSC_FALSE; 45903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 45912a359c20SBarry Smith } 45922a359c20SBarry Smith 4593487a658cSBarry Smith /*@ 4594f69a0ea3SMatthew Knepley SNESSolve - Solves a nonlinear system F(x) = b. 45959b94acceSBarry Smith 4596c3339decSBarry Smith Collective 4597c7afd0dbSLois Curfman McInnes 4598b2002411SLois Curfman McInnes Input Parameters: 4599f6dfbefdSBarry Smith + snes - the `SNES` context 4600dc4c0fb0SBarry Smith . b - the constant part of the equation F(x) = b, or `NULL` to use zero. 460185385478SLisandro Dalcin - x - the solution vector. 46029b94acceSBarry Smith 4603dc4c0fb0SBarry Smith Level: beginner 4604dc4c0fb0SBarry Smith 4605f6dfbefdSBarry Smith Note: 4606420bcc1bSBarry Smith The user should initialize the vector, `x`, with the initial guess 4607420bcc1bSBarry Smith for the nonlinear solve prior to calling `SNESSolve()` or use `SNESSetInitialSolution()`. In particular, 46088ddd3da0SLois Curfman McInnes to employ an initial guess of zero, the user should explicitly set 4609f6dfbefdSBarry Smith this vector to zero by calling `VecSet()`. 46108ddd3da0SLois Curfman McInnes 46111cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESSetFunction()`, `SNESSetJacobian()`, `SNESSetGridSequence()`, `SNESGetSolution()`, 4612db781477SPatrick Sanan `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRGetPreCheck()`, `SNESNewtonTRSetPostCheck()`, `SNESNewtonTRGetPostCheck()`, 4613420bcc1bSBarry Smith `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`, `SNESSetInitialSolution()` 46149b94acceSBarry Smith @*/ 4615d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSolve(SNES snes, Vec b, Vec x) 4616d71ae5a4SJacob Faibussowitsch { 4617ace3abfcSBarry Smith PetscBool flg; 4618efd51863SBarry Smith PetscInt grid; 46190298fd71SBarry Smith Vec xcreated = NULL; 4620caa4e7f2SJed Brown DM dm; 4621052efed2SBarry Smith 46223a40ed3dSBarry Smith PetscFunctionBegin; 46230700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4624a69afd8bSBarry Smith if (x) PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4625a69afd8bSBarry Smith if (x) PetscCheckSameComm(snes, 1, x, 3); 46260700a824SBarry Smith if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 462785385478SLisandro Dalcin if (b) PetscCheckSameComm(snes, 1, b, 2); 462885385478SLisandro Dalcin 462934b4d3a8SMatthew G. Knepley /* High level operations using the nonlinear solver */ 463006fc46c8SMatthew G. Knepley { 463106fc46c8SMatthew G. Knepley PetscViewer viewer; 463206fc46c8SMatthew G. Knepley PetscViewerFormat format; 46337c88af5aSMatthew G. Knepley PetscInt num; 463406fc46c8SMatthew G. Knepley PetscBool flg; 463506fc46c8SMatthew G. Knepley static PetscBool incall = PETSC_FALSE; 463606fc46c8SMatthew G. Knepley 463706fc46c8SMatthew G. Knepley if (!incall) { 463834b4d3a8SMatthew G. Knepley /* Estimate the convergence rate of the discretization */ 46399566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg)); 464006fc46c8SMatthew G. Knepley if (flg) { 464106fc46c8SMatthew G. Knepley PetscConvEst conv; 464246079b62SMatthew G. Knepley DM dm; 464346079b62SMatthew G. Knepley PetscReal *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */ 464446079b62SMatthew G. Knepley PetscInt Nf; 464506fc46c8SMatthew G. Knepley 464606fc46c8SMatthew G. Knepley incall = PETSC_TRUE; 46479566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 46489566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 46499566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(Nf, &alpha)); 46509566063dSJacob Faibussowitsch PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)snes), &conv)); 46519566063dSJacob Faibussowitsch PetscCall(PetscConvEstSetSolver(conv, (PetscObject)snes)); 46529566063dSJacob Faibussowitsch PetscCall(PetscConvEstSetFromOptions(conv)); 46539566063dSJacob Faibussowitsch PetscCall(PetscConvEstSetUp(conv)); 46549566063dSJacob Faibussowitsch PetscCall(PetscConvEstGetConvRate(conv, alpha)); 46559566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(viewer, format)); 46569566063dSJacob Faibussowitsch PetscCall(PetscConvEstRateView(conv, alpha, viewer)); 46579566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer)); 4658cd791dc2SBarry Smith PetscCall(PetscOptionsRestoreViewer(&viewer)); 46599566063dSJacob Faibussowitsch PetscCall(PetscConvEstDestroy(&conv)); 46609566063dSJacob Faibussowitsch PetscCall(PetscFree(alpha)); 466106fc46c8SMatthew G. Knepley incall = PETSC_FALSE; 466206fc46c8SMatthew G. Knepley } 466334b4d3a8SMatthew G. Knepley /* Adaptively refine the initial grid */ 4664b2588ea6SMatthew G. Knepley num = 1; 46659566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_initial", &num, &flg)); 466634b4d3a8SMatthew G. Knepley if (flg) { 466734b4d3a8SMatthew G. Knepley DMAdaptor adaptor; 466834b4d3a8SMatthew G. Knepley 466934b4d3a8SMatthew G. Knepley incall = PETSC_TRUE; 46709566063dSJacob Faibussowitsch PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor)); 46719566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSolver(adaptor, snes)); 46729566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSequenceLength(adaptor, num)); 46739566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetFromOptions(adaptor)); 46749566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetUp(adaptor)); 46759566063dSJacob Faibussowitsch PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x)); 46769566063dSJacob Faibussowitsch PetscCall(DMAdaptorDestroy(&adaptor)); 467734b4d3a8SMatthew G. Knepley incall = PETSC_FALSE; 467834b4d3a8SMatthew G. Knepley } 46797c88af5aSMatthew G. Knepley /* Use grid sequencing to adapt */ 46807c88af5aSMatthew G. Knepley num = 0; 46819566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_sequence", &num, NULL)); 46827c88af5aSMatthew G. Knepley if (num) { 46837c88af5aSMatthew G. Knepley DMAdaptor adaptor; 46847c88af5aSMatthew G. Knepley 46857c88af5aSMatthew G. Knepley incall = PETSC_TRUE; 46869566063dSJacob Faibussowitsch PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor)); 46879566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSolver(adaptor, snes)); 46889566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSequenceLength(adaptor, num)); 46899566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetFromOptions(adaptor)); 46909566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetUp(adaptor)); 46919566063dSJacob Faibussowitsch PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x)); 46929566063dSJacob Faibussowitsch PetscCall(DMAdaptorDestroy(&adaptor)); 46937c88af5aSMatthew G. Knepley incall = PETSC_FALSE; 46947c88af5aSMatthew G. Knepley } 469506fc46c8SMatthew G. Knepley } 469606fc46c8SMatthew G. Knepley } 4697ad540459SPierre Jolivet if (!x) x = snes->vec_sol; 4698caa4e7f2SJed Brown if (!x) { 46999566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 47009566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dm, &xcreated)); 4701a69afd8bSBarry Smith x = xcreated; 4702a69afd8bSBarry Smith } 47039566063dSJacob Faibussowitsch PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view_pre")); 4704f05ece33SBarry Smith 47059566063dSJacob Faibussowitsch for (grid = 0; grid < snes->gridsequence; grid++) PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)))); 4706efd51863SBarry Smith for (grid = 0; grid < snes->gridsequence + 1; grid++) { 470785385478SLisandro Dalcin /* set solution vector */ 47089566063dSJacob Faibussowitsch if (!grid) PetscCall(PetscObjectReference((PetscObject)x)); 47099566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol)); 471085385478SLisandro Dalcin snes->vec_sol = x; 47119566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 4712caa4e7f2SJed Brown 4713caa4e7f2SJed Brown /* set affine vector if provided */ 47149566063dSJacob Faibussowitsch if (b) PetscCall(PetscObjectReference((PetscObject)b)); 47159566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_rhs)); 471685385478SLisandro Dalcin snes->vec_rhs = b; 471785385478SLisandro Dalcin 47185f80ce2aSJacob 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"); 47195f80ce2aSJacob Faibussowitsch PetscCheck(snes->vec_func != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be function vector"); 4720dd8e379bSPierre Jolivet PetscCheck(snes->vec_rhs != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be right-hand side vector"); 4721aa624791SPierre Jolivet if (!snes->vec_sol_update /* && snes->vec_sol */) PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_sol_update)); 47229566063dSJacob Faibussowitsch PetscCall(DMShellSetGlobalVector(dm, snes->vec_sol)); 47239566063dSJacob Faibussowitsch PetscCall(SNESSetUp(snes)); 47243f149594SLisandro Dalcin 47257eee914bSBarry Smith if (!grid) { 47269927e4dfSBarry Smith if (snes->ops->computeinitialguess) PetscCallBack("SNES callback compute initial guess", (*snes->ops->computeinitialguess)(snes, snes->vec_sol, snes->initialguessP)); 4727dd568438SSatish Balay } 4728d25893d9SBarry Smith 4729abc0a331SBarry Smith if (snes->conv_hist_reset) snes->conv_hist_len = 0; 47309371c9d4SSatish Balay if (snes->counters_reset) { 47319371c9d4SSatish Balay snes->nfuncs = 0; 47329371c9d4SSatish Balay snes->linear_its = 0; 47339371c9d4SSatish Balay snes->numFailures = 0; 47349371c9d4SSatish Balay } 4735d5e45103SBarry Smith 47362d157150SStefano Zampini snes->reason = SNES_CONVERGED_ITERATING; 47379566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_Solve, snes, 0, 0, 0)); 4738dbbe0bcdSBarry Smith PetscUseTypeMethod(snes, solve); 47399566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_Solve, snes, 0, 0, 0)); 47402d157150SStefano Zampini PetscCheck(snes->reason, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error, solver %s returned without setting converged reason", ((PetscObject)snes)->type_name); 4741422a814eSBarry Smith snes->domainerror = PETSC_FALSE; /* clear the flag if it has been set */ 47423f149594SLisandro Dalcin 474337ec4e1aSPeter Brune if (snes->lagjac_persist) snes->jac_iter += snes->iter; 474437ec4e1aSPeter Brune if (snes->lagpre_persist) snes->pre_iter += snes->iter; 474537ec4e1aSPeter Brune 47469566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_test_local_min", NULL, NULL, &flg)); 47479566063dSJacob Faibussowitsch if (flg && !PetscPreLoadingOn) PetscCall(SNESTestLocalMin(snes)); 4748c4421ceaSFande Kong /* Call converged reason views. This may involve user-provided viewers as well */ 47499566063dSJacob Faibussowitsch PetscCall(SNESConvergedReasonViewFromOptions(snes)); 47505968eb51SBarry Smith 47515f80ce2aSJacob Faibussowitsch if (snes->errorifnotconverged) PetscCheck(snes->reason >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_NOT_CONVERGED, "SNESSolve has not converged"); 47529c8e83a9SBarry Smith if (snes->reason < 0) break; 4753efd51863SBarry Smith if (grid < snes->gridsequence) { 4754efd51863SBarry Smith DM fine; 4755efd51863SBarry Smith Vec xnew; 4756efd51863SBarry Smith Mat interp; 4757efd51863SBarry Smith 47589566063dSJacob Faibussowitsch PetscCall(DMRefine(snes->dm, PetscObjectComm((PetscObject)snes), &fine)); 47595f80ce2aSJacob Faibussowitsch PetscCheck(fine, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_INCOMP, "DMRefine() did not perform any refinement, cannot continue grid sequencing"); 47609566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(snes->dm, fine, &interp, NULL)); 47619566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(fine, &xnew)); 47629566063dSJacob Faibussowitsch PetscCall(MatInterpolate(interp, x, xnew)); 47639566063dSJacob Faibussowitsch PetscCall(DMInterpolate(snes->dm, interp, fine)); 47649566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interp)); 4765efd51863SBarry Smith x = xnew; 4766efd51863SBarry Smith 47679566063dSJacob Faibussowitsch PetscCall(SNESReset(snes)); 47689566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes, fine)); 47699566063dSJacob Faibussowitsch PetscCall(SNESResetFromOptions(snes)); 47709566063dSJacob Faibussowitsch PetscCall(DMDestroy(&fine)); 47719566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)))); 4772efd51863SBarry Smith } 4773efd51863SBarry Smith } 47749566063dSJacob Faibussowitsch PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view")); 47759566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(snes->vec_sol, (PetscObject)snes, "-snes_view_solution")); 47769566063dSJacob Faibussowitsch PetscCall(DMMonitor(snes->dm)); 47779566063dSJacob Faibussowitsch PetscCall(SNESMonitorPauseFinal_Internal(snes)); 47783f7e2da0SPeter Brune 47799566063dSJacob Faibussowitsch PetscCall(VecDestroy(&xcreated)); 47809566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsBlock((PetscObject)snes)); 47813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 47829b94acceSBarry Smith } 47839b94acceSBarry Smith 47849b94acceSBarry Smith /* --------- Internal routines for SNES Package --------- */ 47859b94acceSBarry Smith 4786cc4c1da9SBarry Smith /*@ 47874b0e389bSBarry Smith SNESSetType - Sets the method for the nonlinear solver. 47889b94acceSBarry Smith 4789c3339decSBarry Smith Collective 4790fee21e36SBarry Smith 4791c7afd0dbSLois Curfman McInnes Input Parameters: 4792f6dfbefdSBarry Smith + snes - the `SNES` context 4793454a90a3SBarry Smith - type - a known method 4794c7afd0dbSLois Curfman McInnes 4795c7afd0dbSLois Curfman McInnes Options Database Key: 4796454a90a3SBarry Smith . -snes_type <type> - Sets the method; use -help for a list 479704d7464bSBarry Smith of available methods (for instance, newtonls or newtontr) 4798ae12b187SLois Curfman McInnes 4799dc4c0fb0SBarry Smith Level: intermediate 4800dc4c0fb0SBarry Smith 48019b94acceSBarry Smith Notes: 4802e090d566SSatish Balay See "petsc/include/petscsnes.h" for available methods (for instance) 4803f6dfbefdSBarry Smith + `SNESNEWTONLS` - Newton's method with line search 4804c7afd0dbSLois Curfman McInnes (systems of nonlinear equations) 48054a221d59SStefano Zampini - `SNESNEWTONTR` - Newton's method with trust region 4806c7afd0dbSLois Curfman McInnes (systems of nonlinear equations) 48079b94acceSBarry Smith 4808f6dfbefdSBarry Smith Normally, it is best to use the `SNESSetFromOptions()` command and then 4809f6dfbefdSBarry Smith set the `SNES` solver type from the options database rather than by using 4810ae12b187SLois Curfman McInnes this routine. Using the options database provides the user with 4811ae12b187SLois Curfman McInnes maximum flexibility in evaluating the many nonlinear solvers. 4812f6dfbefdSBarry Smith The `SNESSetType()` routine is provided for those situations where it 4813ae12b187SLois Curfman McInnes is necessary to set the nonlinear solver independently of the command 4814ae12b187SLois Curfman McInnes line or options database. This might be the case, for example, when 4815ae12b187SLois Curfman McInnes the choice of solver changes during the execution of the program, 4816ae12b187SLois Curfman McInnes and the user's application is taking responsibility for choosing the 4817b0a32e0cSBarry Smith appropriate method. 481836851e7fSLois Curfman McInnes 4819420bcc1bSBarry Smith Developer Note: 4820f6dfbefdSBarry Smith `SNESRegister()` adds a constructor for a new `SNESType` to `SNESList`, `SNESSetType()` locates 4821f6dfbefdSBarry Smith the constructor in that list and calls it to create the specific object. 48228f6c3df8SBarry Smith 48231cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESType`, `SNESCreate()`, `SNESDestroy()`, `SNESGetType()`, `SNESSetFromOptions()` 48249b94acceSBarry Smith @*/ 4825d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetType(SNES snes, SNESType type) 4826d71ae5a4SJacob Faibussowitsch { 4827ace3abfcSBarry Smith PetscBool match; 48285f80ce2aSJacob Faibussowitsch PetscErrorCode (*r)(SNES); 48293a40ed3dSBarry Smith 48303a40ed3dSBarry Smith PetscFunctionBegin; 48310700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 48324f572ea9SToby Isaac PetscAssertPointer(type, 2); 483382bf6240SBarry Smith 48349566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes, type, &match)); 48353ba16761SJacob Faibussowitsch if (match) PetscFunctionReturn(PETSC_SUCCESS); 483692ff6ae8SBarry Smith 48379566063dSJacob Faibussowitsch PetscCall(PetscFunctionListFind(SNESList, type, &r)); 48386adde796SStefano Zampini PetscCheck(r, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested SNES type %s", type); 483975396ef9SLisandro Dalcin /* Destroy the previous private SNES context */ 4840dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, destroy); 484175396ef9SLisandro Dalcin /* Reinitialize function pointers in SNESOps structure */ 48429e5d0892SLisandro Dalcin snes->ops->setup = NULL; 48439e5d0892SLisandro Dalcin snes->ops->solve = NULL; 48449e5d0892SLisandro Dalcin snes->ops->view = NULL; 48459e5d0892SLisandro Dalcin snes->ops->setfromoptions = NULL; 48469e5d0892SLisandro Dalcin snes->ops->destroy = NULL; 48477fe760d5SStefano Zampini 48487fe760d5SStefano Zampini /* It may happen the user has customized the line search before calling SNESSetType */ 48499566063dSJacob Faibussowitsch if (((PetscObject)snes)->type_name) PetscCall(SNESLineSearchDestroy(&snes->linesearch)); 48507fe760d5SStefano Zampini 485175396ef9SLisandro Dalcin /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */ 485275396ef9SLisandro Dalcin snes->setupcalled = PETSC_FALSE; 4853f5af7f23SKarl Rupp 48549566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)snes, type)); 48559566063dSJacob Faibussowitsch PetscCall((*r)(snes)); 48563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 48579b94acceSBarry Smith } 48589b94acceSBarry Smith 4859cc4c1da9SBarry Smith /*@ 4860f6dfbefdSBarry Smith SNESGetType - Gets the `SNES` method type and name (as a string). 48619b94acceSBarry Smith 4862c7afd0dbSLois Curfman McInnes Not Collective 4863c7afd0dbSLois Curfman McInnes 48649b94acceSBarry Smith Input Parameter: 48654b0e389bSBarry Smith . snes - nonlinear solver context 48669b94acceSBarry Smith 48679b94acceSBarry Smith Output Parameter: 4868f6dfbefdSBarry Smith . type - `SNES` method (a character string) 48699b94acceSBarry Smith 487036851e7fSLois Curfman McInnes Level: intermediate 487136851e7fSLois Curfman McInnes 48721cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetType()`, `SNESType`, `SNESSetFromOptions()`, `SNES` 48739b94acceSBarry Smith @*/ 4874d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetType(SNES snes, SNESType *type) 4875d71ae5a4SJacob Faibussowitsch { 48763a40ed3dSBarry Smith PetscFunctionBegin; 48770700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 48784f572ea9SToby Isaac PetscAssertPointer(type, 2); 48797adad957SLisandro Dalcin *type = ((PetscObject)snes)->type_name; 48803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 48819b94acceSBarry Smith } 48829b94acceSBarry Smith 48833cd8a7caSMatthew G. Knepley /*@ 4884f6dfbefdSBarry Smith SNESSetSolution - Sets the solution vector for use by the `SNES` routines. 48853cd8a7caSMatthew G. Knepley 4886c3339decSBarry Smith Logically Collective 48873cd8a7caSMatthew G. Knepley 48883cd8a7caSMatthew G. Knepley Input Parameters: 4889f6dfbefdSBarry Smith + snes - the `SNES` context obtained from `SNESCreate()` 48903cd8a7caSMatthew G. Knepley - u - the solution vector 48913cd8a7caSMatthew G. Knepley 48923cd8a7caSMatthew G. Knepley Level: beginner 48933cd8a7caSMatthew G. Knepley 48941cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetSolution()`, `Vec` 48953cd8a7caSMatthew G. Knepley @*/ 4896d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetSolution(SNES snes, Vec u) 4897d71ae5a4SJacob Faibussowitsch { 48983cd8a7caSMatthew G. Knepley DM dm; 48993cd8a7caSMatthew G. Knepley 49003cd8a7caSMatthew G. Knepley PetscFunctionBegin; 49013cd8a7caSMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 49023cd8a7caSMatthew G. Knepley PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 49039566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)u)); 49049566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol)); 49053cd8a7caSMatthew G. Knepley 49063cd8a7caSMatthew G. Knepley snes->vec_sol = u; 49073cd8a7caSMatthew G. Knepley 49089566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 49099566063dSJacob Faibussowitsch PetscCall(DMShellSetGlobalVector(dm, u)); 49103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49113cd8a7caSMatthew G. Knepley } 49123cd8a7caSMatthew G. Knepley 491352baeb72SSatish Balay /*@ 49149b94acceSBarry Smith SNESGetSolution - Returns the vector where the approximate solution is 4915f6dfbefdSBarry Smith stored. This is the fine grid solution when using `SNESSetGridSequence()`. 49169b94acceSBarry Smith 4917420bcc1bSBarry Smith Not Collective, but `x` is parallel if `snes` is parallel 4918c7afd0dbSLois Curfman McInnes 49199b94acceSBarry Smith Input Parameter: 4920f6dfbefdSBarry Smith . snes - the `SNES` context 49219b94acceSBarry Smith 49229b94acceSBarry Smith Output Parameter: 49239b94acceSBarry Smith . x - the solution 49249b94acceSBarry Smith 492570e92668SMatthew Knepley Level: intermediate 492636851e7fSLois Curfman McInnes 49271cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetSolution()`, `SNESSolve()`, `SNES`, `SNESGetSolutionUpdate()`, `SNESGetFunction()` 49289b94acceSBarry Smith @*/ 4929d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolution(SNES snes, Vec *x) 4930d71ae5a4SJacob Faibussowitsch { 49313a40ed3dSBarry Smith PetscFunctionBegin; 49320700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 49334f572ea9SToby Isaac PetscAssertPointer(x, 2); 493485385478SLisandro Dalcin *x = snes->vec_sol; 49353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 493670e92668SMatthew Knepley } 493770e92668SMatthew Knepley 493852baeb72SSatish Balay /*@ 49399b94acceSBarry Smith SNESGetSolutionUpdate - Returns the vector where the solution update is 49409b94acceSBarry Smith stored. 49419b94acceSBarry Smith 4942420bcc1bSBarry Smith Not Collective, but `x` is parallel if `snes` is parallel 4943c7afd0dbSLois Curfman McInnes 49449b94acceSBarry Smith Input Parameter: 4945f6dfbefdSBarry Smith . snes - the `SNES` context 49469b94acceSBarry Smith 49479b94acceSBarry Smith Output Parameter: 49489b94acceSBarry Smith . x - the solution update 49499b94acceSBarry Smith 495036851e7fSLois Curfman McInnes Level: advanced 495136851e7fSLois Curfman McInnes 49521cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()` 49539b94acceSBarry Smith @*/ 4954d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionUpdate(SNES snes, Vec *x) 4955d71ae5a4SJacob Faibussowitsch { 49563a40ed3dSBarry Smith PetscFunctionBegin; 49570700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 49584f572ea9SToby Isaac PetscAssertPointer(x, 2); 495985385478SLisandro Dalcin *x = snes->vec_sol_update; 49603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49619b94acceSBarry Smith } 49629b94acceSBarry Smith 49639b94acceSBarry Smith /*@C 4964f6dfbefdSBarry Smith SNESGetFunction - Returns the function that defines the nonlinear system set with `SNESSetFunction()` 49659b94acceSBarry Smith 4966420bcc1bSBarry Smith Not Collective, but `r` is parallel if `snes` is parallel. Collective if `r` is requested, but has not been created yet. 4967c7afd0dbSLois Curfman McInnes 49689b94acceSBarry Smith Input Parameter: 4969f6dfbefdSBarry Smith . snes - the `SNES` context 49709b94acceSBarry Smith 4971d8d19677SJose E. Roman Output Parameters: 4972dc4c0fb0SBarry Smith + r - the vector that is used to store residuals (or `NULL` if you don't want it) 49738434afd1SBarry Smith . f - the function (or `NULL` if you don't want it); for calling sequence see `SNESFunctionFn` 4974dc4c0fb0SBarry Smith - ctx - the function context (or `NULL` if you don't want it) 49759b94acceSBarry Smith 497636851e7fSLois Curfman McInnes Level: advanced 497736851e7fSLois Curfman McInnes 4978f6dfbefdSBarry Smith Note: 4979dc4c0fb0SBarry Smith The vector `r` DOES NOT, in general, contain the current value of the `SNES` nonlinear function 498004edfde5SBarry Smith 49818434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetSolution()`, `SNESFunctionFn` 49829b94acceSBarry Smith @*/ 49838434afd1SBarry Smith PetscErrorCode SNESGetFunction(SNES snes, Vec *r, SNESFunctionFn **f, void **ctx) 4984d71ae5a4SJacob Faibussowitsch { 49856cab3a1bSJed Brown DM dm; 4986a63bb30eSJed Brown 49873a40ed3dSBarry Smith PetscFunctionBegin; 49880700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4989a63bb30eSJed Brown if (r) { 4990a63bb30eSJed Brown if (!snes->vec_func) { 4991a63bb30eSJed Brown if (snes->vec_rhs) { 49929566063dSJacob Faibussowitsch PetscCall(VecDuplicate(snes->vec_rhs, &snes->vec_func)); 4993a63bb30eSJed Brown } else if (snes->vec_sol) { 49949566063dSJacob Faibussowitsch PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_func)); 4995a63bb30eSJed Brown } else if (snes->dm) { 49969566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(snes->dm, &snes->vec_func)); 4997a63bb30eSJed Brown } 4998a63bb30eSJed Brown } 4999a63bb30eSJed Brown *r = snes->vec_func; 5000a63bb30eSJed Brown } 50019566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 50029566063dSJacob Faibussowitsch PetscCall(DMSNESGetFunction(dm, f, ctx)); 50033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50049b94acceSBarry Smith } 50059b94acceSBarry Smith 5006c79ef259SPeter Brune /*@C 500737fdd005SBarry Smith SNESGetNGS - Returns the function and context set with `SNESSetNGS()` 5008c79ef259SPeter Brune 5009c79ef259SPeter Brune Input Parameter: 5010f6dfbefdSBarry Smith . snes - the `SNES` context 5011c79ef259SPeter Brune 5012d8d19677SJose E. Roman Output Parameters: 50138434afd1SBarry Smith + f - the function (or `NULL`) see `SNESNGSFn` for calling sequence 5014dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`) 5015c79ef259SPeter Brune 5016c79ef259SPeter Brune Level: advanced 5017c79ef259SPeter Brune 50188434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetNGS()`, `SNESGetFunction()`, `SNESNGSFn` 5019c79ef259SPeter Brune @*/ 50208434afd1SBarry Smith PetscErrorCode SNESGetNGS(SNES snes, SNESNGSFn **f, void **ctx) 5021d71ae5a4SJacob Faibussowitsch { 50226cab3a1bSJed Brown DM dm; 50236cab3a1bSJed Brown 5024646217ecSPeter Brune PetscFunctionBegin; 5025646217ecSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 50269566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 50279566063dSJacob Faibussowitsch PetscCall(DMSNESGetNGS(dm, f, ctx)); 50283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5029646217ecSPeter Brune } 5030646217ecSPeter Brune 5031cc4c1da9SBarry Smith /*@ 50323c7409f5SSatish Balay SNESSetOptionsPrefix - Sets the prefix used for searching for all 5033f6dfbefdSBarry Smith `SNES` options in the database. 50343c7409f5SSatish Balay 5035c3339decSBarry Smith Logically Collective 5036fee21e36SBarry Smith 5037d8d19677SJose E. Roman Input Parameters: 5038f6dfbefdSBarry Smith + snes - the `SNES` context 5039c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names 5040c7afd0dbSLois Curfman McInnes 5041dc4c0fb0SBarry Smith Level: advanced 5042dc4c0fb0SBarry Smith 5043f6dfbefdSBarry Smith Note: 5044a83b1b31SSatish Balay A hyphen (-) must NOT be given at the beginning of the prefix name. 5045c7afd0dbSLois Curfman McInnes The first character of all runtime options is AUTOMATICALLY the hyphen. 5046d850072dSLois Curfman McInnes 50471cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESAppendOptionsPrefix()` 50483c7409f5SSatish Balay @*/ 5049d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetOptionsPrefix(SNES snes, const char prefix[]) 5050d71ae5a4SJacob Faibussowitsch { 50513a40ed3dSBarry Smith PetscFunctionBegin; 50520700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 50539566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes, prefix)); 50549566063dSJacob Faibussowitsch if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 505535f5d045SPeter Brune if (snes->linesearch) { 50569566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 50579566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch, prefix)); 505835f5d045SPeter Brune } 50599566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(snes->ksp, prefix)); 50603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50613c7409f5SSatish Balay } 50623c7409f5SSatish Balay 5063cc4c1da9SBarry Smith /*@ 5064f525115eSLois Curfman McInnes SNESAppendOptionsPrefix - Appends to the prefix used for searching for all 5065f6dfbefdSBarry Smith `SNES` options in the database. 50663c7409f5SSatish Balay 5067c3339decSBarry Smith Logically Collective 5068fee21e36SBarry Smith 5069c7afd0dbSLois Curfman McInnes Input Parameters: 5070f6dfbefdSBarry Smith + snes - the `SNES` context 5071c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names 5072c7afd0dbSLois Curfman McInnes 5073dc4c0fb0SBarry Smith Level: advanced 5074dc4c0fb0SBarry Smith 5075f6dfbefdSBarry Smith Note: 5076a83b1b31SSatish Balay A hyphen (-) must NOT be given at the beginning of the prefix name. 5077c7afd0dbSLois Curfman McInnes The first character of all runtime options is AUTOMATICALLY the hyphen. 5078d850072dSLois Curfman McInnes 50791cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetOptionsPrefix()`, `SNESSetOptionsPrefix()` 50803c7409f5SSatish Balay @*/ 5081d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESAppendOptionsPrefix(SNES snes, const char prefix[]) 5082d71ae5a4SJacob Faibussowitsch { 50833a40ed3dSBarry Smith PetscFunctionBegin; 50840700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 50859566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes, prefix)); 50869566063dSJacob Faibussowitsch if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 508735f5d045SPeter Brune if (snes->linesearch) { 50889566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 50899566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch, prefix)); 509035f5d045SPeter Brune } 50919566063dSJacob Faibussowitsch PetscCall(KSPAppendOptionsPrefix(snes->ksp, prefix)); 50923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50933c7409f5SSatish Balay } 50943c7409f5SSatish Balay 5095cc4c1da9SBarry Smith /*@ 5096f6dfbefdSBarry Smith SNESGetOptionsPrefix - Gets the prefix used for searching for all 5097f6dfbefdSBarry Smith `SNES` options in the database. 50983c7409f5SSatish Balay 5099c7afd0dbSLois Curfman McInnes Not Collective 5100c7afd0dbSLois Curfman McInnes 51013c7409f5SSatish Balay Input Parameter: 5102f6dfbefdSBarry Smith . snes - the `SNES` context 51033c7409f5SSatish Balay 51043c7409f5SSatish Balay Output Parameter: 51053c7409f5SSatish Balay . prefix - pointer to the prefix string used 51063c7409f5SSatish Balay 510736851e7fSLois Curfman McInnes Level: advanced 510836851e7fSLois Curfman McInnes 5109420bcc1bSBarry Smith Fortran Note: 5110dc4c0fb0SBarry Smith The user should pass in a string 'prefix' of 5111dc4c0fb0SBarry Smith sufficient length to hold the prefix. 5112dc4c0fb0SBarry Smith 51131cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetOptionsPrefix()`, `SNESAppendOptionsPrefix()` 51143c7409f5SSatish Balay @*/ 5115d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetOptionsPrefix(SNES snes, const char *prefix[]) 5116d71ae5a4SJacob Faibussowitsch { 51173a40ed3dSBarry Smith PetscFunctionBegin; 51180700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 51199566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)snes, prefix)); 51203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 51213c7409f5SSatish Balay } 51223c7409f5SSatish Balay 51233cea93caSBarry Smith /*@C 51241c84c290SBarry Smith SNESRegister - Adds a method to the nonlinear solver package. 51251c84c290SBarry Smith 512620f4b53cSBarry Smith Not Collective 51271c84c290SBarry Smith 51281c84c290SBarry Smith Input Parameters: 512920f4b53cSBarry Smith + sname - name of a new user-defined solver 513020f4b53cSBarry Smith - function - routine to create method context 51311c84c290SBarry Smith 5132dc4c0fb0SBarry Smith Level: advanced 5133dc4c0fb0SBarry Smith 5134f6dfbefdSBarry Smith Note: 5135f6dfbefdSBarry Smith `SNESRegister()` may be called multiple times to add several user-defined solvers. 51361c84c290SBarry Smith 5137e4094ef1SJacob Faibussowitsch Example Usage: 51381c84c290SBarry Smith .vb 5139bdf89e91SBarry Smith SNESRegister("my_solver", MySolverCreate); 51401c84c290SBarry Smith .ve 51411c84c290SBarry Smith 51421c84c290SBarry Smith Then, your solver can be chosen with the procedural interface via 51431c84c290SBarry Smith $ SNESSetType(snes, "my_solver") 51441c84c290SBarry Smith or at runtime via the option 51451c84c290SBarry Smith $ -snes_type my_solver 51461c84c290SBarry Smith 51471cc06b55SBarry Smith .seealso: [](ch_snes), `SNESRegisterAll()`, `SNESRegisterDestroy()` 51483cea93caSBarry Smith @*/ 5149d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESRegister(const char sname[], PetscErrorCode (*function)(SNES)) 5150d71ae5a4SJacob Faibussowitsch { 5151b2002411SLois Curfman McInnes PetscFunctionBegin; 51529566063dSJacob Faibussowitsch PetscCall(SNESInitializePackage()); 51539566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&SNESList, sname, function)); 51543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5155b2002411SLois Curfman McInnes } 5156da9b6338SBarry Smith 5157d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestLocalMin(SNES snes) 5158d71ae5a4SJacob Faibussowitsch { 515977431f27SBarry Smith PetscInt N, i, j; 5160da9b6338SBarry Smith Vec u, uh, fh; 5161da9b6338SBarry Smith PetscScalar value; 5162da9b6338SBarry Smith PetscReal norm; 5163da9b6338SBarry Smith 5164da9b6338SBarry Smith PetscFunctionBegin; 51659566063dSJacob Faibussowitsch PetscCall(SNESGetSolution(snes, &u)); 51669566063dSJacob Faibussowitsch PetscCall(VecDuplicate(u, &uh)); 51679566063dSJacob Faibussowitsch PetscCall(VecDuplicate(u, &fh)); 5168da9b6338SBarry Smith 5169da9b6338SBarry Smith /* currently only works for sequential */ 51709566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Testing FormFunction() for local min\n")); 51719566063dSJacob Faibussowitsch PetscCall(VecGetSize(u, &N)); 5172da9b6338SBarry Smith for (i = 0; i < N; i++) { 51739566063dSJacob Faibussowitsch PetscCall(VecCopy(u, uh)); 517463a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "i = %" PetscInt_FMT "\n", i)); 5175da9b6338SBarry Smith for (j = -10; j < 11; j++) { 51768b49ba18SBarry Smith value = PetscSign(j) * PetscExpReal(PetscAbs(j) - 10.0); 51779566063dSJacob Faibussowitsch PetscCall(VecSetValue(uh, i, value, ADD_VALUES)); 51789566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, uh, fh)); 51799566063dSJacob Faibussowitsch PetscCall(VecNorm(fh, NORM_2, &norm)); 518063a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), " j norm %" PetscInt_FMT " %18.16e\n", j, (double)norm)); 5181da9b6338SBarry Smith value = -value; 51829566063dSJacob Faibussowitsch PetscCall(VecSetValue(uh, i, value, ADD_VALUES)); 5183da9b6338SBarry Smith } 5184da9b6338SBarry Smith } 51859566063dSJacob Faibussowitsch PetscCall(VecDestroy(&uh)); 51869566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fh)); 51873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5188da9b6338SBarry Smith } 518971f87433Sdalcinl 519071f87433Sdalcinl /*@ 5191f6dfbefdSBarry Smith SNESKSPSetUseEW - Sets `SNES` to the use Eisenstat-Walker method for 519271f87433Sdalcinl computing relative tolerance for linear solvers within an inexact 519371f87433Sdalcinl Newton method. 519471f87433Sdalcinl 5195c3339decSBarry Smith Logically Collective 519671f87433Sdalcinl 519771f87433Sdalcinl Input Parameters: 5198f6dfbefdSBarry Smith + snes - `SNES` context 5199f6dfbefdSBarry Smith - flag - `PETSC_TRUE` or `PETSC_FALSE` 520071f87433Sdalcinl 5201f6dfbefdSBarry Smith Options Database Keys: 520264ba62caSBarry Smith + -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence 520364ba62caSBarry Smith . -snes_ksp_ew_version ver - version of Eisenstat-Walker method 520464ba62caSBarry Smith . -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0 520564ba62caSBarry Smith . -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax 520664ba62caSBarry Smith . -snes_ksp_ew_gamma <gamma> - Sets gamma 520764ba62caSBarry Smith . -snes_ksp_ew_alpha <alpha> - Sets alpha 520864ba62caSBarry Smith . -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2 520964ba62caSBarry Smith - -snes_ksp_ew_threshold <threshold> - Sets threshold 521064ba62caSBarry Smith 5211dc4c0fb0SBarry Smith Level: advanced 5212dc4c0fb0SBarry Smith 5213f6dfbefdSBarry Smith Note: 5214f6dfbefdSBarry Smith The default is to use a constant relative tolerance for 521571f87433Sdalcinl the inner linear solvers. Alternatively, one can use the 52161d27aa22SBarry Smith Eisenstat-Walker method {cite}`ew96`, where the relative convergence tolerance 521771f87433Sdalcinl is reset at each Newton iteration according progress of the nonlinear 521871f87433Sdalcinl solver. 521971f87433Sdalcinl 52201cc06b55SBarry Smith .seealso: [](ch_snes), `KSP`, `SNES`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()` 522171f87433Sdalcinl @*/ 5222d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetUseEW(SNES snes, PetscBool flag) 5223d71ae5a4SJacob Faibussowitsch { 522471f87433Sdalcinl PetscFunctionBegin; 52250700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5226acfcf0e5SJed Brown PetscValidLogicalCollectiveBool(snes, flag, 2); 522771f87433Sdalcinl snes->ksp_ewconv = flag; 52283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 522971f87433Sdalcinl } 523071f87433Sdalcinl 523171f87433Sdalcinl /*@ 5232f6dfbefdSBarry Smith SNESKSPGetUseEW - Gets if `SNES` is using Eisenstat-Walker method 523371f87433Sdalcinl for computing relative tolerance for linear solvers within an 523471f87433Sdalcinl inexact Newton method. 523571f87433Sdalcinl 523671f87433Sdalcinl Not Collective 523771f87433Sdalcinl 523871f87433Sdalcinl Input Parameter: 5239f6dfbefdSBarry Smith . snes - `SNES` context 524071f87433Sdalcinl 524171f87433Sdalcinl Output Parameter: 5242f6dfbefdSBarry Smith . flag - `PETSC_TRUE` or `PETSC_FALSE` 524371f87433Sdalcinl 524471f87433Sdalcinl Level: advanced 524571f87433Sdalcinl 52461cc06b55SBarry Smith .seealso: [](ch_snes), `SNESKSPSetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()` 524771f87433Sdalcinl @*/ 5248d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag) 5249d71ae5a4SJacob Faibussowitsch { 525071f87433Sdalcinl PetscFunctionBegin; 52510700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 52524f572ea9SToby Isaac PetscAssertPointer(flag, 2); 525371f87433Sdalcinl *flag = snes->ksp_ewconv; 52543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 525571f87433Sdalcinl } 525671f87433Sdalcinl 525771f87433Sdalcinl /*@ 5258fa9f3622SBarry Smith SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker 525971f87433Sdalcinl convergence criteria for the linear solvers within an inexact 526071f87433Sdalcinl Newton method. 526171f87433Sdalcinl 5262c3339decSBarry Smith Logically Collective 526371f87433Sdalcinl 526471f87433Sdalcinl Input Parameters: 5265f6dfbefdSBarry Smith + snes - `SNES` context 52660f0abf79SStefano Zampini . version - version 1, 2 (default is 2), 3 or 4 526771f87433Sdalcinl . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 526871f87433Sdalcinl . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 526971f87433Sdalcinl . gamma - multiplicative factor for version 2 rtol computation 527071f87433Sdalcinl (0 <= gamma2 <= 1) 527171f87433Sdalcinl . alpha - power for version 2 rtol computation (1 < alpha <= 2) 527271f87433Sdalcinl . alpha2 - power for safeguard 527371f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1) 527471f87433Sdalcinl 5275dc4c0fb0SBarry Smith Level: advanced 5276dc4c0fb0SBarry Smith 5277f6dfbefdSBarry Smith Notes: 527871f87433Sdalcinl Version 3 was contributed by Luis Chacon, June 2006. 527971f87433Sdalcinl 5280f6dfbefdSBarry Smith Use `PETSC_DEFAULT` to retain the default for any of the parameters. 528171f87433Sdalcinl 52821cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()` 528371f87433Sdalcinl @*/ 5284d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetParametersEW(SNES snes, PetscInt version, PetscReal rtol_0, PetscReal rtol_max, PetscReal gamma, PetscReal alpha, PetscReal alpha2, PetscReal threshold) 5285d71ae5a4SJacob Faibussowitsch { 5286fa9f3622SBarry Smith SNESKSPEW *kctx; 52875fd66863SKarl Rupp 528871f87433Sdalcinl PetscFunctionBegin; 52890700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5290fa9f3622SBarry Smith kctx = (SNESKSPEW *)snes->kspconvctx; 52915f80ce2aSJacob Faibussowitsch PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing"); 5292c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, version, 2); 5293c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, rtol_0, 3); 5294c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, rtol_max, 4); 5295c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, gamma, 5); 5296c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, alpha, 6); 5297c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, alpha2, 7); 5298c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, threshold, 8); 529971f87433Sdalcinl 530071f87433Sdalcinl if (version != PETSC_DEFAULT) kctx->version = version; 530113bcc0bdSJacob Faibussowitsch if (rtol_0 != (PetscReal)PETSC_DEFAULT) kctx->rtol_0 = rtol_0; 530213bcc0bdSJacob Faibussowitsch if (rtol_max != (PetscReal)PETSC_DEFAULT) kctx->rtol_max = rtol_max; 530313bcc0bdSJacob Faibussowitsch if (gamma != (PetscReal)PETSC_DEFAULT) kctx->gamma = gamma; 530413bcc0bdSJacob Faibussowitsch if (alpha != (PetscReal)PETSC_DEFAULT) kctx->alpha = alpha; 530513bcc0bdSJacob Faibussowitsch if (alpha2 != (PetscReal)PETSC_DEFAULT) kctx->alpha2 = alpha2; 530613bcc0bdSJacob Faibussowitsch if (threshold != (PetscReal)PETSC_DEFAULT) kctx->threshold = threshold; 530771f87433Sdalcinl 53080f0abf79SStefano 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); 53090b121fc5SBarry 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); 53100b121fc5SBarry 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); 53110b121fc5SBarry 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); 53120b121fc5SBarry 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); 53130b121fc5SBarry 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); 53143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 531571f87433Sdalcinl } 531671f87433Sdalcinl 531771f87433Sdalcinl /*@ 5318fa9f3622SBarry Smith SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker 531971f87433Sdalcinl convergence criteria for the linear solvers within an inexact 532071f87433Sdalcinl Newton method. 532171f87433Sdalcinl 532271f87433Sdalcinl Not Collective 532371f87433Sdalcinl 532497bb3fdcSJose E. Roman Input Parameter: 5325f6dfbefdSBarry Smith . snes - `SNES` context 532671f87433Sdalcinl 532771f87433Sdalcinl Output Parameters: 53280f0abf79SStefano Zampini + version - version 1, 2 (default is 2), 3 or 4 532971f87433Sdalcinl . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 533071f87433Sdalcinl . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 5331bf388a1fSBarry Smith . gamma - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1) 533271f87433Sdalcinl . alpha - power for version 2 rtol computation (1 < alpha <= 2) 533371f87433Sdalcinl . alpha2 - power for safeguard 533471f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1) 533571f87433Sdalcinl 533671f87433Sdalcinl Level: advanced 533771f87433Sdalcinl 53381cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPSetParametersEW()` 533971f87433Sdalcinl @*/ 5340d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetParametersEW(SNES snes, PetscInt *version, PetscReal *rtol_0, PetscReal *rtol_max, PetscReal *gamma, PetscReal *alpha, PetscReal *alpha2, PetscReal *threshold) 5341d71ae5a4SJacob Faibussowitsch { 5342fa9f3622SBarry Smith SNESKSPEW *kctx; 53435fd66863SKarl Rupp 534471f87433Sdalcinl PetscFunctionBegin; 53450700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5346fa9f3622SBarry Smith kctx = (SNESKSPEW *)snes->kspconvctx; 53475f80ce2aSJacob Faibussowitsch PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing"); 534871f87433Sdalcinl if (version) *version = kctx->version; 534971f87433Sdalcinl if (rtol_0) *rtol_0 = kctx->rtol_0; 535071f87433Sdalcinl if (rtol_max) *rtol_max = kctx->rtol_max; 535171f87433Sdalcinl if (gamma) *gamma = kctx->gamma; 535271f87433Sdalcinl if (alpha) *alpha = kctx->alpha; 535371f87433Sdalcinl if (alpha2) *alpha2 = kctx->alpha2; 535471f87433Sdalcinl if (threshold) *threshold = kctx->threshold; 53553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 535671f87433Sdalcinl } 535771f87433Sdalcinl 53585c0db29aSPierre Jolivet PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx) 5359d71ae5a4SJacob Faibussowitsch { 53605c0db29aSPierre Jolivet SNES snes = (SNES)ctx; 5361fa9f3622SBarry Smith SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx; 536271f87433Sdalcinl PetscReal rtol = PETSC_DEFAULT, stol; 536371f87433Sdalcinl 536471f87433Sdalcinl PetscFunctionBegin; 53653ba16761SJacob Faibussowitsch if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS); 536630058271SDmitry Karpeev if (!snes->iter) { 536730058271SDmitry Karpeev rtol = kctx->rtol_0; /* first time in, so use the original user rtol */ 53689566063dSJacob Faibussowitsch PetscCall(VecNorm(snes->vec_func, NORM_2, &kctx->norm_first)); 53690f0abf79SStefano Zampini } else { 53700fdf79fbSJacob 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); 537171f87433Sdalcinl if (kctx->version == 1) { 53720f0abf79SStefano Zampini rtol = PetscAbsReal(snes->norm - kctx->lresid_last) / kctx->norm_last; 537385ec1a3cSBarry Smith stol = PetscPowReal(kctx->rtol_last, kctx->alpha2); 537471f87433Sdalcinl if (stol > kctx->threshold) rtol = PetscMax(rtol, stol); 537571f87433Sdalcinl } else if (kctx->version == 2) { 537685ec1a3cSBarry Smith rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha); 537785ec1a3cSBarry Smith stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha); 537871f87433Sdalcinl if (stol > kctx->threshold) rtol = PetscMax(rtol, stol); 537971f87433Sdalcinl } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */ 538085ec1a3cSBarry Smith rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha); 538171f87433Sdalcinl /* safeguard: avoid sharp decrease of rtol */ 538285ec1a3cSBarry Smith stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha); 538371f87433Sdalcinl stol = PetscMax(rtol, stol); 538471f87433Sdalcinl rtol = PetscMin(kctx->rtol_0, stol); 538571f87433Sdalcinl /* safeguard: avoid oversolving */ 538630058271SDmitry Karpeev stol = kctx->gamma * (kctx->norm_first * snes->rtol) / snes->norm; 538771f87433Sdalcinl stol = PetscMax(rtol, stol); 538871f87433Sdalcinl rtol = PetscMin(kctx->rtol_0, stol); 53890fdf79fbSJacob Faibussowitsch } else /* if (kctx->version == 4) */ { 53900fdf79fbSJacob Faibussowitsch /* H.-B. An et al. Journal of Computational and Applied Mathematics 200 (2007) 47-60 */ 53910f0abf79SStefano Zampini PetscReal ared = PetscAbsReal(kctx->norm_last - snes->norm); 53920f0abf79SStefano Zampini PetscReal pred = PetscAbsReal(kctx->norm_last - kctx->lresid_last); 53930f0abf79SStefano Zampini PetscReal rk = ared / pred; 53940f0abf79SStefano Zampini if (rk < kctx->v4_p1) rtol = 1. - 2. * kctx->v4_p1; 53950f0abf79SStefano Zampini else if (rk < kctx->v4_p2) rtol = kctx->rtol_last; 53960f0abf79SStefano Zampini else if (rk < kctx->v4_p3) rtol = kctx->v4_m1 * kctx->rtol_last; 53970f0abf79SStefano Zampini else rtol = kctx->v4_m2 * kctx->rtol_last; 53980f0abf79SStefano Zampini 5399a4598233SStefano 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; 54000f0abf79SStefano Zampini kctx->rtol_last_2 = kctx->rtol_last; 54010f0abf79SStefano Zampini kctx->rk_last_2 = kctx->rk_last; 54020f0abf79SStefano Zampini kctx->rk_last = rk; 54030fdf79fbSJacob Faibussowitsch } 54040f0abf79SStefano Zampini } 54050f0abf79SStefano Zampini /* safeguard: avoid rtol greater than rtol_max */ 540671f87433Sdalcinl rtol = PetscMin(rtol, kctx->rtol_max); 54079566063dSJacob Faibussowitsch PetscCall(KSPSetTolerances(ksp, rtol, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT)); 540863a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "iter %" PetscInt_FMT ", Eisenstat-Walker (version %" PetscInt_FMT ") KSP rtol=%g\n", snes->iter, kctx->version, (double)rtol)); 54093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 541071f87433Sdalcinl } 541171f87433Sdalcinl 54125c0db29aSPierre Jolivet PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx) 5413d71ae5a4SJacob Faibussowitsch { 54145c0db29aSPierre Jolivet SNES snes = (SNES)ctx; 5415fa9f3622SBarry Smith SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx; 541671f87433Sdalcinl PCSide pcside; 541771f87433Sdalcinl Vec lres; 541871f87433Sdalcinl 541971f87433Sdalcinl PetscFunctionBegin; 54203ba16761SJacob Faibussowitsch if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS); 54219566063dSJacob Faibussowitsch PetscCall(KSPGetTolerances(ksp, &kctx->rtol_last, NULL, NULL, NULL)); 542271dbe336SPeter Brune kctx->norm_last = snes->norm; 54230f0abf79SStefano Zampini if (kctx->version == 1 || kctx->version == 4) { 54244f00ce20SMatthew G. Knepley PC pc; 54250f0abf79SStefano Zampini PetscBool getRes; 54264f00ce20SMatthew G. Knepley 54279566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksp, &pc)); 54280f0abf79SStefano Zampini PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &getRes)); 54290f0abf79SStefano Zampini if (!getRes) { 54300f0abf79SStefano Zampini KSPNormType normtype; 54310f0abf79SStefano Zampini 54320f0abf79SStefano Zampini PetscCall(KSPGetNormType(ksp, &normtype)); 54330f0abf79SStefano Zampini getRes = (PetscBool)(normtype == KSP_NORM_UNPRECONDITIONED); 54340f0abf79SStefano Zampini } 54359566063dSJacob Faibussowitsch PetscCall(KSPGetPCSide(ksp, &pcside)); 54360f0abf79SStefano Zampini if (pcside == PC_RIGHT || getRes) { /* KSP residual is true linear residual */ 54379566063dSJacob Faibussowitsch PetscCall(KSPGetResidualNorm(ksp, &kctx->lresid_last)); 543871f87433Sdalcinl } else { 543971f87433Sdalcinl /* KSP residual is preconditioned residual */ 544071f87433Sdalcinl /* compute true linear residual norm */ 54410f0abf79SStefano Zampini Mat J; 54420f0abf79SStefano Zampini PetscCall(KSPGetOperators(ksp, &J, NULL)); 54439566063dSJacob Faibussowitsch PetscCall(VecDuplicate(b, &lres)); 54440f0abf79SStefano Zampini PetscCall(MatMult(J, x, lres)); 54459566063dSJacob Faibussowitsch PetscCall(VecAYPX(lres, -1.0, b)); 54469566063dSJacob Faibussowitsch PetscCall(VecNorm(lres, NORM_2, &kctx->lresid_last)); 54479566063dSJacob Faibussowitsch PetscCall(VecDestroy(&lres)); 544871f87433Sdalcinl } 544971f87433Sdalcinl } 54503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 545171f87433Sdalcinl } 545271f87433Sdalcinl 5453d4211eb9SBarry Smith /*@ 5454f6dfbefdSBarry Smith SNESGetKSP - Returns the `KSP` context for a `SNES` solver. 5455d4211eb9SBarry Smith 5456420bcc1bSBarry Smith Not Collective, but if `snes` is parallel, then `ksp` is parallel 5457d4211eb9SBarry Smith 5458d4211eb9SBarry Smith Input Parameter: 5459f6dfbefdSBarry Smith . snes - the `SNES` context 5460d4211eb9SBarry Smith 5461d4211eb9SBarry Smith Output Parameter: 5462f6dfbefdSBarry Smith . ksp - the `KSP` context 5463d4211eb9SBarry Smith 5464dc4c0fb0SBarry Smith Level: beginner 5465dc4c0fb0SBarry Smith 5466d4211eb9SBarry Smith Notes: 5467f6dfbefdSBarry Smith The user can then directly manipulate the `KSP` context to set various 5468d4211eb9SBarry Smith options, etc. Likewise, the user can then extract and manipulate the 5469f6dfbefdSBarry Smith `PC` contexts as well. 5470f6dfbefdSBarry Smith 5471f6dfbefdSBarry Smith Some `SNESType`s do not use a `KSP` but a `KSP` is still returned by this function 5472d4211eb9SBarry Smith 54731cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSP`, `PC`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()` 5474d4211eb9SBarry Smith @*/ 5475d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetKSP(SNES snes, KSP *ksp) 5476d71ae5a4SJacob Faibussowitsch { 547771f87433Sdalcinl PetscFunctionBegin; 5478d4211eb9SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 54794f572ea9SToby Isaac PetscAssertPointer(ksp, 2); 5480d4211eb9SBarry Smith 5481d4211eb9SBarry Smith if (!snes->ksp) { 54829566063dSJacob Faibussowitsch PetscCall(KSPCreate(PetscObjectComm((PetscObject)snes), &snes->ksp)); 54839566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->ksp, (PetscObject)snes, 1)); 5484d4211eb9SBarry Smith 54855c0db29aSPierre Jolivet PetscCall(KSPSetPreSolve(snes->ksp, KSPPreSolve_SNESEW, snes)); 54865c0db29aSPierre Jolivet PetscCall(KSPSetPostSolve(snes->ksp, KSPPostSolve_SNESEW, snes)); 5487a5c2985bSBarry Smith 54889566063dSJacob Faibussowitsch PetscCall(KSPMonitorSetFromOptions(snes->ksp, "-snes_monitor_ksp", "snes_preconditioned_residual", snes)); 54899566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptions((PetscObject)snes->ksp, ((PetscObject)snes)->options)); 5490d4211eb9SBarry Smith } 5491d4211eb9SBarry Smith *ksp = snes->ksp; 54923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 549371f87433Sdalcinl } 54946c699258SBarry Smith 5495af0996ceSBarry Smith #include <petsc/private/dmimpl.h> 54966c699258SBarry Smith /*@ 5497f6dfbefdSBarry Smith SNESSetDM - Sets the `DM` that may be used by some nonlinear solvers or their underlying preconditioners 54986c699258SBarry Smith 5499c3339decSBarry Smith Logically Collective 55006c699258SBarry Smith 55016c699258SBarry Smith Input Parameters: 55022a808120SBarry Smith + snes - the nonlinear solver context 5503420bcc1bSBarry Smith - dm - the `DM`, cannot be `NULL` 5504dc4c0fb0SBarry Smith 5505dc4c0fb0SBarry Smith Level: intermediate 55066c699258SBarry Smith 5507f6dfbefdSBarry Smith Note: 5508f6dfbefdSBarry Smith A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`, 5509f6dfbefdSBarry Smith even when not using interfaces like `DMSNESSetFunction()`. Use `DMClone()` to get a distinct `DM` when solving different 5510e03a659cSJed Brown problems using the same function space. 5511e03a659cSJed Brown 5512420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()` 55136c699258SBarry Smith @*/ 5514d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDM(SNES snes, DM dm) 5515d71ae5a4SJacob Faibussowitsch { 5516345fed2cSBarry Smith KSP ksp; 5517942e3340SBarry Smith DMSNES sdm; 55186c699258SBarry Smith 55196c699258SBarry Smith PetscFunctionBegin; 55200700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 55212a808120SBarry Smith PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 55229566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 5523942e3340SBarry Smith if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */ 552451f4b3c7SToby Isaac if (snes->dm->dmsnes && !dm->dmsnes) { 55259566063dSJacob Faibussowitsch PetscCall(DMCopyDMSNES(snes->dm, dm)); 55269566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(snes->dm, &sdm)); 5527f5af7f23SKarl Rupp if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */ 55286cab3a1bSJed Brown } 55299566063dSJacob Faibussowitsch PetscCall(DMCoarsenHookRemove(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes)); 55309566063dSJacob Faibussowitsch PetscCall(DMDestroy(&snes->dm)); 55316cab3a1bSJed Brown } 55326c699258SBarry Smith snes->dm = dm; 5533116d1032SJed Brown snes->dmAuto = PETSC_FALSE; 5534f5af7f23SKarl Rupp 55359566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 55369566063dSJacob Faibussowitsch PetscCall(KSPSetDM(ksp, dm)); 55379566063dSJacob Faibussowitsch PetscCall(KSPSetDMActive(ksp, PETSC_FALSE)); 5538efd4aadfSBarry Smith if (snes->npc) { 55399566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes->npc, snes->dm)); 55409566063dSJacob Faibussowitsch PetscCall(SNESSetNPCSide(snes, snes->npcside)); 55412c155ee1SBarry Smith } 55423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 55436c699258SBarry Smith } 55446c699258SBarry Smith 55456c699258SBarry Smith /*@ 5546420bcc1bSBarry Smith SNESGetDM - Gets the `DM` that may be used by some solvers/preconditioners 55476c699258SBarry Smith 5548f6dfbefdSBarry Smith Not Collective but dm obtained is parallel on snes 55496c699258SBarry Smith 55506c699258SBarry Smith Input Parameter: 5551420bcc1bSBarry Smith . snes - the `SNES` context 55526c699258SBarry Smith 55536c699258SBarry Smith Output Parameter: 5554420bcc1bSBarry Smith . dm - the `DM` 55556c699258SBarry Smith 55566c699258SBarry Smith Level: intermediate 55576c699258SBarry Smith 5558420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESSetDM()`, `KSPSetDM()`, `KSPGetDM()` 55596c699258SBarry Smith @*/ 5560d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDM(SNES snes, DM *dm) 5561d71ae5a4SJacob Faibussowitsch { 55626c699258SBarry Smith PetscFunctionBegin; 55630700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 55646cab3a1bSJed Brown if (!snes->dm) { 55659566063dSJacob Faibussowitsch PetscCall(DMShellCreate(PetscObjectComm((PetscObject)snes), &snes->dm)); 5566116d1032SJed Brown snes->dmAuto = PETSC_TRUE; 55676cab3a1bSJed Brown } 55686c699258SBarry Smith *dm = snes->dm; 55693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 55706c699258SBarry Smith } 55710807856dSBarry Smith 557231823bd8SMatthew G Knepley /*@ 5573be95d8f1SBarry Smith SNESSetNPC - Sets the nonlinear preconditioner to be used. 557431823bd8SMatthew G Knepley 5575c3339decSBarry Smith Collective 557631823bd8SMatthew G Knepley 557731823bd8SMatthew G Knepley Input Parameters: 5578f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 5579420bcc1bSBarry Smith - npc - the nonlinear preconditioner object 558031823bd8SMatthew G Knepley 5581dc4c0fb0SBarry Smith Level: developer 5582dc4c0fb0SBarry Smith 558331823bd8SMatthew G Knepley Notes: 5584f6dfbefdSBarry Smith Use `SNESGetNPC()` to retrieve the preconditioner context (for example, 558531823bd8SMatthew G Knepley to configure it using the API). 558631823bd8SMatthew G Knepley 5587f6dfbefdSBarry Smith Only some `SNESType` can use a nonlinear preconditioner 5588f6dfbefdSBarry Smith 5589420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNGS`, `SNESFAS`, `SNESGetNPC()`, `SNESHasNPC()` 559031823bd8SMatthew G Knepley @*/ 5591d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPC(SNES snes, SNES npc) 5592d71ae5a4SJacob Faibussowitsch { 559331823bd8SMatthew G Knepley PetscFunctionBegin; 559431823bd8SMatthew G Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5595f6dfbefdSBarry Smith PetscValidHeaderSpecific(npc, SNES_CLASSID, 2); 5596f6dfbefdSBarry Smith PetscCheckSameComm(snes, 1, npc, 2); 5597f6dfbefdSBarry Smith PetscCall(PetscObjectReference((PetscObject)npc)); 55989566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&snes->npc)); 5599f6dfbefdSBarry Smith snes->npc = npc; 56003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 560131823bd8SMatthew G Knepley } 560231823bd8SMatthew G Knepley 560331823bd8SMatthew G Knepley /*@ 5604f6dfbefdSBarry Smith SNESGetNPC - Gets a nonlinear preconditioning solver SNES` to be used to precondition the original nonlinear solver. 560531823bd8SMatthew G Knepley 5606f6dfbefdSBarry Smith Not Collective; but any changes to the obtained the npc object must be applied collectively 560731823bd8SMatthew G Knepley 560831823bd8SMatthew G Knepley Input Parameter: 5609f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 561031823bd8SMatthew G Knepley 561131823bd8SMatthew G Knepley Output Parameter: 5612e4094ef1SJacob Faibussowitsch . pc - preconditioner context 561331823bd8SMatthew G Knepley 5614f6dfbefdSBarry Smith Options Database Key: 5615f6dfbefdSBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner 5616b5badacbSBarry Smith 5617dc4c0fb0SBarry Smith Level: developer 5618dc4c0fb0SBarry Smith 561995452b02SPatrick Sanan Notes: 5620f6dfbefdSBarry Smith If a `SNES` was previously set with `SNESSetNPC()` then that value is returned, otherwise a new `SNES` object is created. 5621be95d8f1SBarry Smith 5622f6dfbefdSBarry Smith The (preconditioner) `SNES` returned automatically inherits the same nonlinear function and Jacobian supplied to the original 5623f6dfbefdSBarry Smith `SNES` 5624951fe5abSBarry Smith 56251cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESHasNPC()`, `SNES`, `SNESCreate()` 562631823bd8SMatthew G Knepley @*/ 5627d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPC(SNES snes, SNES *pc) 5628d71ae5a4SJacob Faibussowitsch { 5629a64e098fSPeter Brune const char *optionsprefix; 563031823bd8SMatthew G Knepley 563131823bd8SMatthew G Knepley PetscFunctionBegin; 563231823bd8SMatthew G Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 56334f572ea9SToby Isaac PetscAssertPointer(pc, 2); 5634efd4aadfSBarry Smith if (!snes->npc) { 5635ec785e5bSStefano Zampini void *ctx; 5636ec785e5bSStefano Zampini 56379566063dSJacob Faibussowitsch PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &snes->npc)); 56389566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->npc, (PetscObject)snes, 1)); 56399566063dSJacob Faibussowitsch PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 56409566063dSJacob Faibussowitsch PetscCall(SNESSetOptionsPrefix(snes->npc, optionsprefix)); 56419566063dSJacob Faibussowitsch PetscCall(SNESAppendOptionsPrefix(snes->npc, "npc_")); 5642fb87a551SStefano Zampini if (snes->ops->usercompute) { 5643fb87a551SStefano Zampini PetscCall(SNESSetComputeApplicationContext(snes, snes->ops->usercompute, snes->ops->userdestroy)); 5644fb87a551SStefano Zampini } else { 5645ec785e5bSStefano Zampini PetscCall(SNESGetApplicationContext(snes, &ctx)); 5646ec785e5bSStefano Zampini PetscCall(SNESSetApplicationContext(snes->npc, ctx)); 5647fb87a551SStefano Zampini } 56489566063dSJacob Faibussowitsch PetscCall(SNESSetCountersReset(snes->npc, PETSC_FALSE)); 564931823bd8SMatthew G Knepley } 5650efd4aadfSBarry Smith *pc = snes->npc; 56513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 565231823bd8SMatthew G Knepley } 565331823bd8SMatthew G Knepley 56543ad1a0b9SPatrick Farrell /*@ 56553ad1a0b9SPatrick Farrell SNESHasNPC - Returns whether a nonlinear preconditioner exists 56563ad1a0b9SPatrick Farrell 56573ad1a0b9SPatrick Farrell Not Collective 56583ad1a0b9SPatrick Farrell 56593ad1a0b9SPatrick Farrell Input Parameter: 5660f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 56613ad1a0b9SPatrick Farrell 56623ad1a0b9SPatrick Farrell Output Parameter: 5663420bcc1bSBarry Smith . has_npc - whether the `SNES` has a nonlinear preconditioner or not 56643ad1a0b9SPatrick Farrell 56653ad1a0b9SPatrick Farrell Level: developer 56663ad1a0b9SPatrick Farrell 56671cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESGetNPC()` 56683ad1a0b9SPatrick Farrell @*/ 5669d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc) 5670d71ae5a4SJacob Faibussowitsch { 56713ad1a0b9SPatrick Farrell PetscFunctionBegin; 56723ad1a0b9SPatrick Farrell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5673efd4aadfSBarry Smith *has_npc = (PetscBool)(snes->npc ? PETSC_TRUE : PETSC_FALSE); 56743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 56753ad1a0b9SPatrick Farrell } 56763ad1a0b9SPatrick Farrell 5677c40d0f55SPeter Brune /*@ 5678420bcc1bSBarry Smith SNESSetNPCSide - Sets the nonlinear preconditioning side. 5679c40d0f55SPeter Brune 5680c3339decSBarry Smith Logically Collective 5681c40d0f55SPeter Brune 5682c40d0f55SPeter Brune Input Parameter: 5683f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 5684c40d0f55SPeter Brune 5685c40d0f55SPeter Brune Output Parameter: 5686c40d0f55SPeter Brune . side - the preconditioning side, where side is one of 5687c40d0f55SPeter Brune .vb 56882d547940SBarry Smith PC_LEFT - left preconditioning 56892d547940SBarry Smith PC_RIGHT - right preconditioning (default for most nonlinear solvers) 5690c40d0f55SPeter Brune .ve 5691c40d0f55SPeter Brune 5692f6dfbefdSBarry Smith Options Database Key: 569367b8a455SSatish Balay . -snes_npc_side <right,left> - nonlinear preconditioner side 5694c40d0f55SPeter Brune 5695dc4c0fb0SBarry Smith Level: intermediate 5696dc4c0fb0SBarry Smith 5697f6dfbefdSBarry Smith Note: 5698f6dfbefdSBarry Smith `SNESNRICHARDSON` and `SNESNCG` only support left preconditioning. 56992d547940SBarry Smith 5700420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNRICHARDSON`, `SNESNCG`, `SNESType`, `SNESGetNPCSide()`, `KSPSetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide` 5701c40d0f55SPeter Brune @*/ 5702d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPCSide(SNES snes, PCSide side) 5703d71ae5a4SJacob Faibussowitsch { 5704c40d0f55SPeter Brune PetscFunctionBegin; 5705c40d0f55SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5706c40d0f55SPeter Brune PetscValidLogicalCollectiveEnum(snes, side, 2); 5707b552625fSStefano Zampini if (side == PC_SIDE_DEFAULT) side = PC_RIGHT; 570854c59aa7SJacob Faibussowitsch PetscCheck((side == PC_LEFT) || (side == PC_RIGHT), PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Only PC_LEFT and PC_RIGHT are supported"); 5709efd4aadfSBarry Smith snes->npcside = side; 57103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5711c40d0f55SPeter Brune } 5712c40d0f55SPeter Brune 5713c40d0f55SPeter Brune /*@ 5714be95d8f1SBarry Smith SNESGetNPCSide - Gets the preconditioning side. 5715c40d0f55SPeter Brune 5716c40d0f55SPeter Brune Not Collective 5717c40d0f55SPeter Brune 5718c40d0f55SPeter Brune Input Parameter: 5719f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 5720c40d0f55SPeter Brune 5721c40d0f55SPeter Brune Output Parameter: 5722c40d0f55SPeter Brune . side - the preconditioning side, where side is one of 5723c40d0f55SPeter Brune .vb 5724f6dfbefdSBarry Smith `PC_LEFT` - left preconditioning 5725f6dfbefdSBarry Smith `PC_RIGHT` - right preconditioning (default for most nonlinear solvers) 5726c40d0f55SPeter Brune .ve 5727c40d0f55SPeter Brune 5728c40d0f55SPeter Brune Level: intermediate 5729c40d0f55SPeter Brune 5730420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNPCSide()`, `KSPGetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide` 5731c40d0f55SPeter Brune @*/ 5732d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPCSide(SNES snes, PCSide *side) 5733d71ae5a4SJacob Faibussowitsch { 5734c40d0f55SPeter Brune PetscFunctionBegin; 5735c40d0f55SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 57364f572ea9SToby Isaac PetscAssertPointer(side, 2); 5737efd4aadfSBarry Smith *side = snes->npcside; 57383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5739c40d0f55SPeter Brune } 5740c40d0f55SPeter Brune 57419e764e56SPeter Brune /*@ 5742420bcc1bSBarry Smith SNESSetLineSearch - Sets the linesearch to be used for `SNES` 57439e764e56SPeter Brune 5744c3339decSBarry Smith Collective 57459e764e56SPeter Brune 57469e764e56SPeter Brune Input Parameters: 5747f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 57489e764e56SPeter Brune - linesearch - the linesearch object 57499e764e56SPeter Brune 5750dc4c0fb0SBarry Smith Level: developer 5751dc4c0fb0SBarry Smith 5752f6dfbefdSBarry Smith Note: 5753420bcc1bSBarry Smith This is almost never used, rather one uses `SNESGetLineSearch()` to retrieve the line search and set options on it 57549e764e56SPeter Brune to configure it using the API). 57559e764e56SPeter Brune 5756420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()` 57579e764e56SPeter Brune @*/ 5758d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch) 5759d71ae5a4SJacob Faibussowitsch { 57609e764e56SPeter Brune PetscFunctionBegin; 57619e764e56SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5762f1c6b773SPeter Brune PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 2); 57639e764e56SPeter Brune PetscCheckSameComm(snes, 1, linesearch, 2); 57649566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)linesearch)); 57659566063dSJacob Faibussowitsch PetscCall(SNESLineSearchDestroy(&snes->linesearch)); 5766f5af7f23SKarl Rupp 57679e764e56SPeter Brune snes->linesearch = linesearch; 57683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 57699e764e56SPeter Brune } 57709e764e56SPeter Brune 5771a34ceb2aSJed Brown /*@ 5772420bcc1bSBarry Smith SNESGetLineSearch - Returns the line search context possibly set with `SNESSetLineSearch()` 5773f6dfbefdSBarry Smith or creates a default line search instance associated with the `SNES` and returns it. 57749e764e56SPeter Brune 57759e764e56SPeter Brune Not Collective 57769e764e56SPeter Brune 57779e764e56SPeter Brune Input Parameter: 5778f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 57799e764e56SPeter Brune 57809e764e56SPeter Brune Output Parameter: 57819e764e56SPeter Brune . linesearch - linesearch context 57829e764e56SPeter Brune 5783162e0bf5SPeter Brune Level: beginner 57849e764e56SPeter Brune 57851cc06b55SBarry Smith .seealso: [](ch_snes), `SNESLineSearch`, `SNESSetLineSearch()`, `SNESLineSearchCreate()` 57869e764e56SPeter Brune @*/ 5787d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch) 5788d71ae5a4SJacob Faibussowitsch { 57899e764e56SPeter Brune const char *optionsprefix; 57909e764e56SPeter Brune 57919e764e56SPeter Brune PetscFunctionBegin; 57929e764e56SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 57934f572ea9SToby Isaac PetscAssertPointer(linesearch, 2); 57949e764e56SPeter Brune if (!snes->linesearch) { 57959566063dSJacob Faibussowitsch PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 57969566063dSJacob Faibussowitsch PetscCall(SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch)); 57979566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetSNES(snes->linesearch, snes)); 57989566063dSJacob Faibussowitsch PetscCall(SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix)); 57999566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->linesearch, (PetscObject)snes, 1)); 58009e764e56SPeter Brune } 58019e764e56SPeter Brune *linesearch = snes->linesearch; 58023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 58039e764e56SPeter Brune } 5804