1af0996ceSBarry Smith #include <petsc/private/snesimpl.h> /*I "petscsnes.h" I*/ 207475bc1SBarry Smith #include <petscdmshell.h> 3d96771aaSLisandro Dalcin #include <petscdraw.h> 4a01aa210SMatthew G. Knepley #include <petscds.h> 534b4d3a8SMatthew G. Knepley #include <petscdmadaptor.h> 606fc46c8SMatthew G. Knepley #include <petscconvest.h> 79b94acceSBarry Smith 8ace3abfcSBarry Smith PetscBool SNESRegisterAllCalled = PETSC_FALSE; 90298fd71SBarry Smith PetscFunctionList SNESList = NULL; 108ba1e511SMatthew Knepley 118ba1e511SMatthew Knepley /* Logging support */ 1222c6f798SBarry Smith PetscClassId SNES_CLASSID, DMSNES_CLASSID; 1397276fddSZach Atkins PetscLogEvent SNES_Solve, SNES_SetUp, SNES_FunctionEval, SNES_JacobianEval, SNES_NGSEval, SNES_NGSFuncEval, SNES_NewtonALEval, SNES_NPCSolve, SNES_ObjectiveEval; 14a09944afSBarry Smith 15e113a28aSBarry Smith /*@ 16dc4c0fb0SBarry Smith SNESSetErrorIfNotConverged - Causes `SNESSolve()` to generate an error immediately if the solver has not converged. 17e113a28aSBarry Smith 18c3339decSBarry Smith Logically Collective 19e113a28aSBarry Smith 20e113a28aSBarry Smith Input Parameters: 21f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 22f6dfbefdSBarry Smith - flg - `PETSC_TRUE` indicates you want the error generated 23e113a28aSBarry Smith 2420f4b53cSBarry Smith Options Database Key: 2567b8a455SSatish Balay . -snes_error_if_not_converged <true,false> - cause an immediate error condition and stop the program if the solver does not converge 26e113a28aSBarry Smith 27e113a28aSBarry Smith Level: intermediate 28e113a28aSBarry Smith 29f6dfbefdSBarry Smith Note: 30f6dfbefdSBarry Smith Normally PETSc continues if a solver fails to converge, you can call `SNESGetConvergedReason()` after a `SNESSolve()` 31f6dfbefdSBarry Smith to determine if it has converged. Otherwise the solution may be inaccurate or wrong 32e113a28aSBarry Smith 331cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetErrorIfNotConverged()`, `KSPGetErrorIfNotConverged()`, `KSPSetErrorIfNotConverged()` 34e113a28aSBarry Smith @*/ 35d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetErrorIfNotConverged(SNES snes, PetscBool flg) 36d71ae5a4SJacob Faibussowitsch { 37e113a28aSBarry Smith PetscFunctionBegin; 38e113a28aSBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 39acfcf0e5SJed Brown PetscValidLogicalCollectiveBool(snes, flg, 2); 40e113a28aSBarry Smith snes->errorifnotconverged = flg; 413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 42e113a28aSBarry Smith } 43e113a28aSBarry Smith 44e113a28aSBarry Smith /*@ 45f6dfbefdSBarry Smith SNESGetErrorIfNotConverged - Indicates if `SNESSolve()` will generate an error if the solver does not converge? 46e113a28aSBarry Smith 47e113a28aSBarry Smith Not Collective 48e113a28aSBarry Smith 49e113a28aSBarry Smith Input Parameter: 50f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 51e113a28aSBarry Smith 52e113a28aSBarry Smith Output Parameter: 53f6dfbefdSBarry Smith . flag - `PETSC_TRUE` if it will generate an error, else `PETSC_FALSE` 54e113a28aSBarry Smith 55e113a28aSBarry Smith Level: intermediate 56e113a28aSBarry Smith 571cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetErrorIfNotConverged()`, `KSPGetErrorIfNotConverged()`, `KSPSetErrorIfNotConverged()` 58e113a28aSBarry Smith @*/ 59d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetErrorIfNotConverged(SNES snes, PetscBool *flag) 60d71ae5a4SJacob Faibussowitsch { 61e113a28aSBarry Smith PetscFunctionBegin; 62e113a28aSBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 634f572ea9SToby Isaac PetscAssertPointer(flag, 2); 64e113a28aSBarry Smith *flag = snes->errorifnotconverged; 653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 66e113a28aSBarry Smith } 67e113a28aSBarry Smith 684fc747eaSLawrence Mitchell /*@ 69dc4c0fb0SBarry Smith SNESSetAlwaysComputesFinalResidual - tells the `SNES` to always compute the residual (nonlinear function value) at the final solution 704fc747eaSLawrence Mitchell 71c3339decSBarry Smith Logically Collective 724fc747eaSLawrence Mitchell 734fc747eaSLawrence Mitchell Input Parameters: 74f6dfbefdSBarry Smith + snes - the shell `SNES` 75f6dfbefdSBarry Smith - flg - `PETSC_TRUE` to always compute the residual 764fc747eaSLawrence Mitchell 774fc747eaSLawrence Mitchell Level: advanced 784fc747eaSLawrence Mitchell 79f6dfbefdSBarry Smith Note: 80f6dfbefdSBarry Smith Some solvers (such as smoothers in a `SNESFAS`) do not need the residual computed at the final solution so skip computing it 81f6dfbefdSBarry Smith to save time. 82f6dfbefdSBarry Smith 83420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSolve()`, `SNESGetAlwaysComputesFinalResidual()` 844fc747eaSLawrence Mitchell @*/ 85d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetAlwaysComputesFinalResidual(SNES snes, PetscBool flg) 86d71ae5a4SJacob Faibussowitsch { 874fc747eaSLawrence Mitchell PetscFunctionBegin; 884fc747eaSLawrence Mitchell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 894fc747eaSLawrence Mitchell snes->alwayscomputesfinalresidual = flg; 903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 914fc747eaSLawrence Mitchell } 924fc747eaSLawrence Mitchell 934fc747eaSLawrence Mitchell /*@ 94f6dfbefdSBarry Smith SNESGetAlwaysComputesFinalResidual - checks if the `SNES` always computes the residual at the final solution 954fc747eaSLawrence Mitchell 96c3339decSBarry Smith Logically Collective 974fc747eaSLawrence Mitchell 984fc747eaSLawrence Mitchell Input Parameter: 99f6dfbefdSBarry Smith . snes - the `SNES` context 1004fc747eaSLawrence Mitchell 1014fc747eaSLawrence Mitchell Output Parameter: 102f6dfbefdSBarry Smith . flg - `PETSC_TRUE` if the residual is computed 1034fc747eaSLawrence Mitchell 1044fc747eaSLawrence Mitchell Level: advanced 1054fc747eaSLawrence Mitchell 106420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSolve()`, `SNESSetAlwaysComputesFinalResidual()` 1074fc747eaSLawrence Mitchell @*/ 108d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetAlwaysComputesFinalResidual(SNES snes, PetscBool *flg) 109d71ae5a4SJacob Faibussowitsch { 1104fc747eaSLawrence Mitchell PetscFunctionBegin; 1114fc747eaSLawrence Mitchell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1124fc747eaSLawrence Mitchell *flg = snes->alwayscomputesfinalresidual; 1133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1144fc747eaSLawrence Mitchell } 1154fc747eaSLawrence Mitchell 116e725d27bSBarry Smith /*@ 117f6dfbefdSBarry Smith SNESSetFunctionDomainError - tells `SNES` that the input vector, a proposed new solution, to your function you provided to `SNESSetFunction()` is not 118f0b84518SBarry Smith in the functions domain. For example, a step with negative pressure. 1194936397dSBarry Smith 120c3339decSBarry Smith Logically Collective 1214936397dSBarry Smith 1222fe279fdSBarry Smith Input Parameter: 123f6dfbefdSBarry Smith . snes - the `SNES` context 1244936397dSBarry Smith 12528529972SSatish Balay Level: advanced 1264936397dSBarry Smith 127ced0f3aeSBarry Smith Notes: 128ced0f3aeSBarry Smith If this is called the `SNESSolve()` stops iterating and returns with a `SNESConvergedReason` of `SNES_DIVERGED_FUNCTION_DOMAIN` 129ced0f3aeSBarry Smith 130ced0f3aeSBarry Smith You should always call `SNESGetConvergedReason()` after each `SNESSolve()` and verify if the iteration converged (positive result) or diverged (negative result). 131ced0f3aeSBarry Smith 132f0b84518SBarry Smith You can direct `SNES` to avoid certain steps by using `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()` or 133f0b84518SBarry Smith `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()` 134f0b84518SBarry Smith 1358434afd1SBarry Smith .seealso: [](ch_snes), `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetJacobianDomainError()`, `SNESVISetVariableBounds()`, 136ced0f3aeSBarry Smith `SNESVISetComputeVariableBounds()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESConvergedReason`, `SNESGetConvergedReason()` 1374936397dSBarry Smith @*/ 138d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionDomainError(SNES snes) 139d71ae5a4SJacob Faibussowitsch { 1404936397dSBarry Smith PetscFunctionBegin; 1410700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1425f80ce2aSJacob Faibussowitsch PetscCheck(!snes->errorifnotconverged, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "User code indicates input vector is not in the function domain"); 1434936397dSBarry Smith snes->domainerror = PETSC_TRUE; 1443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1454936397dSBarry Smith } 1464936397dSBarry Smith 1476a388c36SPeter Brune /*@ 148f6dfbefdSBarry Smith SNESSetJacobianDomainError - tells `SNES` that the function you provided to `SNESSetJacobian()` at the proposed step. For example there is a negative element transformation. 14907b62357SFande Kong 150c3339decSBarry Smith Logically Collective 15107b62357SFande Kong 1522fe279fdSBarry Smith Input Parameter: 153f6dfbefdSBarry Smith . snes - the `SNES` context 15407b62357SFande Kong 15507b62357SFande Kong Level: advanced 15607b62357SFande Kong 157ced0f3aeSBarry Smith Notes: 158ced0f3aeSBarry Smith If this is called the `SNESSolve()` stops iterating and returns with a `SNESConvergedReason` of `SNES_DIVERGED_FUNCTION_DOMAIN` 159ced0f3aeSBarry Smith 160ced0f3aeSBarry Smith You should always call `SNESGetConvergedReason()` after each `SNESSolve()` and verify if the iteration converged (positive result) or diverged (negative result). 161ced0f3aeSBarry Smith 162f0b84518SBarry Smith You can direct `SNES` to avoid certain steps by using `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()` or 163f0b84518SBarry Smith `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()` 164f0b84518SBarry Smith 1658434afd1SBarry Smith .seealso: [](ch_snes), `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetFunctionDomainError()`, `SNESVISetVariableBounds()`, 166ced0f3aeSBarry Smith `SNESVISetComputeVariableBounds()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESConvergedReason`, `SNESGetConvergedReason()` 16707b62357SFande Kong @*/ 168d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetJacobianDomainError(SNES snes) 169d71ae5a4SJacob Faibussowitsch { 17007b62357SFande Kong PetscFunctionBegin; 17107b62357SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1725f80ce2aSJacob Faibussowitsch PetscCheck(!snes->errorifnotconverged, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "User code indicates computeJacobian does not make sense"); 17307b62357SFande Kong snes->jacobiandomainerror = PETSC_TRUE; 1743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17507b62357SFande Kong } 17607b62357SFande Kong 17707b62357SFande Kong /*@ 178f6dfbefdSBarry Smith SNESSetCheckJacobianDomainError - tells `SNESSolve()` whether to check if the user called `SNESSetJacobianDomainError()` Jacobian domain error after 179420bcc1bSBarry Smith each Jacobian evaluation. By default, it checks for the Jacobian domain error in the debug mode, and does not check it in the optimized mode. 180b351a90bSFande Kong 181c3339decSBarry Smith Logically Collective 182b351a90bSFande Kong 183b351a90bSFande Kong Input Parameters: 18420f4b53cSBarry Smith + snes - the `SNES` context 185f6dfbefdSBarry Smith - flg - indicates if or not to check Jacobian domain error after each Jacobian evaluation 186b351a90bSFande Kong 187b351a90bSFande Kong Level: advanced 188b351a90bSFande Kong 189f6dfbefdSBarry Smith Note: 190f6dfbefdSBarry Smith Checks require one extra parallel synchronization for each Jacobian evaluation 191f6dfbefdSBarry Smith 1928434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetFunctionDomainError()`, `SNESGetCheckJacobianDomainError()` 193b351a90bSFande Kong @*/ 194d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCheckJacobianDomainError(SNES snes, PetscBool flg) 195d71ae5a4SJacob Faibussowitsch { 196b351a90bSFande Kong PetscFunctionBegin; 197b351a90bSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 198b351a90bSFande Kong snes->checkjacdomainerror = flg; 1993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 200b351a90bSFande Kong } 201b351a90bSFande Kong 202b351a90bSFande Kong /*@ 203420bcc1bSBarry Smith SNESGetCheckJacobianDomainError - Get an indicator whether or not `SNES` is checking Jacobian domain errors after each Jacobian evaluation. 2048383d7d7SFande Kong 205c3339decSBarry Smith Logically Collective 2068383d7d7SFande Kong 2072fe279fdSBarry Smith Input Parameter: 208f6dfbefdSBarry Smith . snes - the `SNES` context 2098383d7d7SFande Kong 2102fe279fdSBarry Smith Output Parameter: 211420bcc1bSBarry Smith . flg - `PETSC_FALSE` indicates that it is not checking Jacobian domain errors after each Jacobian evaluation 2128383d7d7SFande Kong 2138383d7d7SFande Kong Level: advanced 2148383d7d7SFande Kong 2158434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetFunctionDomainError()`, `SNESSetCheckJacobianDomainError()` 2168383d7d7SFande Kong @*/ 217d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetCheckJacobianDomainError(SNES snes, PetscBool *flg) 218d71ae5a4SJacob Faibussowitsch { 2198383d7d7SFande Kong PetscFunctionBegin; 2208383d7d7SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2214f572ea9SToby Isaac PetscAssertPointer(flg, 2); 2228383d7d7SFande Kong *flg = snes->checkjacdomainerror; 2233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2248383d7d7SFande Kong } 2258383d7d7SFande Kong 2268383d7d7SFande Kong /*@ 227420bcc1bSBarry Smith SNESGetFunctionDomainError - Gets the status of the domain error after a call to `SNESComputeFunction()` 2286a388c36SPeter Brune 229f6dfbefdSBarry Smith Logically Collective 2306a388c36SPeter Brune 2312fe279fdSBarry Smith Input Parameter: 232f6dfbefdSBarry Smith . snes - the `SNES` context 2336a388c36SPeter Brune 2342fe279fdSBarry Smith Output Parameter: 235f6dfbefdSBarry Smith . domainerror - Set to `PETSC_TRUE` if there's a domain error; `PETSC_FALSE` otherwise. 2366a388c36SPeter Brune 237f6dfbefdSBarry Smith Level: developer 2386a388c36SPeter Brune 2391cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunctionDomainError()`, `SNESComputeFunction()` 2406a388c36SPeter Brune @*/ 241d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionDomainError(SNES snes, PetscBool *domainerror) 242d71ae5a4SJacob Faibussowitsch { 2436a388c36SPeter Brune PetscFunctionBegin; 2446a388c36SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2454f572ea9SToby Isaac PetscAssertPointer(domainerror, 2); 2466a388c36SPeter Brune *domainerror = snes->domainerror; 2473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2486a388c36SPeter Brune } 2496a388c36SPeter Brune 25007b62357SFande Kong /*@ 251420bcc1bSBarry Smith SNESGetJacobianDomainError - Gets the status of the Jacobian domain error after a call to `SNESComputeJacobian()` 25207b62357SFande Kong 253c3339decSBarry Smith Logically Collective 25407b62357SFande Kong 2552fe279fdSBarry Smith Input Parameter: 256f6dfbefdSBarry Smith . snes - the `SNES` context 25707b62357SFande Kong 2582fe279fdSBarry Smith Output Parameter: 259f6dfbefdSBarry Smith . domainerror - Set to `PETSC_TRUE` if there's a Jacobian domain error; `PETSC_FALSE` otherwise. 26007b62357SFande Kong 26107b62357SFande Kong Level: advanced 26207b62357SFande Kong 2631cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunctionDomainError()`, `SNESComputeFunction()`, `SNESGetFunctionDomainError()` 26407b62357SFande Kong @*/ 265d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetJacobianDomainError(SNES snes, PetscBool *domainerror) 266d71ae5a4SJacob Faibussowitsch { 26707b62357SFande Kong PetscFunctionBegin; 26807b62357SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2694f572ea9SToby Isaac PetscAssertPointer(domainerror, 2); 27007b62357SFande Kong *domainerror = snes->jacobiandomainerror; 2713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 27207b62357SFande Kong } 27307b62357SFande Kong 274ffeef943SBarry Smith /*@ 275f6dfbefdSBarry Smith SNESLoad - Loads a `SNES` that has been stored in `PETSCVIEWERBINARY` with `SNESView()`. 27655849f57SBarry Smith 277c3339decSBarry Smith Collective 27855849f57SBarry Smith 27955849f57SBarry Smith Input Parameters: 280e4094ef1SJacob Faibussowitsch + snes - the newly loaded `SNES`, this needs to have been created with `SNESCreate()` or 281f6dfbefdSBarry Smith some related function before a call to `SNESLoad()`. 282f6dfbefdSBarry Smith - viewer - binary file viewer, obtained from `PetscViewerBinaryOpen()` 28355849f57SBarry Smith 28455849f57SBarry Smith Level: intermediate 28555849f57SBarry Smith 286f6dfbefdSBarry Smith Note: 287420bcc1bSBarry Smith The `SNESType` is determined by the data in the file, any type set into the `SNES` before this call is ignored. 28855849f57SBarry Smith 2891cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `PetscViewer`, `SNESCreate()`, `SNESType`, `PetscViewerBinaryOpen()`, `SNESView()`, `MatLoad()`, `VecLoad()` 29055849f57SBarry Smith @*/ 291d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESLoad(SNES snes, PetscViewer viewer) 292d71ae5a4SJacob Faibussowitsch { 29355849f57SBarry Smith PetscBool isbinary; 294060da220SMatthew G. Knepley PetscInt classid; 29555849f57SBarry Smith char type[256]; 29655849f57SBarry Smith KSP ksp; 2972d53ad75SBarry Smith DM dm; 2982d53ad75SBarry Smith DMSNES dmsnes; 29955849f57SBarry Smith 30055849f57SBarry Smith PetscFunctionBegin; 3012d53ad75SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 30255849f57SBarry Smith PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 3039566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 3045f80ce2aSJacob Faibussowitsch PetscCheck(isbinary, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerBinaryOpen()"); 30555849f57SBarry Smith 3069566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer, &classid, 1, NULL, PETSC_INT)); 3075f80ce2aSJacob Faibussowitsch PetscCheck(classid == SNES_FILE_CLASSID, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Not SNES next in file"); 3089566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer, type, 256, NULL, PETSC_CHAR)); 3099566063dSJacob Faibussowitsch PetscCall(SNESSetType(snes, type)); 310dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, load, viewer); 3119566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 3129566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &dmsnes)); 3139566063dSJacob Faibussowitsch PetscCall(DMSNESLoad(dmsnes, viewer)); 3149566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 3159566063dSJacob Faibussowitsch PetscCall(KSPLoad(ksp, viewer)); 3163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 31755849f57SBarry Smith } 3186a388c36SPeter Brune 3199804daf3SBarry Smith #include <petscdraw.h> 320e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS) 321e04113cfSBarry Smith #include <petscviewersaws.h> 322bfb97211SBarry Smith #endif 3238404b7f3SBarry Smith 324ffeef943SBarry Smith /*@ 325dc4c0fb0SBarry Smith SNESViewFromOptions - View a `SNES` based on values in the options database 326fe2efc57SMark 327c3339decSBarry Smith Collective 328fe2efc57SMark 329fe2efc57SMark Input Parameters: 330f6dfbefdSBarry Smith + A - the `SNES` context 331dc4c0fb0SBarry Smith . obj - Optional object that provides the options prefix for the checks 332736c3998SJose E. Roman - name - command line option 333fe2efc57SMark 334fe2efc57SMark Level: intermediate 335f6dfbefdSBarry Smith 3361cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESView`, `PetscObjectViewFromOptions()`, `SNESCreate()` 337fe2efc57SMark @*/ 338d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESViewFromOptions(SNES A, PetscObject obj, const char name[]) 339d71ae5a4SJacob Faibussowitsch { 340fe2efc57SMark PetscFunctionBegin; 341fe2efc57SMark PetscValidHeaderSpecific(A, SNES_CLASSID, 1); 3429566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 3433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 344fe2efc57SMark } 345fe2efc57SMark 346789d8953SBarry Smith PETSC_EXTERN PetscErrorCode SNESComputeJacobian_DMDA(SNES, Vec, Mat, Mat, void *); 347789d8953SBarry Smith 348ffeef943SBarry Smith /*@ 349dc4c0fb0SBarry Smith SNESView - Prints or visualizes the `SNES` data structure. 3509b94acceSBarry Smith 351c3339decSBarry Smith Collective 352fee21e36SBarry Smith 353c7afd0dbSLois Curfman McInnes Input Parameters: 354f6dfbefdSBarry Smith + snes - the `SNES` context 355f6dfbefdSBarry Smith - viewer - the `PetscViewer` 356c7afd0dbSLois Curfman McInnes 3579b94acceSBarry Smith Options Database Key: 358f6dfbefdSBarry Smith . -snes_view - Calls `SNESView()` at end of `SNESSolve()` 3599b94acceSBarry Smith 360dc4c0fb0SBarry Smith Level: beginner 361dc4c0fb0SBarry Smith 3629b94acceSBarry Smith Notes: 3639b94acceSBarry Smith The available visualization contexts include 364f6dfbefdSBarry Smith + `PETSC_VIEWER_STDOUT_SELF` - standard output (default) 365f6dfbefdSBarry Smith - `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard 366c8a8ba5cSLois Curfman McInnes output where only the first processor opens 367c8a8ba5cSLois Curfman McInnes the file. All other processors send their 368c8a8ba5cSLois Curfman McInnes data to the first processor to print. 3699b94acceSBarry Smith 370052bf0daSPierre Jolivet The available formats include 371f6dfbefdSBarry Smith + `PETSC_VIEWER_DEFAULT` - standard output (default) 372f6dfbefdSBarry Smith - `PETSC_VIEWER_ASCII_INFO_DETAIL` - more verbose output for `SNESNASM` 373052bf0daSPierre Jolivet 3743e081fefSLois Curfman McInnes The user can open an alternative visualization context with 375f6dfbefdSBarry Smith `PetscViewerASCIIOpen()` - output to a specified file. 3769b94acceSBarry Smith 377f6dfbefdSBarry Smith In the debugger you can do "call `SNESView`(snes,0)" to display the `SNES` solver. (The same holds for any PETSc object viewer). 378595c91d4SBarry Smith 3791cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESLoad()`, `SNESCreate()`, `PetscViewerASCIIOpen()` 3809b94acceSBarry Smith @*/ 381d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESView(SNES snes, PetscViewer viewer) 382d71ae5a4SJacob Faibussowitsch { 383fa9f3622SBarry Smith SNESKSPEW *kctx; 38494b7f48cSBarry Smith KSP ksp; 3857f1410a3SPeter Brune SNESLineSearch linesearch; 38672a02f06SBarry Smith PetscBool iascii, isstring, isbinary, isdraw; 3872d53ad75SBarry Smith DMSNES dmsnes; 388e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS) 389536b137fSBarry Smith PetscBool issaws; 390bfb97211SBarry Smith #endif 3919b94acceSBarry Smith 3923a40ed3dSBarry Smith PetscFunctionBegin; 3930700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 39448a46eb9SPierre Jolivet if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &viewer)); 3950700a824SBarry Smith PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 396c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, viewer, 2); 39774679c65SBarry Smith 3989566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 3999566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 4009566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 4019566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 402e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS) 4039566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 404bfb97211SBarry Smith #endif 40532077d6dSBarry Smith if (iascii) { 406dc0571f2SMatthew G. Knepley SNESNormSchedule normschedule; 4078404b7f3SBarry Smith DM dm; 4088434afd1SBarry Smith SNESJacobianFn *cJ; 4098404b7f3SBarry Smith void *ctx; 410789d8953SBarry Smith const char *pre = ""; 411dc0571f2SMatthew G. Knepley 4129566063dSJacob Faibussowitsch PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)snes, viewer)); 41348a46eb9SPierre Jolivet if (!snes->setupcalled) PetscCall(PetscViewerASCIIPrintf(viewer, " SNES has not been set up so information may be incomplete\n")); 414e7788613SBarry Smith if (snes->ops->view) { 4159566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 416dbbe0bcdSBarry Smith PetscUseTypeMethod(snes, view, viewer); 4179566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 4180ef38995SBarry Smith } 41977e5a1f9SBarry Smith if (snes->max_funcs == PETSC_UNLIMITED) { 42077e5a1f9SBarry Smith PetscCall(PetscViewerASCIIPrintf(viewer, " maximum iterations=%" PetscInt_FMT ", maximum function evaluations=unlimited\n", snes->max_its)); 42177e5a1f9SBarry Smith } else { 42263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " maximum iterations=%" PetscInt_FMT ", maximum function evaluations=%" PetscInt_FMT "\n", snes->max_its, snes->max_funcs)); 42377e5a1f9SBarry Smith } 4249566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " tolerances: relative=%g, absolute=%g, solution=%g\n", (double)snes->rtol, (double)snes->abstol, (double)snes->stol)); 42548a46eb9SPierre Jolivet if (snes->usesksp) PetscCall(PetscViewerASCIIPrintf(viewer, " total number of linear solver iterations=%" PetscInt_FMT "\n", snes->linear_its)); 42663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " total number of function evaluations=%" PetscInt_FMT "\n", snes->nfuncs)); 4279566063dSJacob Faibussowitsch PetscCall(SNESGetNormSchedule(snes, &normschedule)); 4289566063dSJacob Faibussowitsch if (normschedule > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " norm schedule %s\n", SNESNormSchedules[normschedule])); 42948a46eb9SPierre Jolivet if (snes->gridsequence) PetscCall(PetscViewerASCIIPrintf(viewer, " total number of grid sequence refinements=%" PetscInt_FMT "\n", snes->gridsequence)); 4309b94acceSBarry Smith if (snes->ksp_ewconv) { 431fa9f3622SBarry Smith kctx = (SNESKSPEW *)snes->kspconvctx; 4329b94acceSBarry Smith if (kctx) { 43363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Eisenstat-Walker computation of KSP relative tolerance (version %" PetscInt_FMT ")\n", kctx->version)); 4349566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " rtol_0=%g, rtol_max=%g, threshold=%g\n", (double)kctx->rtol_0, (double)kctx->rtol_max, (double)kctx->threshold)); 4359566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " gamma=%g, alpha=%g, alpha2=%g\n", (double)kctx->gamma, (double)kctx->alpha, (double)kctx->alpha2)); 4369b94acceSBarry Smith } 4379b94acceSBarry Smith } 438eb1f6c34SBarry Smith if (snes->lagpreconditioner == -1) { 4399566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Preconditioned is never rebuilt\n")); 440eb1f6c34SBarry Smith } else if (snes->lagpreconditioner > 1) { 44163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Preconditioned is rebuilt every %" PetscInt_FMT " new Jacobians\n", snes->lagpreconditioner)); 442eb1f6c34SBarry Smith } 443eb1f6c34SBarry Smith if (snes->lagjacobian == -1) { 4449566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Jacobian is never rebuilt\n")); 445eb1f6c34SBarry Smith } else if (snes->lagjacobian > 1) { 44663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Jacobian is rebuilt every %" PetscInt_FMT " SNES iterations\n", snes->lagjacobian)); 447eb1f6c34SBarry Smith } 4489566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 4499566063dSJacob Faibussowitsch PetscCall(DMSNESGetJacobian(dm, &cJ, &ctx)); 450789d8953SBarry Smith if (snes->mf_operator) { 4519566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Jacobian is applied matrix-free with differencing\n")); 452789d8953SBarry Smith pre = "Preconditioning "; 453789d8953SBarry Smith } 4548404b7f3SBarry Smith if (cJ == SNESComputeJacobianDefault) { 4559566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %sJacobian is built using finite differences one column at a time\n", pre)); 4568404b7f3SBarry Smith } else if (cJ == SNESComputeJacobianDefaultColor) { 4579566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %sJacobian is built using finite differences with coloring\n", pre)); 458789d8953SBarry Smith /* it slightly breaks data encapsulation for access the DMDA information directly */ 459789d8953SBarry Smith } else if (cJ == SNESComputeJacobian_DMDA) { 460789d8953SBarry Smith MatFDColoring fdcoloring; 4619566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)dm, "DMDASNES_FDCOLORING", (PetscObject *)&fdcoloring)); 462789d8953SBarry Smith if (fdcoloring) { 4639566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %sJacobian is built using colored finite differences on a DMDA\n", pre)); 464789d8953SBarry Smith } else { 4659566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %sJacobian is built using a DMDA local Jacobian\n", pre)); 466789d8953SBarry Smith } 467996e1cbcSBarry Smith } else if (snes->mf && !snes->mf_operator) { 4689566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Jacobian is applied matrix-free with differencing, no explicit Jacobian\n")); 4698404b7f3SBarry Smith } 4700f5bd95cSBarry Smith } else if (isstring) { 471317d6ea6SBarry Smith const char *type; 4729566063dSJacob Faibussowitsch PetscCall(SNESGetType(snes, &type)); 4739566063dSJacob Faibussowitsch PetscCall(PetscViewerStringSPrintf(viewer, " SNESType: %-7.7s", type)); 474dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, view, viewer); 47555849f57SBarry Smith } else if (isbinary) { 47655849f57SBarry Smith PetscInt classid = SNES_FILE_CLASSID; 47755849f57SBarry Smith MPI_Comm comm; 47855849f57SBarry Smith PetscMPIInt rank; 47955849f57SBarry Smith char type[256]; 48055849f57SBarry Smith 4819566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 4829566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 483dd400576SPatrick Sanan if (rank == 0) { 4849566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryWrite(viewer, &classid, 1, PETSC_INT)); 4859566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(type, ((PetscObject)snes)->type_name, sizeof(type))); 4869566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryWrite(viewer, type, sizeof(type), PETSC_CHAR)); 48755849f57SBarry Smith } 488dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, view, viewer); 48972a02f06SBarry Smith } else if (isdraw) { 49072a02f06SBarry Smith PetscDraw draw; 49172a02f06SBarry Smith char str[36]; 49289fd9fafSBarry Smith PetscReal x, y, bottom, h; 49372a02f06SBarry Smith 4949566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 4959566063dSJacob Faibussowitsch PetscCall(PetscDrawGetCurrentPoint(draw, &x, &y)); 4969566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(str, "SNES: ", sizeof(str))); 4979566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(str, ((PetscObject)snes)->type_name, sizeof(str))); 4989566063dSJacob Faibussowitsch PetscCall(PetscDrawStringBoxed(draw, x, y, PETSC_DRAW_BLUE, PETSC_DRAW_BLACK, str, NULL, &h)); 49989fd9fafSBarry Smith bottom = y - h; 5009566063dSJacob Faibussowitsch PetscCall(PetscDrawPushCurrentPoint(draw, x, bottom)); 501dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, view, viewer); 502e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS) 503536b137fSBarry Smith } else if (issaws) { 504d45a07a7SBarry Smith PetscMPIInt rank; 5052657e9d9SBarry Smith const char *name; 506d45a07a7SBarry Smith 5079566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)snes, &name)); 5089566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 509dd400576SPatrick Sanan if (!((PetscObject)snes)->amsmem && rank == 0) { 510d45a07a7SBarry Smith char dir[1024]; 511d45a07a7SBarry Smith 5129566063dSJacob Faibussowitsch PetscCall(PetscObjectViewSAWs((PetscObject)snes, viewer)); 5139566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/its", name)); 514792fecdfSBarry Smith PetscCallSAWs(SAWs_Register, (dir, &snes->iter, 1, SAWs_READ, SAWs_INT)); 51548a46eb9SPierre Jolivet if (!snes->conv_hist) PetscCall(SNESSetConvergenceHistory(snes, NULL, NULL, PETSC_DECIDE, PETSC_TRUE)); 5169566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/conv_hist", name)); 517792fecdfSBarry Smith PetscCallSAWs(SAWs_Register, (dir, snes->conv_hist, 10, SAWs_READ, SAWs_DOUBLE)); 518f05ece33SBarry Smith } 519bfb97211SBarry Smith #endif 52072a02f06SBarry Smith } 52172a02f06SBarry Smith if (snes->linesearch) { 5229566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &linesearch)); 5239566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 5249566063dSJacob Faibussowitsch PetscCall(SNESLineSearchView(linesearch, viewer)); 5259566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 52619bcc07fSBarry Smith } 527efd4aadfSBarry Smith if (snes->npc && snes->usesnpc) { 5289566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 5299566063dSJacob Faibussowitsch PetscCall(SNESView(snes->npc, viewer)); 5309566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 5314a0c5b0cSMatthew G Knepley } 5329566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 5339566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(snes->dm, &dmsnes)); 5349566063dSJacob Faibussowitsch PetscCall(DMSNESView(dmsnes, viewer)); 5359566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 5362c155ee1SBarry Smith if (snes->usesksp) { 5379566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 5389566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 5399566063dSJacob Faibussowitsch PetscCall(KSPView(ksp, viewer)); 5409566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 5412c155ee1SBarry Smith } 54272a02f06SBarry Smith if (isdraw) { 54372a02f06SBarry Smith PetscDraw draw; 5449566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 5459566063dSJacob Faibussowitsch PetscCall(PetscDrawPopCurrentPoint(draw)); 5467f1410a3SPeter Brune } 5473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5489b94acceSBarry Smith } 5499b94acceSBarry Smith 55076b2cf59SMatthew Knepley /* 55176b2cf59SMatthew Knepley We retain a list of functions that also take SNES command 55276b2cf59SMatthew Knepley line options. These are called at the end SNESSetFromOptions() 55376b2cf59SMatthew Knepley */ 55476b2cf59SMatthew Knepley #define MAXSETFROMOPTIONS 5 555a7cc72afSBarry Smith static PetscInt numberofsetfromoptions; 5566849ba73SBarry Smith static PetscErrorCode (*othersetfromoptions[MAXSETFROMOPTIONS])(SNES); 55776b2cf59SMatthew Knepley 558ac226902SBarry Smith /*@C 559f6dfbefdSBarry Smith SNESAddOptionsChecker - Adds an additional function to check for `SNES` options. 56076b2cf59SMatthew Knepley 56176b2cf59SMatthew Knepley Not Collective 56276b2cf59SMatthew Knepley 56376b2cf59SMatthew Knepley Input Parameter: 56476b2cf59SMatthew Knepley . snescheck - function that checks for options 56576b2cf59SMatthew Knepley 566420bcc1bSBarry Smith Calling sequence of `snescheck`: 567420bcc1bSBarry Smith . snes - the `SNES` object for which it is checking options 568420bcc1bSBarry Smith 56976b2cf59SMatthew Knepley Level: developer 57076b2cf59SMatthew Knepley 5711cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()` 57276b2cf59SMatthew Knepley @*/ 573420bcc1bSBarry Smith PetscErrorCode SNESAddOptionsChecker(PetscErrorCode (*snescheck)(SNES snes)) 574d71ae5a4SJacob Faibussowitsch { 57576b2cf59SMatthew Knepley PetscFunctionBegin; 57663a3b9bcSJacob Faibussowitsch PetscCheck(numberofsetfromoptions < MAXSETFROMOPTIONS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many options checkers, only %d allowed", MAXSETFROMOPTIONS); 57776b2cf59SMatthew Knepley othersetfromoptions[numberofsetfromoptions++] = snescheck; 5783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 57976b2cf59SMatthew Knepley } 58076b2cf59SMatthew Knepley 581d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetUpMatrixFree_Private(SNES snes, PetscBool hasOperator, PetscInt version) 582d71ae5a4SJacob Faibussowitsch { 583aa3661deSLisandro Dalcin Mat J; 584895c21f2SBarry Smith MatNullSpace nullsp; 585aa3661deSLisandro Dalcin 586aa3661deSLisandro Dalcin PetscFunctionBegin; 5870700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 588aa3661deSLisandro Dalcin 58998613b67SLisandro Dalcin if (!snes->vec_func && (snes->jacobian || snes->jacobian_pre)) { 59098613b67SLisandro Dalcin Mat A = snes->jacobian, B = snes->jacobian_pre; 5919566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A ? A : B, NULL, &snes->vec_func)); 59298613b67SLisandro Dalcin } 59398613b67SLisandro Dalcin 5940fdf79fbSJacob Faibussowitsch PetscCheck(version == 1 || version == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "matrix-free operator routines, only version 1 and 2"); 595aa3661deSLisandro Dalcin if (version == 1) { 5969566063dSJacob Faibussowitsch PetscCall(MatCreateSNESMF(snes, &J)); 5979566063dSJacob Faibussowitsch PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix)); 5989566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(J)); 5991e2ae407SBarry Smith /* TODO: the version 2 code should be merged into the MatCreateSNESMF() and MatCreateMFFD() infrastructure and then removed */ 6000fdf79fbSJacob Faibussowitsch } else /* if (version == 2) */ { 6015f80ce2aSJacob Faibussowitsch PetscCheck(snes->vec_func, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "SNESSetFunction() must be called first"); 602570b7f6dSBarry Smith #if !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_REAL_SINGLE) && !defined(PETSC_USE_REAL___FLOAT128) && !defined(PETSC_USE_REAL___FP16) 603f6dfbefdSBarry Smith PetscCall(MatCreateSNESMFMore(snes, snes->vec_func, &J)); 604aa3661deSLisandro Dalcin #else 6052479783cSJose E. Roman SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "matrix-free operator routines (version 2)"); 606aa3661deSLisandro Dalcin #endif 6070fdf79fbSJacob Faibussowitsch } 608aa3661deSLisandro Dalcin 60901c1178eSBarry Smith /* attach any user provided null space that was on Amat to the newly created matrix-free matrix */ 610895c21f2SBarry Smith if (snes->jacobian) { 6119566063dSJacob Faibussowitsch PetscCall(MatGetNullSpace(snes->jacobian, &nullsp)); 6121baa6e33SBarry Smith if (nullsp) PetscCall(MatSetNullSpace(J, nullsp)); 613895c21f2SBarry Smith } 614895c21f2SBarry Smith 61563a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Setting default matrix-free operator routines (version %" PetscInt_FMT ")\n", version)); 616d3462f78SMatthew Knepley if (hasOperator) { 617aa3661deSLisandro Dalcin /* This version replaces the user provided Jacobian matrix with a 618aa3661deSLisandro Dalcin matrix-free version but still employs the user-provided preconditioner matrix. */ 6199566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL)); 620aa3661deSLisandro Dalcin } else { 621aa3661deSLisandro Dalcin /* This version replaces both the user-provided Jacobian and the user- 62201c1178eSBarry Smith provided preconditioner Jacobian with the default matrix-free version. */ 623b552625fSStefano Zampini if (snes->npcside == PC_LEFT && snes->npc) { 6249566063dSJacob Faibussowitsch if (!snes->jacobian) PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL)); 625172a4300SPeter Brune } else { 626789d8953SBarry Smith KSP ksp; 627789d8953SBarry Smith PC pc; 628789d8953SBarry Smith PetscBool match; 629789d8953SBarry Smith 6309566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J, J, MatMFFDComputeJacobian, NULL)); 631aa3661deSLisandro Dalcin /* Force no preconditioner */ 6329566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 6339566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksp, &pc)); 6342698c518SLisandro Dalcin PetscCall(PetscObjectTypeCompareAny((PetscObject)pc, &match, PCSHELL, PCH2OPUS, "")); 635aa3661deSLisandro Dalcin if (!match) { 6369566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Setting default matrix-free preconditioner routines\nThat is no preconditioner is being used\n")); 6379566063dSJacob Faibussowitsch PetscCall(PCSetType(pc, PCNONE)); 638aa3661deSLisandro Dalcin } 639aa3661deSLisandro Dalcin } 640789d8953SBarry Smith } 6419566063dSJacob Faibussowitsch PetscCall(MatDestroy(&J)); 6423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 643aa3661deSLisandro Dalcin } 644aa3661deSLisandro Dalcin 645d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMRestrictHook_SNESVecSol(DM dmfine, Mat Restrict, Vec Rscale, Mat Inject, DM dmcoarse, void *ctx) 646d71ae5a4SJacob Faibussowitsch { 647dfe15315SJed Brown SNES snes = (SNES)ctx; 6480298fd71SBarry Smith Vec Xfine, Xfine_named = NULL, Xcoarse; 649dfe15315SJed Brown 650dfe15315SJed Brown PetscFunctionBegin; 65116ebb321SJed Brown if (PetscLogPrintInfo) { 65216ebb321SJed Brown PetscInt finelevel, coarselevel, fineclevel, coarseclevel; 6539566063dSJacob Faibussowitsch PetscCall(DMGetRefineLevel(dmfine, &finelevel)); 6549566063dSJacob Faibussowitsch PetscCall(DMGetCoarsenLevel(dmfine, &fineclevel)); 6559566063dSJacob Faibussowitsch PetscCall(DMGetRefineLevel(dmcoarse, &coarselevel)); 6569566063dSJacob Faibussowitsch PetscCall(DMGetCoarsenLevel(dmcoarse, &coarseclevel)); 65763a3b9bcSJacob 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)); 65816ebb321SJed Brown } 659dfe15315SJed Brown if (dmfine == snes->dm) Xfine = snes->vec_sol; 660dfe15315SJed Brown else { 6619566063dSJacob Faibussowitsch PetscCall(DMGetNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named)); 662dfe15315SJed Brown Xfine = Xfine_named; 663dfe15315SJed Brown } 6649566063dSJacob Faibussowitsch PetscCall(DMGetNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse)); 665907f5c5aSLawrence Mitchell if (Inject) { 6669566063dSJacob Faibussowitsch PetscCall(MatRestrict(Inject, Xfine, Xcoarse)); 667907f5c5aSLawrence Mitchell } else { 6689566063dSJacob Faibussowitsch PetscCall(MatRestrict(Restrict, Xfine, Xcoarse)); 6699566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(Xcoarse, Xcoarse, Rscale)); 670907f5c5aSLawrence Mitchell } 6719566063dSJacob Faibussowitsch PetscCall(DMRestoreNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse)); 6729566063dSJacob Faibussowitsch if (Xfine_named) PetscCall(DMRestoreNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named)); 6733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 674dfe15315SJed Brown } 675dfe15315SJed Brown 676d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCoarsenHook_SNESVecSol(DM dm, DM dmc, void *ctx) 677d71ae5a4SJacob Faibussowitsch { 67816ebb321SJed Brown PetscFunctionBegin; 6799566063dSJacob Faibussowitsch PetscCall(DMCoarsenHookAdd(dmc, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, ctx)); 6803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 68116ebb321SJed Brown } 68216ebb321SJed Brown 683a6950cb2SJed Brown /* This may be called to rediscretize the operator on levels of linear multigrid. The DM shuffle is so the user can 684a6950cb2SJed Brown * safely call SNESGetDM() in their residual evaluation routine. */ 685d71ae5a4SJacob Faibussowitsch static PetscErrorCode KSPComputeOperators_SNES(KSP ksp, Mat A, Mat B, void *ctx) 686d71ae5a4SJacob Faibussowitsch { 687caa4e7f2SJed Brown SNES snes = (SNES)ctx; 68897d931d1SStefano Zampini DMSNES sdm; 6890298fd71SBarry Smith Vec X, Xnamed = NULL; 690dfe15315SJed Brown DM dmsave; 6914e269d77SPeter Brune void *ctxsave; 6928434afd1SBarry Smith SNESJacobianFn *jac = NULL; 693caa4e7f2SJed Brown 694caa4e7f2SJed Brown PetscFunctionBegin; 695dfe15315SJed Brown dmsave = snes->dm; 6969566063dSJacob Faibussowitsch PetscCall(KSPGetDM(ksp, &snes->dm)); 697dfe15315SJed Brown if (dmsave == snes->dm) X = snes->vec_sol; /* We are on the finest level */ 69897d931d1SStefano Zampini else { 699309d62e6SStefano Zampini PetscBool has; 700309d62e6SStefano Zampini 70197d931d1SStefano Zampini /* We are on a coarser level, this vec was initialized using a DM restrict hook */ 702309d62e6SStefano Zampini PetscCall(DMHasNamedGlobalVector(snes->dm, "SNESVecSol", &has)); 703309d62e6SStefano Zampini PetscCheck(has, PetscObjectComm((PetscObject)snes->dm), PETSC_ERR_PLIB, "Missing SNESVecSol"); 70497d931d1SStefano Zampini PetscCall(DMGetNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed)); 705dfe15315SJed Brown X = Xnamed; 7069566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, NULL, NULL, &jac, &ctxsave)); 7074e269d77SPeter Brune /* If the DM's don't match up, the MatFDColoring context needed for the jacobian won't match up either -- fixit. */ 70848a46eb9SPierre Jolivet if (jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, SNESComputeJacobianDefaultColor, NULL)); 7094e269d77SPeter Brune } 7104e269d77SPeter Brune 7112b93b426SMatthew G. Knepley /* Compute the operators */ 71297d931d1SStefano Zampini PetscCall(DMGetDMSNES(snes->dm, &sdm)); 71397d931d1SStefano Zampini if (Xnamed && sdm->ops->computefunction) { 71497d931d1SStefano Zampini /* The SNES contract with the user is that ComputeFunction is always called before ComputeJacobian. 71597d931d1SStefano Zampini We make sure of this here. Disable affine shift since it is for the finest level */ 71697d931d1SStefano Zampini Vec F, saverhs = snes->vec_rhs; 71797d931d1SStefano Zampini 71897d931d1SStefano Zampini snes->vec_rhs = NULL; 71997d931d1SStefano Zampini PetscCall(DMGetGlobalVector(snes->dm, &F)); 72097d931d1SStefano Zampini PetscCall(SNESComputeFunction(snes, X, F)); 72197d931d1SStefano Zampini PetscCall(DMRestoreGlobalVector(snes->dm, &F)); 72297d931d1SStefano Zampini snes->vec_rhs = saverhs; 72397d931d1SStefano Zampini snes->nfuncs--; /* Do not log coarser level evaluations */ 72497d931d1SStefano Zampini } 72597d931d1SStefano Zampini /* Make sure KSP DM has the Jacobian computation routine */ 72697d931d1SStefano Zampini if (!sdm->ops->computejacobian) PetscCall(DMCopyDMSNES(dmsave, snes->dm)); 7279566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobian(snes, X, A, B)); 72897d931d1SStefano Zampini 7292b93b426SMatthew G. Knepley /* Put the previous context back */ 73048a46eb9SPierre Jolivet if (snes->dm != dmsave && jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, jac, ctxsave)); 7314e269d77SPeter Brune 7329566063dSJacob Faibussowitsch if (Xnamed) PetscCall(DMRestoreNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed)); 733dfe15315SJed Brown snes->dm = dmsave; 7343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 735caa4e7f2SJed Brown } 736caa4e7f2SJed Brown 7376cab3a1bSJed Brown /*@ 738dc4c0fb0SBarry Smith SNESSetUpMatrices - ensures that matrices are available for `SNES` Newton-like methods, this is called by `SNESSetUp_XXX()` 7396cab3a1bSJed Brown 7406cab3a1bSJed Brown Collective 7416cab3a1bSJed Brown 7424165533cSJose E. Roman Input Parameter: 74320f4b53cSBarry Smith . snes - `SNES` object to configure 7446cab3a1bSJed Brown 7456cab3a1bSJed Brown Level: developer 7466cab3a1bSJed Brown 747dc4c0fb0SBarry Smith Note: 748dc4c0fb0SBarry 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` 749dc4c0fb0SBarry Smith 75073a84a35SBarry Smith Developer Note: 75173a84a35SBarry Smith The functionality of this routine overlaps in a confusing way with the functionality of `SNESSetUpMatrixFree_Private()` which is called by 75273a84a35SBarry Smith `SNESSetUp()` but sometimes `SNESSetUpMatrices()` is called without `SNESSetUp()` being called. A refactorization to simplify the 75373a84a35SBarry Smith logic that handles the matrix-free case is desirable. 75473a84a35SBarry Smith 7551cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUp()` 7566cab3a1bSJed Brown @*/ 757d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUpMatrices(SNES snes) 758d71ae5a4SJacob Faibussowitsch { 7596cab3a1bSJed Brown DM dm; 760942e3340SBarry Smith DMSNES sdm; 7616cab3a1bSJed Brown 7626cab3a1bSJed Brown PetscFunctionBegin; 7639566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 7649566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 76573a84a35SBarry Smith if (!snes->jacobian && snes->mf && !snes->mf_operator && !snes->jacobian_pre) { 7666cab3a1bSJed Brown Mat J; 7676cab3a1bSJed Brown void *functx; 7689566063dSJacob Faibussowitsch PetscCall(MatCreateSNESMF(snes, &J)); 7699566063dSJacob Faibussowitsch PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix)); 7709566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(J)); 7719566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, NULL, &functx)); 7729566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J, J, NULL, NULL)); 7739566063dSJacob Faibussowitsch PetscCall(MatDestroy(&J)); 774caa4e7f2SJed Brown } else if (snes->mf_operator && !snes->jacobian_pre && !snes->jacobian) { 7756cab3a1bSJed Brown Mat J, B; 7769566063dSJacob Faibussowitsch PetscCall(MatCreateSNESMF(snes, &J)); 7779566063dSJacob Faibussowitsch PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix)); 7789566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(J)); 7799566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(snes->dm, &B)); 78006f20277SJed Brown /* sdm->computejacobian was already set to reach here */ 7819566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J, B, NULL, NULL)); 7829566063dSJacob Faibussowitsch PetscCall(MatDestroy(&J)); 7839566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 784caa4e7f2SJed Brown } else if (!snes->jacobian_pre) { 7851ba9b98eSMatthew G. Knepley PetscDS prob; 7866cab3a1bSJed Brown Mat J, B; 7871ba9b98eSMatthew G. Knepley PetscBool hasPrec = PETSC_FALSE; 7881ba9b98eSMatthew G. Knepley 7896cab3a1bSJed Brown J = snes->jacobian; 7909566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob)); 7919566063dSJacob Faibussowitsch if (prob) PetscCall(PetscDSHasJacobianPreconditioner(prob, &hasPrec)); 7929566063dSJacob Faibussowitsch if (J) PetscCall(PetscObjectReference((PetscObject)J)); 7939566063dSJacob Faibussowitsch else if (hasPrec) PetscCall(DMCreateMatrix(snes->dm, &J)); 7949566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(snes->dm, &B)); 7959566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J ? J : B, B, NULL, NULL)); 7969566063dSJacob Faibussowitsch PetscCall(MatDestroy(&J)); 7979566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 7986cab3a1bSJed Brown } 799caa4e7f2SJed Brown { 800caa4e7f2SJed Brown KSP ksp; 8019566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 8029566063dSJacob Faibussowitsch PetscCall(KSPSetComputeOperators(ksp, KSPComputeOperators_SNES, snes)); 8039566063dSJacob Faibussowitsch PetscCall(DMCoarsenHookAdd(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes)); 804caa4e7f2SJed Brown } 8053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8066cab3a1bSJed Brown } 8076cab3a1bSJed Brown 808d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESMonitorPauseFinal_Internal(SNES snes) 809d71ae5a4SJacob Faibussowitsch { 8105e7c47f3SMatthew G. Knepley PetscInt i; 8115e7c47f3SMatthew G. Knepley 8125e7c47f3SMatthew G. Knepley PetscFunctionBegin; 8133ba16761SJacob Faibussowitsch if (!snes->pauseFinal) PetscFunctionReturn(PETSC_SUCCESS); 8145e7c47f3SMatthew G. Knepley for (i = 0; i < snes->numbermonitors; ++i) { 8155e7c47f3SMatthew G. Knepley PetscViewerAndFormat *vf = (PetscViewerAndFormat *)snes->monitorcontext[i]; 8165e7c47f3SMatthew G. Knepley PetscDraw draw; 8175e7c47f3SMatthew G. Knepley PetscReal lpause; 8185e7c47f3SMatthew G. Knepley 8195e7c47f3SMatthew G. Knepley if (!vf) continue; 8205e7c47f3SMatthew G. Knepley if (vf->lg) { 8215e7c47f3SMatthew G. Knepley if (!PetscCheckPointer(vf->lg, PETSC_OBJECT)) continue; 8225e7c47f3SMatthew G. Knepley if (((PetscObject)vf->lg)->classid != PETSC_DRAWLG_CLASSID) continue; 8239566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(vf->lg, &draw)); 8249566063dSJacob Faibussowitsch PetscCall(PetscDrawGetPause(draw, &lpause)); 8259566063dSJacob Faibussowitsch PetscCall(PetscDrawSetPause(draw, -1.0)); 8269566063dSJacob Faibussowitsch PetscCall(PetscDrawPause(draw)); 8279566063dSJacob Faibussowitsch PetscCall(PetscDrawSetPause(draw, lpause)); 8285e7c47f3SMatthew G. Knepley } else { 8295e7c47f3SMatthew G. Knepley PetscBool isdraw; 8305e7c47f3SMatthew G. Knepley 8315e7c47f3SMatthew G. Knepley if (!PetscCheckPointer(vf->viewer, PETSC_OBJECT)) continue; 8325e7c47f3SMatthew G. Knepley if (((PetscObject)vf->viewer)->classid != PETSC_VIEWER_CLASSID) continue; 8339566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)vf->viewer, PETSCVIEWERDRAW, &isdraw)); 8345e7c47f3SMatthew G. Knepley if (!isdraw) continue; 8359566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(vf->viewer, 0, &draw)); 8369566063dSJacob Faibussowitsch PetscCall(PetscDrawGetPause(draw, &lpause)); 8379566063dSJacob Faibussowitsch PetscCall(PetscDrawSetPause(draw, -1.0)); 8389566063dSJacob Faibussowitsch PetscCall(PetscDrawPause(draw)); 8399566063dSJacob Faibussowitsch PetscCall(PetscDrawSetPause(draw, lpause)); 8405e7c47f3SMatthew G. Knepley } 8415e7c47f3SMatthew G. Knepley } 8423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8435e7c47f3SMatthew G. Knepley } 8445e7c47f3SMatthew G. Knepley 845fde5950dSBarry Smith /*@C 846fde5950dSBarry Smith SNESMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user 847fde5950dSBarry Smith 848c3339decSBarry Smith Collective 849fde5950dSBarry Smith 850fde5950dSBarry Smith Input Parameters: 851dc4c0fb0SBarry Smith + snes - `SNES` object you wish to monitor 852fde5950dSBarry Smith . name - the monitor type one is seeking 853fde5950dSBarry Smith . help - message indicating what monitoring is done 854fde5950dSBarry Smith . manual - manual page for the monitor 85549abdd8aSBarry Smith . monitor - the monitor function, this must use a `PetscViewerFormat` as its context 856f6dfbefdSBarry 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 857fde5950dSBarry Smith 858420bcc1bSBarry Smith Calling sequence of `monitor`: 859420bcc1bSBarry Smith + snes - the nonlinear solver context 860420bcc1bSBarry Smith . it - the current iteration 861420bcc1bSBarry Smith . r - the current function norm 862420bcc1bSBarry Smith - vf - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use 863420bcc1bSBarry Smith 864420bcc1bSBarry Smith Calling sequence of `monitorsetup`: 865420bcc1bSBarry Smith + snes - the nonlinear solver context 866420bcc1bSBarry Smith - vf - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use 867420bcc1bSBarry Smith 868f6dfbefdSBarry Smith Options Database Key: 869f6dfbefdSBarry Smith . -name - trigger the use of this monitor in `SNESSetFromOptions()` 870f6dfbefdSBarry Smith 871f6dfbefdSBarry Smith Level: advanced 872fde5950dSBarry Smith 873648c30bcSBarry Smith .seealso: [](ch_snes), `PetscOptionsCreateViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, 874db781477SPatrick Sanan `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()` 875e4094ef1SJacob Faibussowitsch `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, 876db781477SPatrick Sanan `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`, 877c2e3fba1SPatrick Sanan `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`, 878db781477SPatrick Sanan `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`, 879db781477SPatrick Sanan `PetscOptionsFList()`, `PetscOptionsEList()` 880fde5950dSBarry Smith @*/ 881420bcc1bSBarry 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)) 882d71ae5a4SJacob Faibussowitsch { 883fde5950dSBarry Smith PetscViewer viewer; 884fde5950dSBarry Smith PetscViewerFormat format; 885fde5950dSBarry Smith PetscBool flg; 886fde5950dSBarry Smith 887fde5950dSBarry Smith PetscFunctionBegin; 888648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, name, &viewer, &format, &flg)); 889fde5950dSBarry Smith if (flg) { 890d43b4f6eSBarry Smith PetscViewerAndFormat *vf; 8919566063dSJacob Faibussowitsch PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf)); 892648c30bcSBarry Smith PetscCall(PetscViewerDestroy(&viewer)); 8931baa6e33SBarry Smith if (monitorsetup) PetscCall((*monitorsetup)(snes, vf)); 89449abdd8aSBarry Smith PetscCall(SNESMonitorSet(snes, (PetscErrorCode (*)(SNES, PetscInt, PetscReal, void *))monitor, vf, (PetscCtxDestroyFn *)PetscViewerAndFormatDestroy)); 895fde5950dSBarry Smith } 8963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 897fde5950dSBarry Smith } 898fde5950dSBarry Smith 899a4598233SStefano Zampini PetscErrorCode SNESEWSetFromOptions_Private(SNESKSPEW *kctx, PetscBool print_api, MPI_Comm comm, const char *prefix) 900d71ae5a4SJacob Faibussowitsch { 901a4598233SStefano Zampini const char *api = print_api ? "SNESKSPSetParametersEW" : NULL; 902a4598233SStefano Zampini 9030f0abf79SStefano Zampini PetscFunctionBegin; 9040f0abf79SStefano Zampini PetscOptionsBegin(comm, prefix, "Eisenstat and Walker type forcing options", "KSP"); 905a4598233SStefano Zampini PetscCall(PetscOptionsInt("-ksp_ew_version", "Version 1, 2 or 3", api, kctx->version, &kctx->version, NULL)); 906a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_rtol0", "0 <= rtol0 < 1", api, kctx->rtol_0, &kctx->rtol_0, NULL)); 907a4598233SStefano Zampini kctx->rtol_max = PetscMax(kctx->rtol_0, kctx->rtol_max); 908a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_rtolmax", "0 <= rtolmax < 1", api, kctx->rtol_max, &kctx->rtol_max, NULL)); 909a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_gamma", "0 <= gamma <= 1", api, kctx->gamma, &kctx->gamma, NULL)); 910a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_alpha", "1 < alpha <= 2", api, kctx->alpha, &kctx->alpha, NULL)); 9110f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_alpha2", "alpha2", NULL, kctx->alpha2, &kctx->alpha2, NULL)); 912a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_threshold", "0 < threshold < 1", api, kctx->threshold, &kctx->threshold, NULL)); 9130f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_p1", "p1", NULL, kctx->v4_p1, &kctx->v4_p1, NULL)); 9140f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_p2", "p2", NULL, kctx->v4_p2, &kctx->v4_p2, NULL)); 9150f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_p3", "p3", NULL, kctx->v4_p3, &kctx->v4_p3, NULL)); 9160f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_m1", "Scaling when rk-1 in [p2,p3)", NULL, kctx->v4_m1, &kctx->v4_m1, NULL)); 9170f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_m2", "Scaling when rk-1 in [p3,+infty)", NULL, kctx->v4_m2, &kctx->v4_m2, NULL)); 9180f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_m3", "Threshold for successive rtol (0.1 in Eq.7)", NULL, kctx->v4_m3, &kctx->v4_m3, NULL)); 9190f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_m4", "Adaptation scaling (0.5 in Eq.7)", NULL, kctx->v4_m4, &kctx->v4_m4, NULL)); 9200f0abf79SStefano Zampini PetscOptionsEnd(); 9213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9220f0abf79SStefano Zampini } 9230f0abf79SStefano Zampini 9249b94acceSBarry Smith /*@ 925f6dfbefdSBarry Smith SNESSetFromOptions - Sets various `SNES` and `KSP` parameters from user options. 9269b94acceSBarry Smith 927c3339decSBarry Smith Collective 928c7afd0dbSLois Curfman McInnes 9299b94acceSBarry Smith Input Parameter: 930f6dfbefdSBarry Smith . snes - the `SNES` context 9319b94acceSBarry Smith 93236851e7fSLois Curfman McInnes Options Database Keys: 933f6dfbefdSBarry Smith + -snes_type <type> - newtonls, newtontr, ngmres, ncg, nrichardson, qn, vi, fas, `SNESType` for complete list 934b39c3a46SLois Curfman McInnes . -snes_rtol <rtol> - relative decrease in tolerance norm from initial 93577e5a1f9SBarry Smith . -snes_atol <abstol> - absolute tolerance of residual norm 93677e5a1f9SBarry Smith . -snes_stol <stol> - convergence tolerance in terms of the norm of the change in the solution between steps 937e4d06f11SPatrick Farrell . -snes_divergence_tolerance <divtol> - if the residual goes above divtol*rnorm0, exit with divergence 938b39c3a46SLois Curfman McInnes . -snes_max_it <max_it> - maximum number of iterations 939b39c3a46SLois Curfman McInnes . -snes_max_funcs <max_funcs> - maximum number of function evaluations 94077e5a1f9SBarry Smith . -snes_force_iteration <force> - force `SNESSolve()` to take at least one iteration 9414839bfe8SBarry Smith . -snes_max_fail <max_fail> - maximum number of line search failures allowed before stopping, default is none 942ddf469c8SBarry Smith . -snes_max_linear_solve_fail - number of linear solver failures before SNESSolve() stops 943a8054027SBarry Smith . -snes_lag_preconditioner <lag> - how often preconditioner is rebuilt (use -1 to never rebuild) 9443d5a8a6aSBarry Smith . -snes_lag_preconditioner_persists <true,false> - retains the -snes_lag_preconditioner information across multiple SNESSolve() 945e35cf81dSBarry Smith . -snes_lag_jacobian <lag> - how often Jacobian is rebuilt (use -1 to never rebuild) 9463d5a8a6aSBarry Smith . -snes_lag_jacobian_persists <true,false> - retains the -snes_lag_jacobian information across multiple SNESSolve() 947ceaaa498SBarry 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. 948fde5950dSBarry Smith . -snes_monitor [ascii][:filename][:viewer format] - prints residual norm at each iteration. if no filename given prints to stdout 949fde5950dSBarry Smith . -snes_monitor_solution [ascii binary draw][:filename][:viewer format] - plots solution at each iteration 950fde5950dSBarry Smith . -snes_monitor_residual [ascii binary draw][:filename][:viewer format] - plots residual (not its norm) at each iteration 951fde5950dSBarry Smith . -snes_monitor_solution_update [ascii binary draw][:filename][:viewer format] - plots update to solution at each iteration 9524619e776SBarry Smith . -snes_monitor_lg_residualnorm - plots residual norm at each iteration 953459f5d12SBarry Smith . -snes_monitor_lg_range - plots residual norm at each iteration 9545e7c47f3SMatthew G. Knepley . -snes_monitor_pause_final - Pauses all monitor drawing after the solver ends 955e24b481bSBarry Smith . -snes_fd - use finite differences to compute Jacobian; very slow, only for testing 956e2e60de9SPeter Brune . -snes_fd_color - use finite differences with coloring to compute Jacobian 957ceaaa498SBarry Smith . -snes_mf_ksp_monitor - if using matrix-free multiply then print h at each `KSP` iteration 958b5badacbSBarry Smith . -snes_converged_reason - print the reason for convergence/divergence after each solve 959ceaaa498SBarry Smith . -npc_snes_type <type> - the `SNES` type to use as a nonlinear preconditioner 960e62ac41dSBarry 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. 961e62ac41dSBarry 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. 96282738288SBarry Smith 963f6dfbefdSBarry Smith Options Database Keys for Eisenstat-Walker method: 964fa9f3622SBarry Smith + -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence 9654b27c08aSLois Curfman McInnes . -snes_ksp_ew_version ver - version of Eisenstat-Walker method 96636851e7fSLois Curfman McInnes . -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0 96736851e7fSLois Curfman McInnes . -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax 96836851e7fSLois Curfman McInnes . -snes_ksp_ew_gamma <gamma> - Sets gamma 96936851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha <alpha> - Sets alpha 97036851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2 97136851e7fSLois Curfman McInnes - -snes_ksp_ew_threshold <threshold> - Sets threshold 97282738288SBarry Smith 973dc4c0fb0SBarry Smith Level: beginner 974dc4c0fb0SBarry Smith 97511ca99fdSLois Curfman McInnes Notes: 976ec5066bdSBarry Smith To see all options, run your program with the -help option or consult the users manual 977ec5066bdSBarry Smith 978420bcc1bSBarry Smith `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`, 979420bcc1bSBarry Smith and computing explicitly with 980f6dfbefdSBarry Smith finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object. 98183e2fdc7SBarry Smith 982420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESType`, `SNESSetOptionsPrefix()`, `SNESResetFromOptions()`, `SNES`, `SNESCreate()`, `MatCreateSNESMF()`, `MatFDColoring` 9839b94acceSBarry Smith @*/ 984d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFromOptions(SNES snes) 985d71ae5a4SJacob Faibussowitsch { 9868afaa268SBarry Smith PetscBool flg, pcset, persist, set; 98777e5a1f9SBarry Smith PetscInt i, indx, lag, grids, max_its, max_funcs; 98804d7464bSBarry Smith const char *deft = SNESNEWTONLS; 989649ef022SMatthew Knepley const char *convtests[] = {"default", "skip", "correct_pressure"}; 99085385478SLisandro Dalcin SNESKSPEW *kctx = NULL; 9910f0abf79SStefano Zampini char type[256], monfilename[PETSC_MAX_PATH_LEN], ewprefix[256]; 992c40d0f55SPeter Brune PCSide pcside; 993a64e098fSPeter Brune const char *optionsprefix; 99477e5a1f9SBarry Smith PetscReal rtol, abstol, stol; 9959b94acceSBarry Smith 9963a40ed3dSBarry Smith PetscFunctionBegin; 9970700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 9989566063dSJacob Faibussowitsch PetscCall(SNESRegisterAll()); 999d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)snes); 1000639ff905SBarry Smith if (((PetscObject)snes)->type_name) deft = ((PetscObject)snes)->type_name; 10019566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-snes_type", "Nonlinear solver method", "SNESSetType", SNESList, deft, type, 256, &flg)); 1002d64ed03dSBarry Smith if (flg) { 10039566063dSJacob Faibussowitsch PetscCall(SNESSetType(snes, type)); 10047adad957SLisandro Dalcin } else if (!((PetscObject)snes)->type_name) { 10059566063dSJacob Faibussowitsch PetscCall(SNESSetType(snes, deft)); 1006d64ed03dSBarry Smith } 1007186905e3SBarry Smith 100877e5a1f9SBarry Smith abstol = snes->abstol; 100977e5a1f9SBarry Smith rtol = snes->rtol; 101077e5a1f9SBarry Smith stol = snes->stol; 101177e5a1f9SBarry Smith max_its = snes->max_its; 101277e5a1f9SBarry Smith max_funcs = snes->max_funcs; 101377e5a1f9SBarry Smith PetscCall(PetscOptionsReal("-snes_rtol", "Stop if decrease in function norm less than", "SNESSetTolerances", snes->rtol, &rtol, NULL)); 101477e5a1f9SBarry Smith PetscCall(PetscOptionsReal("-snes_atol", "Stop if function norm less than", "SNESSetTolerances", snes->abstol, &abstol, NULL)); 101577e5a1f9SBarry Smith PetscCall(PetscOptionsReal("-snes_stol", "Stop if step length less than", "SNESSetTolerances", snes->stol, &stol, NULL)); 101677e5a1f9SBarry Smith PetscCall(PetscOptionsInt("-snes_max_it", "Maximum iterations", "SNESSetTolerances", snes->max_its, &max_its, NULL)); 101777e5a1f9SBarry Smith PetscCall(PetscOptionsInt("-snes_max_funcs", "Maximum function evaluations", "SNESSetTolerances", snes->max_funcs, &max_funcs, NULL)); 101877e5a1f9SBarry Smith PetscCall(SNESSetTolerances(snes, abstol, rtol, stol, max_its, max_funcs)); 101977e5a1f9SBarry Smith 102077e5a1f9SBarry Smith PetscCall(PetscOptionsReal("-snes_divergence_tolerance", "Stop if residual norm increases by this factor", "SNESSetDivergenceTolerance", snes->divtol, &snes->divtol, &flg)); 102177e5a1f9SBarry Smith if (flg) PetscCall(SNESSetDivergenceTolerance(snes, snes->divtol)); 102277e5a1f9SBarry Smith 102377e5a1f9SBarry Smith PetscCall(PetscOptionsInt("-snes_max_fail", "Maximum nonlinear step failures", "SNESSetMaxNonlinearStepFailures", snes->maxFailures, &snes->maxFailures, &flg)); 102477e5a1f9SBarry Smith if (flg) PetscCall(SNESSetMaxNonlinearStepFailures(snes, snes->maxFailures)); 102577e5a1f9SBarry Smith 102677e5a1f9SBarry Smith PetscCall(PetscOptionsInt("-snes_max_linear_solve_fail", "Maximum failures in linear solves allowed", "SNESSetMaxLinearSolveFailures", snes->maxLinearSolveFailures, &snes->maxLinearSolveFailures, &flg)); 102777e5a1f9SBarry Smith if (flg) PetscCall(SNESSetMaxLinearSolveFailures(snes, snes->maxLinearSolveFailures)); 102877e5a1f9SBarry Smith 10299566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_error_if_not_converged", "Generate error if solver does not converge", "SNESSetErrorIfNotConverged", snes->errorifnotconverged, &snes->errorifnotconverged, NULL)); 10309566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_force_iteration", "Force SNESSolve() to take at least one iteration", "SNESSetForceIteration", snes->forceiteration, &snes->forceiteration, NULL)); 10319566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_check_jacobian_domain_error", "Check Jacobian domain error after Jacobian evaluation", "SNESCheckJacobianDomainError", snes->checkjacdomainerror, &snes->checkjacdomainerror, NULL)); 103285385478SLisandro Dalcin 10339566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_lag_preconditioner", "How often to rebuild preconditioner", "SNESSetLagPreconditioner", snes->lagpreconditioner, &lag, &flg)); 1034a8054027SBarry Smith if (flg) { 10355f80ce2aSJacob 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"); 10369566063dSJacob Faibussowitsch PetscCall(SNESSetLagPreconditioner(snes, lag)); 1037a8054027SBarry Smith } 10389566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_lag_preconditioner_persists", "Preconditioner lagging through multiple SNES solves", "SNESSetLagPreconditionerPersists", snes->lagjac_persist, &persist, &flg)); 10391baa6e33SBarry Smith if (flg) PetscCall(SNESSetLagPreconditionerPersists(snes, persist)); 10409566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_lag_jacobian", "How often to rebuild Jacobian", "SNESSetLagJacobian", snes->lagjacobian, &lag, &flg)); 1041e35cf81dSBarry Smith if (flg) { 10425f80ce2aSJacob 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"); 10439566063dSJacob Faibussowitsch PetscCall(SNESSetLagJacobian(snes, lag)); 1044e35cf81dSBarry Smith } 10459566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_lag_jacobian_persists", "Jacobian lagging through multiple SNES solves", "SNESSetLagJacobianPersists", snes->lagjac_persist, &persist, &flg)); 10461baa6e33SBarry Smith if (flg) PetscCall(SNESSetLagJacobianPersists(snes, persist)); 104737ec4e1aSPeter Brune 10489566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_grid_sequence", "Use grid sequencing to generate initial guess", "SNESSetGridSequence", snes->gridsequence, &grids, &flg)); 10491baa6e33SBarry Smith if (flg) PetscCall(SNESSetGridSequence(snes, grids)); 1050a8054027SBarry Smith 1051400f6f02SBarry Smith PetscCall(PetscOptionsEList("-snes_convergence_test", "Convergence test", "SNESSetConvergenceTest", convtests, PETSC_STATIC_ARRAY_LENGTH(convtests), "default", &indx, &flg)); 105285385478SLisandro Dalcin if (flg) { 105385385478SLisandro Dalcin switch (indx) { 1054d71ae5a4SJacob Faibussowitsch case 0: 1055d71ae5a4SJacob Faibussowitsch PetscCall(SNESSetConvergenceTest(snes, SNESConvergedDefault, NULL, NULL)); 1056d71ae5a4SJacob Faibussowitsch break; 1057d71ae5a4SJacob Faibussowitsch case 1: 1058d71ae5a4SJacob Faibussowitsch PetscCall(SNESSetConvergenceTest(snes, SNESConvergedSkip, NULL, NULL)); 1059d71ae5a4SJacob Faibussowitsch break; 1060d71ae5a4SJacob Faibussowitsch case 2: 1061d71ae5a4SJacob Faibussowitsch PetscCall(SNESSetConvergenceTest(snes, SNESConvergedCorrectPressure, NULL, NULL)); 1062d71ae5a4SJacob Faibussowitsch break; 106385385478SLisandro Dalcin } 106485385478SLisandro Dalcin } 106585385478SLisandro Dalcin 10669566063dSJacob Faibussowitsch PetscCall(PetscOptionsEList("-snes_norm_schedule", "SNES Norm schedule", "SNESSetNormSchedule", SNESNormSchedules, 5, "function", &indx, &flg)); 10679566063dSJacob Faibussowitsch if (flg) PetscCall(SNESSetNormSchedule(snes, (SNESNormSchedule)indx)); 1068fdacfa88SPeter Brune 10699566063dSJacob Faibussowitsch PetscCall(PetscOptionsEList("-snes_function_type", "SNES Norm schedule", "SNESSetFunctionType", SNESFunctionTypes, 2, "unpreconditioned", &indx, &flg)); 10709566063dSJacob Faibussowitsch if (flg) PetscCall(SNESSetFunctionType(snes, (SNESFunctionType)indx)); 1071186905e3SBarry Smith 107285385478SLisandro Dalcin kctx = (SNESKSPEW *)snes->kspconvctx; 107385385478SLisandro Dalcin 10749566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_ksp_ew", "Use Eisentat-Walker linear system convergence test", "SNESKSPSetUseEW", snes->ksp_ewconv, &snes->ksp_ewconv, NULL)); 1075186905e3SBarry Smith 10760f0abf79SStefano Zampini PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 10770f0abf79SStefano Zampini PetscCall(PetscSNPrintf(ewprefix, sizeof(ewprefix), "%s%s", optionsprefix ? optionsprefix : "", "snes_")); 1078a4598233SStefano Zampini PetscCall(SNESEWSetFromOptions_Private(kctx, PETSC_TRUE, PetscObjectComm((PetscObject)snes), ewprefix)); 1079186905e3SBarry Smith 108090d69ab7SBarry Smith flg = PETSC_FALSE; 10819566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_monitor_cancel", "Remove all monitors", "SNESMonitorCancel", flg, &flg, &set)); 10829566063dSJacob Faibussowitsch if (set && flg) PetscCall(SNESMonitorCancel(snes)); 1083eabae89aSBarry Smith 10849566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor", "Monitor norm of function", "SNESMonitorDefault", SNESMonitorDefault, SNESMonitorDefaultSetUp)); 10859566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_short", "Monitor norm of function with fewer digits", "SNESMonitorDefaultShort", SNESMonitorDefaultShort, NULL)); 10869566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_range", "Monitor range of elements of function", "SNESMonitorRange", SNESMonitorRange, NULL)); 1087eabae89aSBarry Smith 10889566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_ratio", "Monitor ratios of the norm of function for consecutive steps", "SNESMonitorRatio", SNESMonitorRatio, SNESMonitorRatioSetUp)); 10899566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_field", "Monitor norm of function (split into fields)", "SNESMonitorDefaultField", SNESMonitorDefaultField, NULL)); 10909566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution", "View solution at each iteration", "SNESMonitorSolution", SNESMonitorSolution, NULL)); 10919566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution_update", "View correction at each iteration", "SNESMonitorSolutionUpdate", SNESMonitorSolutionUpdate, NULL)); 10929566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_residual", "View residual at each iteration", "SNESMonitorResidual", SNESMonitorResidual, NULL)); 10939566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_jacupdate_spectrum", "Print the change in the spectrum of the Jacobian", "SNESMonitorJacUpdateSpectrum", SNESMonitorJacUpdateSpectrum, NULL)); 10949566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_fields", "Monitor norm of function per field", "SNESMonitorSet", SNESMonitorFields, NULL)); 10959566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_monitor_pause_final", "Pauses all draw monitors at the final iterate", "SNESMonitorPauseFinal_Internal", PETSC_FALSE, &snes->pauseFinal, NULL)); 10962db13446SMatthew G. Knepley 10979566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-snes_monitor_python", "Use Python function", "SNESMonitorSet", NULL, monfilename, sizeof(monfilename), &flg)); 10989566063dSJacob Faibussowitsch if (flg) PetscCall(PetscPythonMonitorSet((PetscObject)snes, monfilename)); 10995180491cSLisandro Dalcin 110090d69ab7SBarry Smith flg = PETSC_FALSE; 11019566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_monitor_lg_range", "Plot function range at each iteration", "SNESMonitorLGRange", flg, &flg, NULL)); 1102459f5d12SBarry Smith if (flg) { 1103459f5d12SBarry Smith PetscViewer ctx; 1104e24b481bSBarry Smith 11059566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &ctx)); 110649abdd8aSBarry Smith PetscCall(SNESMonitorSet(snes, SNESMonitorLGRange, ctx, (PetscCtxDestroyFn *)PetscViewerDestroy)); 1107459f5d12SBarry Smith } 11082e7541e6SPeter Brune 1109648c30bcSBarry Smith PetscCall(PetscViewerDestroy(&snes->convergedreasonviewer)); 1110648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_converged_reason", &snes->convergedreasonviewer, &snes->convergedreasonformat, NULL)); 111190d69ab7SBarry Smith flg = PETSC_FALSE; 11129566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_converged_reason_view_cancel", "Remove all converged reason viewers", "SNESConvergedReasonViewCancel", flg, &flg, &set)); 11139566063dSJacob Faibussowitsch if (set && flg) PetscCall(SNESConvergedReasonViewCancel(snes)); 1114c4421ceaSFande Kong 1115c4421ceaSFande Kong flg = PETSC_FALSE; 11169566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_fd", "Use finite differences (slow) to compute Jacobian", "SNESComputeJacobianDefault", flg, &flg, NULL)); 11174b27c08aSLois Curfman McInnes if (flg) { 11186cab3a1bSJed Brown void *functx; 1119b1f624c7SBarry Smith DM dm; 11209566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 1121800f99ffSJeremy L Thompson PetscCall(DMSNESUnsetJacobianContext_Internal(dm)); 11229566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, NULL, &functx)); 11239566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefault, functx)); 11249566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Setting default finite difference Jacobian matrix\n")); 11259b94acceSBarry Smith } 1126639f9d9dSBarry Smith 112744848bc4SPeter Brune flg = PETSC_FALSE; 11289566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_fd_function", "Use finite differences (slow) to compute function from user objective", "SNESObjectiveComputeFunctionDefaultFD", flg, &flg, NULL)); 11291baa6e33SBarry Smith if (flg) PetscCall(SNESSetFunction(snes, NULL, SNESObjectiveComputeFunctionDefaultFD, NULL)); 113097584545SPeter Brune 113197584545SPeter Brune flg = PETSC_FALSE; 11329566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_fd_color", "Use finite differences with coloring to compute Jacobian", "SNESComputeJacobianDefaultColor", flg, &flg, NULL)); 113344848bc4SPeter Brune if (flg) { 1134c52e227fSPeter Brune DM dm; 11359566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 1136800f99ffSJeremy L Thompson PetscCall(DMSNESUnsetJacobianContext_Internal(dm)); 11379566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefaultColor, NULL)); 11389566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Setting default finite difference coloring Jacobian matrix\n")); 113944848bc4SPeter Brune } 114044848bc4SPeter Brune 1141aa3661deSLisandro Dalcin flg = PETSC_FALSE; 11429566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_mf_operator", "Use a Matrix-Free Jacobian with user-provided preconditioner matrix", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf_operator, &flg)); 1143d8f46077SPeter Brune if (flg && snes->mf_operator) { 1144a8248277SBarry Smith snes->mf_operator = PETSC_TRUE; 1145d8f46077SPeter Brune snes->mf = PETSC_TRUE; 1146a8248277SBarry Smith } 1147aa3661deSLisandro Dalcin flg = PETSC_FALSE; 11489566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_mf", "Use a Matrix-Free Jacobian with no preconditioner matrix", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf, &flg)); 1149d8f46077SPeter Brune if (!flg && snes->mf_operator) snes->mf = PETSC_TRUE; 11509566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_mf_version", "Matrix-Free routines version 1 or 2", "None", snes->mf_version, &snes->mf_version, NULL)); 1151d28543b3SPeter Brune 1152c40d0f55SPeter Brune flg = PETSC_FALSE; 11539566063dSJacob Faibussowitsch PetscCall(SNESGetNPCSide(snes, &pcside)); 11549566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-snes_npc_side", "SNES nonlinear preconditioner side", "SNESSetNPCSide", PCSides, (PetscEnum)pcside, (PetscEnum *)&pcside, &flg)); 11559566063dSJacob Faibussowitsch if (flg) PetscCall(SNESSetNPCSide(snes, pcside)); 1156c40d0f55SPeter Brune 1157e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS) 11588a70d858SHong Zhang /* 11598a70d858SHong Zhang Publish convergence information using SAWs 11608a70d858SHong Zhang */ 11618a70d858SHong Zhang flg = PETSC_FALSE; 11629566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_monitor_saws", "Publish SNES progress using SAWs", "SNESMonitorSet", flg, &flg, NULL)); 11638a70d858SHong Zhang if (flg) { 11648a70d858SHong Zhang void *ctx; 11659566063dSJacob Faibussowitsch PetscCall(SNESMonitorSAWsCreate(snes, &ctx)); 11669566063dSJacob Faibussowitsch PetscCall(SNESMonitorSet(snes, SNESMonitorSAWs, ctx, SNESMonitorSAWsDestroy)); 11678a70d858SHong Zhang } 11688a70d858SHong Zhang #endif 11698a70d858SHong Zhang #if defined(PETSC_HAVE_SAWS) 1170b90c6cbeSBarry Smith { 1171b90c6cbeSBarry Smith PetscBool set; 1172b90c6cbeSBarry Smith flg = PETSC_FALSE; 11739566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_saws_block", "Block for SAWs at end of SNESSolve", "PetscObjectSAWsBlock", ((PetscObject)snes)->amspublishblock, &flg, &set)); 11741baa6e33SBarry Smith if (set) PetscCall(PetscObjectSAWsSetBlock((PetscObject)snes, flg)); 1175b90c6cbeSBarry Smith } 1176b90c6cbeSBarry Smith #endif 1177b90c6cbeSBarry Smith 117848a46eb9SPierre Jolivet for (i = 0; i < numberofsetfromoptions; i++) PetscCall((*othersetfromoptions[i])(snes)); 117976b2cf59SMatthew Knepley 1180dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, setfromoptions, PetscOptionsObject); 11815d973c19SBarry Smith 11825d973c19SBarry Smith /* process any options handlers added with PetscObjectAddOptionsHandler() */ 1183dbbe0bcdSBarry Smith PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)snes, PetscOptionsObject)); 1184d0609cedSBarry Smith PetscOptionsEnd(); 11854bbc92c1SBarry Smith 1186d8d34be6SBarry Smith if (snes->linesearch) { 11879566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 11889566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetFromOptions(snes->linesearch)); 1189d8d34be6SBarry Smith } 11909e764e56SPeter Brune 11916aa5e7e9SBarry Smith if (snes->usesksp) { 11929566063dSJacob Faibussowitsch if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 11939566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(snes->ksp, snes->jacobian, snes->jacobian_pre)); 11949566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(snes->ksp)); 11956aa5e7e9SBarry Smith } 11966991f827SBarry Smith 1197b5badacbSBarry Smith /* if user has set the SNES NPC type via options database, create it. */ 11989566063dSJacob Faibussowitsch PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 11999566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)snes)->options, optionsprefix, "-npc_snes_type", &pcset)); 120048a46eb9SPierre Jolivet if (pcset && (!snes->npc)) PetscCall(SNESGetNPC(snes, &snes->npc)); 12011baa6e33SBarry Smith if (snes->npc) PetscCall(SNESSetFromOptions(snes->npc)); 1202b3cd9a81SMatthew G. Knepley snes->setfromoptionscalled++; 12033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1204b3cd9a81SMatthew G. Knepley } 1205b3cd9a81SMatthew G. Knepley 1206b3cd9a81SMatthew G. Knepley /*@ 1207420bcc1bSBarry Smith SNESResetFromOptions - Sets various `SNES` and `KSP` parameters from user options ONLY if the `SNESSetFromOptions()` was previously called 1208b3cd9a81SMatthew G. Knepley 1209c3339decSBarry Smith Collective 1210b3cd9a81SMatthew G. Knepley 1211b3cd9a81SMatthew G. Knepley Input Parameter: 1212f6dfbefdSBarry Smith . snes - the `SNES` context 1213b3cd9a81SMatthew G. Knepley 1214420bcc1bSBarry Smith Level: advanced 1215b3cd9a81SMatthew G. Knepley 12161cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESSetOptionsPrefix()` 1217b3cd9a81SMatthew G. Knepley @*/ 1218d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESResetFromOptions(SNES snes) 1219d71ae5a4SJacob Faibussowitsch { 1220b3cd9a81SMatthew G. Knepley PetscFunctionBegin; 12219566063dSJacob Faibussowitsch if (snes->setfromoptionscalled) PetscCall(SNESSetFromOptions(snes)); 12223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12239b94acceSBarry Smith } 12249b94acceSBarry Smith 1225bb9467b5SJed Brown /*@C 1226d25893d9SBarry Smith SNESSetComputeApplicationContext - Sets an optional function to compute a user-defined context for 1227d25893d9SBarry Smith the nonlinear solvers. 1228d25893d9SBarry Smith 1229dc4c0fb0SBarry Smith Logically Collective; No Fortran Support 1230d25893d9SBarry Smith 1231d25893d9SBarry Smith Input Parameters: 1232f6dfbefdSBarry Smith + snes - the `SNES` context 1233d25893d9SBarry Smith . compute - function to compute the context 123449abdd8aSBarry Smith - destroy - function to destroy the context, see `PetscCtxDestroyFn` for the calling sequence 1235d25893d9SBarry Smith 1236420bcc1bSBarry Smith Calling sequence of `compute`: 1237420bcc1bSBarry Smith + snes - the `SNES` context 1238420bcc1bSBarry Smith - ctx - context to be computed 1239420bcc1bSBarry Smith 1240d25893d9SBarry Smith Level: intermediate 1241d25893d9SBarry Smith 1242f6dfbefdSBarry Smith Note: 1243f6dfbefdSBarry Smith This routine is useful if you are performing grid sequencing or using `SNESFAS` and need the appropriate context generated for each level. 1244f6dfbefdSBarry Smith 1245f6dfbefdSBarry Smith Use `SNESSetApplicationContext()` to see the context immediately 1246f6dfbefdSBarry Smith 124749abdd8aSBarry Smith .seealso: [](ch_snes), `SNESGetApplicationContext()`, `SNESSetApplicationContext()`, `PetscCtxDestroyFn` 1248d25893d9SBarry Smith @*/ 124949abdd8aSBarry Smith PetscErrorCode SNESSetComputeApplicationContext(SNES snes, PetscErrorCode (*compute)(SNES snes, void **ctx), PetscCtxDestroyFn *destroy) 1250d71ae5a4SJacob Faibussowitsch { 1251d25893d9SBarry Smith PetscFunctionBegin; 1252d25893d9SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1253d25893d9SBarry Smith snes->ops->usercompute = compute; 125449abdd8aSBarry Smith snes->ops->ctxdestroy = destroy; 12553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1256d25893d9SBarry Smith } 1257a847f771SSatish Balay 1258b07ff414SBarry Smith /*@ 1259f6dfbefdSBarry Smith SNESSetApplicationContext - Sets the optional user-defined context for the nonlinear solvers. 12609b94acceSBarry Smith 1261c3339decSBarry Smith Logically Collective 1262fee21e36SBarry Smith 1263c7afd0dbSLois Curfman McInnes Input Parameters: 1264f6dfbefdSBarry Smith + snes - the `SNES` context 126549abdd8aSBarry Smith - ctx - optional user context 1266c7afd0dbSLois Curfman McInnes 126736851e7fSLois Curfman McInnes Level: intermediate 126836851e7fSLois Curfman McInnes 1269f6dfbefdSBarry Smith Notes: 1270f6dfbefdSBarry Smith Users can provide a context when constructing the `SNES` options and then access it inside their function, Jacobian, or other evaluation function 1271f6dfbefdSBarry Smith with `SNESGetApplicationContext()` 1272f6dfbefdSBarry Smith 1273f6dfbefdSBarry Smith To provide a function that computes the context for you use `SNESSetComputeApplicationContext()` 1274f6dfbefdSBarry Smith 1275420bcc1bSBarry Smith Fortran Note: 1276dc4c0fb0SBarry Smith You must write a Fortran interface definition for this 1277420bcc1bSBarry Smith function that tells Fortran the Fortran derived data type that you are passing in as the `usrP` argument. 1278daf670e6SBarry Smith 12791cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetComputeApplicationContext()`, `SNESGetApplicationContext()` 12809b94acceSBarry Smith @*/ 128149abdd8aSBarry Smith PetscErrorCode SNESSetApplicationContext(SNES snes, void *ctx) 1282d71ae5a4SJacob Faibussowitsch { 1283b07ff414SBarry Smith KSP ksp; 12841b2093e4SBarry Smith 12853a40ed3dSBarry Smith PetscFunctionBegin; 12860700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 12879566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 128849abdd8aSBarry Smith PetscCall(KSPSetApplicationContext(ksp, ctx)); 128949abdd8aSBarry Smith snes->ctx = ctx; 12903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12919b94acceSBarry Smith } 129274679c65SBarry Smith 1293b07ff414SBarry Smith /*@ 12949b94acceSBarry Smith SNESGetApplicationContext - Gets the user-defined context for the 1295420bcc1bSBarry Smith nonlinear solvers set with `SNESGetApplicationContext()` or `SNESSetComputeApplicationContext()` 12969b94acceSBarry Smith 1297c7afd0dbSLois Curfman McInnes Not Collective 1298c7afd0dbSLois Curfman McInnes 12999b94acceSBarry Smith Input Parameter: 1300f6dfbefdSBarry Smith . snes - `SNES` context 13019b94acceSBarry Smith 13029b94acceSBarry Smith Output Parameter: 130349abdd8aSBarry Smith . ctx - user context 13049b94acceSBarry Smith 130536851e7fSLois Curfman McInnes Level: intermediate 130636851e7fSLois Curfman McInnes 1307420bcc1bSBarry Smith Fortran Note: 1308dc4c0fb0SBarry Smith You must write a Fortran interface definition for this 1309420bcc1bSBarry Smith function that tells Fortran the Fortran derived data type that you are passing in as the `usrP` argument. 1310dc4c0fb0SBarry Smith 1311420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESSetApplicationContext()`, `SNESSetComputeApplicationContext()` 13129b94acceSBarry Smith @*/ 131349abdd8aSBarry Smith PetscErrorCode SNESGetApplicationContext(SNES snes, void *ctx) 1314d71ae5a4SJacob Faibussowitsch { 13153a40ed3dSBarry Smith PetscFunctionBegin; 13160700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 131749abdd8aSBarry Smith *(void **)ctx = snes->ctx; 13183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13199b94acceSBarry Smith } 132074679c65SBarry Smith 13219b94acceSBarry Smith /*@ 1322420bcc1bSBarry Smith SNESSetUseMatrixFree - indicates that `SNES` should use matrix-free finite difference matrix-vector products to apply the Jacobian. 13233565c898SBarry Smith 1324dc4c0fb0SBarry Smith Logically Collective 13253565c898SBarry Smith 13263565c898SBarry Smith Input Parameters: 1327f6dfbefdSBarry Smith + snes - `SNES` context 1328f6dfbefdSBarry Smith . mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used 1329f6dfbefdSBarry 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 1330420bcc1bSBarry Smith this option no matrix-element based preconditioners can be used in the linear solve since the matrix won't be explicitly available 13313565c898SBarry Smith 1332f6dfbefdSBarry Smith Options Database Keys: 133301c1178eSBarry Smith + -snes_mf_operator - use matrix-free only for the mat operator 1334f6dfbefdSBarry Smith . -snes_mf - use matrix-free for both the mat and pmat operator 1335ec5066bdSBarry Smith . -snes_fd_color - compute the Jacobian via coloring and finite differences. 1336ec5066bdSBarry Smith - -snes_fd - compute the Jacobian via finite differences (slow) 13373565c898SBarry Smith 13383565c898SBarry Smith Level: intermediate 13393565c898SBarry Smith 1340f6dfbefdSBarry Smith Note: 1341420bcc1bSBarry Smith `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`, 1342420bcc1bSBarry Smith and computing explicitly with 1343f6dfbefdSBarry Smith finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object. 1344ec5066bdSBarry Smith 1345420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetUseMatrixFree()`, `MatCreateSNESMF()`, `SNESComputeJacobianDefaultColor()`, `MatFDColoring` 13463565c898SBarry Smith @*/ 1347d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUseMatrixFree(SNES snes, PetscBool mf_operator, PetscBool mf) 1348d71ae5a4SJacob Faibussowitsch { 13493565c898SBarry Smith PetscFunctionBegin; 13503565c898SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 135188b4c220SStefano Zampini PetscValidLogicalCollectiveBool(snes, mf_operator, 2); 135288b4c220SStefano Zampini PetscValidLogicalCollectiveBool(snes, mf, 3); 13534ddffce6SLisandro Dalcin snes->mf = mf_operator ? PETSC_TRUE : mf; 13543565c898SBarry Smith snes->mf_operator = mf_operator; 13553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13563565c898SBarry Smith } 13573565c898SBarry Smith 13583565c898SBarry Smith /*@ 1359dc4c0fb0SBarry Smith SNESGetUseMatrixFree - indicates if the `SNES` uses matrix-free finite difference matrix vector products to apply the Jacobian. 13603565c898SBarry Smith 1361420bcc1bSBarry Smith Not Collective, but the resulting flags will be the same on all MPI processes 13623565c898SBarry Smith 13633565c898SBarry Smith Input Parameter: 1364f6dfbefdSBarry Smith . snes - `SNES` context 13653565c898SBarry Smith 13663565c898SBarry Smith Output Parameters: 1367f6dfbefdSBarry Smith + mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used 1368f6dfbefdSBarry 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 13693565c898SBarry Smith 13703565c898SBarry Smith Level: intermediate 13713565c898SBarry Smith 13721cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUseMatrixFree()`, `MatCreateSNESMF()` 13733565c898SBarry Smith @*/ 1374d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUseMatrixFree(SNES snes, PetscBool *mf_operator, PetscBool *mf) 1375d71ae5a4SJacob Faibussowitsch { 13763565c898SBarry Smith PetscFunctionBegin; 13773565c898SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 13783565c898SBarry Smith if (mf) *mf = snes->mf; 13793565c898SBarry Smith if (mf_operator) *mf_operator = snes->mf_operator; 13803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13813565c898SBarry Smith } 13823565c898SBarry Smith 13833565c898SBarry Smith /*@ 1384420bcc1bSBarry Smith SNESGetIterationNumber - Gets the number of nonlinear iterations completed in the current or most recent `SNESSolve()` 13859b94acceSBarry Smith 1386c7afd0dbSLois Curfman McInnes Not Collective 1387c7afd0dbSLois Curfman McInnes 13889b94acceSBarry Smith Input Parameter: 1389f6dfbefdSBarry Smith . snes - `SNES` context 13909b94acceSBarry Smith 13919b94acceSBarry Smith Output Parameter: 13929b94acceSBarry Smith . iter - iteration number 13939b94acceSBarry Smith 1394dc4c0fb0SBarry Smith Level: intermediate 1395dc4c0fb0SBarry Smith 1396c8228a4eSBarry Smith Notes: 1397c8228a4eSBarry Smith For example, during the computation of iteration 2 this would return 1. 1398c8228a4eSBarry Smith 1399c8228a4eSBarry Smith This is useful for using lagged Jacobians (where one does not recompute the 1400f6dfbefdSBarry Smith Jacobian at each `SNES` iteration). For example, the code 140108405cd6SLois Curfman McInnes .vb 140208405cd6SLois Curfman McInnes ierr = SNESGetIterationNumber(snes,&it); 140308405cd6SLois Curfman McInnes if (!(it % 2)) { 140408405cd6SLois Curfman McInnes [compute Jacobian here] 140508405cd6SLois Curfman McInnes } 140608405cd6SLois Curfman McInnes .ve 1407f6dfbefdSBarry Smith can be used in your function that computes the Jacobian to cause the Jacobian to be 1408f6dfbefdSBarry Smith recomputed every second `SNES` iteration. See also `SNESSetLagJacobian()` 1409c8228a4eSBarry Smith 1410f6dfbefdSBarry Smith After the `SNES` solve is complete this will return the number of nonlinear iterations used. 1411c04deec6SBarry Smith 1412420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetLagJacobian()`, `SNESGetLinearSolveIterations()`, `SNESSetMonitor()` 14139b94acceSBarry Smith @*/ 1414d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetIterationNumber(SNES snes, PetscInt *iter) 1415d71ae5a4SJacob Faibussowitsch { 14163a40ed3dSBarry Smith PetscFunctionBegin; 14170700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 14184f572ea9SToby Isaac PetscAssertPointer(iter, 2); 14199b94acceSBarry Smith *iter = snes->iter; 14203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14219b94acceSBarry Smith } 142274679c65SBarry Smith 1423360c497dSPeter Brune /*@ 1424360c497dSPeter Brune SNESSetIterationNumber - Sets the current iteration number. 1425360c497dSPeter Brune 1426360c497dSPeter Brune Not Collective 1427360c497dSPeter Brune 1428d8d19677SJose E. Roman Input Parameters: 1429f6dfbefdSBarry Smith + snes - `SNES` context 1430a2b725a8SWilliam Gropp - iter - iteration number 1431360c497dSPeter Brune 1432360c497dSPeter Brune Level: developer 1433360c497dSPeter Brune 1434420bcc1bSBarry Smith Note: 1435420bcc1bSBarry Smith This should only be called inside a `SNES` nonlinear solver. 1436420bcc1bSBarry Smith 14371cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetLinearSolveIterations()` 1438360c497dSPeter Brune @*/ 1439d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetIterationNumber(SNES snes, PetscInt iter) 1440d71ae5a4SJacob Faibussowitsch { 1441360c497dSPeter Brune PetscFunctionBegin; 1442360c497dSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 14439566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes)); 1444360c497dSPeter Brune snes->iter = iter; 14459566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes)); 14463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1447360c497dSPeter Brune } 1448360c497dSPeter Brune 14499b94acceSBarry Smith /*@ 1450b850b91aSLisandro Dalcin SNESGetNonlinearStepFailures - Gets the number of unsuccessful steps 1451420bcc1bSBarry Smith attempted by the nonlinear solver in the current or most recent `SNESSolve()` . 14529b94acceSBarry Smith 1453c7afd0dbSLois Curfman McInnes Not Collective 1454c7afd0dbSLois Curfman McInnes 14559b94acceSBarry Smith Input Parameter: 1456f6dfbefdSBarry Smith . snes - `SNES` context 14579b94acceSBarry Smith 14589b94acceSBarry Smith Output Parameter: 14599b94acceSBarry Smith . nfails - number of unsuccessful steps attempted 14609b94acceSBarry Smith 1461dc4c0fb0SBarry Smith Level: intermediate 1462dc4c0fb0SBarry Smith 1463f6dfbefdSBarry Smith Note: 1464f6dfbefdSBarry Smith This counter is reset to zero for each successive call to `SNESSolve()`. 1465c96a6f78SLois Curfman McInnes 14661cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, 1467db781477SPatrick Sanan `SNESSetMaxNonlinearStepFailures()`, `SNESGetMaxNonlinearStepFailures()` 14689b94acceSBarry Smith @*/ 1469d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNonlinearStepFailures(SNES snes, PetscInt *nfails) 1470d71ae5a4SJacob Faibussowitsch { 14713a40ed3dSBarry Smith PetscFunctionBegin; 14720700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 14734f572ea9SToby Isaac PetscAssertPointer(nfails, 2); 147450ffb88aSMatthew Knepley *nfails = snes->numFailures; 14753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 147650ffb88aSMatthew Knepley } 147750ffb88aSMatthew Knepley 147850ffb88aSMatthew Knepley /*@ 1479b850b91aSLisandro Dalcin SNESSetMaxNonlinearStepFailures - Sets the maximum number of unsuccessful steps 1480420bcc1bSBarry Smith attempted by the nonlinear solver before it gives up and returns unconverged or generates an error 148150ffb88aSMatthew Knepley 148250ffb88aSMatthew Knepley Not Collective 148350ffb88aSMatthew Knepley 148450ffb88aSMatthew Knepley Input Parameters: 1485f6dfbefdSBarry Smith + snes - `SNES` context 148677e5a1f9SBarry Smith - maxFails - maximum of unsuccessful steps allowed, use `PETSC_UNLIMITED` to have no limit on the number of failures 148750ffb88aSMatthew Knepley 1488420bcc1bSBarry Smith Options Database Key: 1489420bcc1bSBarry Smith . -snes_max_fail <n> - maximum number of unsuccessful steps allowed 1490420bcc1bSBarry Smith 149150ffb88aSMatthew Knepley Level: intermediate 149250ffb88aSMatthew Knepley 1493420bcc1bSBarry Smith Developer Note: 1494420bcc1bSBarry Smith The options database key is wrong for this function name 1495420bcc1bSBarry Smith 14961cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, 1497db781477SPatrick Sanan `SNESGetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()` 149850ffb88aSMatthew Knepley @*/ 1499d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxNonlinearStepFailures(SNES snes, PetscInt maxFails) 1500d71ae5a4SJacob Faibussowitsch { 150150ffb88aSMatthew Knepley PetscFunctionBegin; 15020700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 150377e5a1f9SBarry Smith 150477e5a1f9SBarry Smith if (maxFails == PETSC_UNLIMITED) { 15051690c2aeSBarry Smith snes->maxFailures = PETSC_INT_MAX; 150677e5a1f9SBarry Smith } else { 150777e5a1f9SBarry Smith PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures"); 150850ffb88aSMatthew Knepley snes->maxFailures = maxFails; 150977e5a1f9SBarry Smith } 15103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 151150ffb88aSMatthew Knepley } 151250ffb88aSMatthew Knepley 151350ffb88aSMatthew Knepley /*@ 1514b850b91aSLisandro Dalcin SNESGetMaxNonlinearStepFailures - Gets the maximum number of unsuccessful steps 1515420bcc1bSBarry Smith attempted by the nonlinear solver before it gives up and returns unconverged or generates an error 151650ffb88aSMatthew Knepley 151750ffb88aSMatthew Knepley Not Collective 151850ffb88aSMatthew Knepley 151950ffb88aSMatthew Knepley Input Parameter: 152020f4b53cSBarry Smith . snes - `SNES` context 152150ffb88aSMatthew Knepley 152250ffb88aSMatthew Knepley Output Parameter: 152350ffb88aSMatthew Knepley . maxFails - maximum of unsuccessful steps 152450ffb88aSMatthew Knepley 152550ffb88aSMatthew Knepley Level: intermediate 152650ffb88aSMatthew Knepley 15271cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, 1528db781477SPatrick Sanan `SNESSetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()` 152950ffb88aSMatthew Knepley @*/ 1530d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxNonlinearStepFailures(SNES snes, PetscInt *maxFails) 1531d71ae5a4SJacob Faibussowitsch { 153250ffb88aSMatthew Knepley PetscFunctionBegin; 15330700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 15344f572ea9SToby Isaac PetscAssertPointer(maxFails, 2); 153550ffb88aSMatthew Knepley *maxFails = snes->maxFailures; 15363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15379b94acceSBarry Smith } 1538a847f771SSatish Balay 15392541af92SBarry Smith /*@ 15402541af92SBarry Smith SNESGetNumberFunctionEvals - Gets the number of user provided function evaluations 1541420bcc1bSBarry Smith done by the `SNES` object in the current or most recent `SNESSolve()` 15422541af92SBarry Smith 15432541af92SBarry Smith Not Collective 15442541af92SBarry Smith 15452541af92SBarry Smith Input Parameter: 1546f6dfbefdSBarry Smith . snes - `SNES` context 15472541af92SBarry Smith 15482541af92SBarry Smith Output Parameter: 15492541af92SBarry Smith . nfuncs - number of evaluations 15502541af92SBarry Smith 15512541af92SBarry Smith Level: intermediate 15522541af92SBarry Smith 1553f6dfbefdSBarry Smith Note: 1554f6dfbefdSBarry Smith Reset every time `SNESSolve()` is called unless `SNESSetCountersReset()` is used. 1555971e163fSPeter Brune 15561cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, `SNESSetCountersReset()` 15572541af92SBarry Smith @*/ 1558d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNumberFunctionEvals(SNES snes, PetscInt *nfuncs) 1559d71ae5a4SJacob Faibussowitsch { 15602541af92SBarry Smith PetscFunctionBegin; 15610700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 15624f572ea9SToby Isaac PetscAssertPointer(nfuncs, 2); 15632541af92SBarry Smith *nfuncs = snes->nfuncs; 15643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15652541af92SBarry Smith } 15662541af92SBarry Smith 15673d4c4710SBarry Smith /*@ 15683d4c4710SBarry Smith SNESGetLinearSolveFailures - Gets the number of failed (non-converged) 1569420bcc1bSBarry Smith linear solvers in the current or most recent `SNESSolve()` 15703d4c4710SBarry Smith 15713d4c4710SBarry Smith Not Collective 15723d4c4710SBarry Smith 15733d4c4710SBarry Smith Input Parameter: 1574f6dfbefdSBarry Smith . snes - `SNES` context 15753d4c4710SBarry Smith 15763d4c4710SBarry Smith Output Parameter: 15773d4c4710SBarry Smith . nfails - number of failed solves 15783d4c4710SBarry Smith 1579f6dfbefdSBarry Smith Options Database Key: 15809d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated 15819d85da0cSMatthew G. Knepley 1582f6dfbefdSBarry Smith Level: intermediate 1583f6dfbefdSBarry Smith 1584f6dfbefdSBarry Smith Note: 1585f6dfbefdSBarry Smith This counter is reset to zero for each successive call to `SNESSolve()`. 15863d4c4710SBarry Smith 15871cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()` 15883d4c4710SBarry Smith @*/ 1589d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveFailures(SNES snes, PetscInt *nfails) 1590d71ae5a4SJacob Faibussowitsch { 15913d4c4710SBarry Smith PetscFunctionBegin; 15920700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 15934f572ea9SToby Isaac PetscAssertPointer(nfails, 2); 15943d4c4710SBarry Smith *nfails = snes->numLinearSolveFailures; 15953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15963d4c4710SBarry Smith } 15973d4c4710SBarry Smith 15983d4c4710SBarry Smith /*@ 15993d4c4710SBarry Smith SNESSetMaxLinearSolveFailures - the number of failed linear solve attempts 1600f6dfbefdSBarry Smith allowed before `SNES` returns with a diverged reason of `SNES_DIVERGED_LINEAR_SOLVE` 16013d4c4710SBarry Smith 1602c3339decSBarry Smith Logically Collective 16033d4c4710SBarry Smith 16043d4c4710SBarry Smith Input Parameters: 1605f6dfbefdSBarry Smith + snes - `SNES` context 160677e5a1f9SBarry Smith - maxFails - maximum allowed linear solve failures, use `PETSC_UNLIMITED` to have no limit on the number of failures 16073d4c4710SBarry Smith 1608f6dfbefdSBarry Smith Options Database Key: 16099d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated 16109d85da0cSMatthew G. Knepley 1611dc4c0fb0SBarry Smith Level: intermediate 1612dc4c0fb0SBarry Smith 1613f6dfbefdSBarry Smith Note: 1614f6dfbefdSBarry Smith By default this is 0; that is `SNES` returns on the first failed linear solve 16153d4c4710SBarry Smith 1616420bcc1bSBarry Smith Developer Note: 1617420bcc1bSBarry Smith The options database key is wrong for this function name 1618420bcc1bSBarry Smith 16191cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()` 16203d4c4710SBarry Smith @*/ 1621d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxLinearSolveFailures(SNES snes, PetscInt maxFails) 1622d71ae5a4SJacob Faibussowitsch { 16233d4c4710SBarry Smith PetscFunctionBegin; 16240700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1625c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, maxFails, 2); 162677e5a1f9SBarry Smith 162777e5a1f9SBarry Smith if (maxFails == PETSC_UNLIMITED) { 16281690c2aeSBarry Smith snes->maxLinearSolveFailures = PETSC_INT_MAX; 162977e5a1f9SBarry Smith } else { 163077e5a1f9SBarry Smith PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures"); 16313d4c4710SBarry Smith snes->maxLinearSolveFailures = maxFails; 163277e5a1f9SBarry Smith } 16333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16343d4c4710SBarry Smith } 16353d4c4710SBarry Smith 16363d4c4710SBarry Smith /*@ 16373d4c4710SBarry Smith SNESGetMaxLinearSolveFailures - gets the maximum number of linear solve failures that 1638f6dfbefdSBarry Smith are allowed before `SNES` returns as unsuccessful 16393d4c4710SBarry Smith 16403d4c4710SBarry Smith Not Collective 16413d4c4710SBarry Smith 16423d4c4710SBarry Smith Input Parameter: 1643f6dfbefdSBarry Smith . snes - `SNES` context 16443d4c4710SBarry Smith 16453d4c4710SBarry Smith Output Parameter: 16463d4c4710SBarry Smith . maxFails - maximum of unsuccessful solves allowed 16473d4c4710SBarry Smith 16483d4c4710SBarry Smith Level: intermediate 16493d4c4710SBarry Smith 1650f6dfbefdSBarry Smith Note: 1651f6dfbefdSBarry Smith By default this is 1; that is `SNES` returns on the first failed linear solve 16523d4c4710SBarry Smith 16531cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, 16543d4c4710SBarry Smith @*/ 1655d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxLinearSolveFailures(SNES snes, PetscInt *maxFails) 1656d71ae5a4SJacob Faibussowitsch { 16573d4c4710SBarry Smith PetscFunctionBegin; 16580700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 16594f572ea9SToby Isaac PetscAssertPointer(maxFails, 2); 16603d4c4710SBarry Smith *maxFails = snes->maxLinearSolveFailures; 16613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16623d4c4710SBarry Smith } 16633d4c4710SBarry Smith 1664c96a6f78SLois Curfman McInnes /*@ 1665b850b91aSLisandro Dalcin SNESGetLinearSolveIterations - Gets the total number of linear iterations 1666420bcc1bSBarry Smith used by the nonlinear solver in the most recent `SNESSolve()` 1667c96a6f78SLois Curfman McInnes 1668c7afd0dbSLois Curfman McInnes Not Collective 1669c7afd0dbSLois Curfman McInnes 1670c96a6f78SLois Curfman McInnes Input Parameter: 1671f6dfbefdSBarry Smith . snes - `SNES` context 1672c96a6f78SLois Curfman McInnes 1673c96a6f78SLois Curfman McInnes Output Parameter: 1674c96a6f78SLois Curfman McInnes . lits - number of linear iterations 1675c96a6f78SLois Curfman McInnes 1676dc4c0fb0SBarry Smith Level: intermediate 1677dc4c0fb0SBarry Smith 1678c96a6f78SLois Curfman McInnes Notes: 1679f6dfbefdSBarry Smith This counter is reset to zero for each successive call to `SNESSolve()` unless `SNESSetCountersReset()` is used. 1680c96a6f78SLois Curfman McInnes 1681f6dfbefdSBarry 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 1682f6dfbefdSBarry Smith then call `KSPGetIterationNumber()` after the failed solve. 1683010be392SBarry Smith 16841cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetIterationNumber()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESSetCountersReset()` 1685c96a6f78SLois Curfman McInnes @*/ 1686d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveIterations(SNES snes, PetscInt *lits) 1687d71ae5a4SJacob Faibussowitsch { 16883a40ed3dSBarry Smith PetscFunctionBegin; 16890700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 16904f572ea9SToby Isaac PetscAssertPointer(lits, 2); 1691c96a6f78SLois Curfman McInnes *lits = snes->linear_its; 16923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1693c96a6f78SLois Curfman McInnes } 1694c96a6f78SLois Curfman McInnes 1695971e163fSPeter Brune /*@ 1696971e163fSPeter Brune SNESSetCountersReset - Sets whether or not the counters for linear iterations and function evaluations 1697f6dfbefdSBarry Smith are reset every time `SNESSolve()` is called. 1698971e163fSPeter Brune 1699c3339decSBarry Smith Logically Collective 1700971e163fSPeter Brune 1701d8d19677SJose E. Roman Input Parameters: 1702f6dfbefdSBarry Smith + snes - `SNES` context 1703f6dfbefdSBarry Smith - reset - whether to reset the counters or not, defaults to `PETSC_TRUE` 1704971e163fSPeter Brune 1705971e163fSPeter Brune Level: developer 1706971e163fSPeter Brune 17071cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()` 1708971e163fSPeter Brune @*/ 1709d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCountersReset(SNES snes, PetscBool reset) 1710d71ae5a4SJacob Faibussowitsch { 1711971e163fSPeter Brune PetscFunctionBegin; 1712971e163fSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1713971e163fSPeter Brune PetscValidLogicalCollectiveBool(snes, reset, 2); 1714971e163fSPeter Brune snes->counters_reset = reset; 17153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1716971e163fSPeter Brune } 1717971e163fSPeter Brune 17182999313aSBarry Smith /*@ 171912b1dd1aSStefano Zampini SNESResetCounters - Reset counters for linear iterations and function evaluations. 172012b1dd1aSStefano Zampini 172112b1dd1aSStefano Zampini Logically Collective 172212b1dd1aSStefano Zampini 172312b1dd1aSStefano Zampini Input Parameters: 172412b1dd1aSStefano Zampini . snes - `SNES` context 172512b1dd1aSStefano Zampini 172612b1dd1aSStefano Zampini Level: developer 172712b1dd1aSStefano Zampini 172812b1dd1aSStefano Zampini Note: 172912b1dd1aSStefano Zampini It honors the flag set with `SNESSetCountersReset()` 173012b1dd1aSStefano Zampini 173112b1dd1aSStefano Zampini .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()` 173212b1dd1aSStefano Zampini @*/ 173312b1dd1aSStefano Zampini PetscErrorCode SNESResetCounters(SNES snes) 173412b1dd1aSStefano Zampini { 173512b1dd1aSStefano Zampini PetscFunctionBegin; 173612b1dd1aSStefano Zampini PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 173712b1dd1aSStefano Zampini if (snes->counters_reset) { 173812b1dd1aSStefano Zampini snes->nfuncs = 0; 173912b1dd1aSStefano Zampini snes->linear_its = 0; 174012b1dd1aSStefano Zampini snes->numFailures = 0; 174112b1dd1aSStefano Zampini } 174212b1dd1aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 174312b1dd1aSStefano Zampini } 174412b1dd1aSStefano Zampini 174512b1dd1aSStefano Zampini /*@ 1746f6dfbefdSBarry Smith SNESSetKSP - Sets a `KSP` context for the `SNES` object to use 17472999313aSBarry Smith 1748420bcc1bSBarry Smith Not Collective, but the `SNES` and `KSP` objects must live on the same `MPI_Comm` 17492999313aSBarry Smith 17502999313aSBarry Smith Input Parameters: 1751f6dfbefdSBarry Smith + snes - the `SNES` context 1752f6dfbefdSBarry Smith - ksp - the `KSP` context 17532999313aSBarry Smith 1754dc4c0fb0SBarry Smith Level: developer 1755dc4c0fb0SBarry Smith 17562999313aSBarry Smith Notes: 1757f6dfbefdSBarry Smith The `SNES` object already has its `KSP` object, you can obtain with `SNESGetKSP()` 17582999313aSBarry Smith so this routine is rarely needed. 17592999313aSBarry Smith 1760f6dfbefdSBarry Smith The `KSP` object that is already in the `SNES` object has its reference count 1761420bcc1bSBarry Smith decreased by one when this is called. 17622999313aSBarry Smith 176342747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `KSP`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()` 17642999313aSBarry Smith @*/ 1765d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetKSP(SNES snes, KSP ksp) 1766d71ae5a4SJacob Faibussowitsch { 17672999313aSBarry Smith PetscFunctionBegin; 17680700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 17690700a824SBarry Smith PetscValidHeaderSpecific(ksp, KSP_CLASSID, 2); 17702999313aSBarry Smith PetscCheckSameComm(snes, 1, ksp, 2); 17719566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)ksp)); 17729566063dSJacob Faibussowitsch if (snes->ksp) PetscCall(PetscObjectDereference((PetscObject)snes->ksp)); 17732999313aSBarry Smith snes->ksp = ksp; 17743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17752999313aSBarry Smith } 17762999313aSBarry Smith 177752baeb72SSatish Balay /*@ 177877e5a1f9SBarry Smith SNESParametersInitialize - Sets all the parameters in `snes` to their default value (when `SNESCreate()` was called) if they 177977e5a1f9SBarry Smith currently contain default values 178077e5a1f9SBarry Smith 178177e5a1f9SBarry Smith Collective 178277e5a1f9SBarry Smith 178377e5a1f9SBarry Smith Input Parameter: 178477e5a1f9SBarry Smith . snes - the `SNES` object 178577e5a1f9SBarry Smith 178677e5a1f9SBarry Smith Level: developer 178777e5a1f9SBarry Smith 178877e5a1f9SBarry Smith Developer Note: 178977e5a1f9SBarry Smith This is called by all the `SNESCreate_XXX()` routines. 179077e5a1f9SBarry Smith 179177e5a1f9SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`, 179277e5a1f9SBarry Smith `PetscObjectParameterSetDefault()` 179377e5a1f9SBarry Smith @*/ 179477e5a1f9SBarry Smith PetscErrorCode SNESParametersInitialize(SNES snes) 179577e5a1f9SBarry Smith { 179677e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, max_its, 50); 179777e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, max_funcs, 10000); 179877e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, rtol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8); 179977e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, abstol, PetscDefined(USE_REAL_SINGLE) ? 1.e-25 : 1.e-50); 180077e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, stol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8); 180177e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, divtol, 1.e4); 180277e5a1f9SBarry Smith return PETSC_SUCCESS; 180377e5a1f9SBarry Smith } 180477e5a1f9SBarry Smith 180577e5a1f9SBarry Smith /*@ 1806dc4c0fb0SBarry Smith SNESCreate - Creates a nonlinear solver context used to manage a set of nonlinear solves 18079b94acceSBarry Smith 1808d083f849SBarry Smith Collective 1809c7afd0dbSLois Curfman McInnes 1810f6dfbefdSBarry Smith Input Parameter: 1811906ed7ccSBarry Smith . comm - MPI communicator 18129b94acceSBarry Smith 18139b94acceSBarry Smith Output Parameter: 181420f4b53cSBarry Smith . outsnes - the new `SNES` context 18159b94acceSBarry Smith 1816c7afd0dbSLois Curfman McInnes Options Database Keys: 1817dc4c0fb0SBarry Smith + -snes_mf - Activates default matrix-free Jacobian-vector products, and no preconditioning matrix 1818dc4c0fb0SBarry Smith . -snes_mf_operator - Activates default matrix-free Jacobian-vector products, and a user-provided preconditioning matrix 1819dc4c0fb0SBarry Smith as set by `SNESSetJacobian()` 1820dc4c0fb0SBarry Smith . -snes_fd_coloring - uses a relative fast computation of the Jacobian using finite differences and a graph coloring 1821c7afd0dbSLois Curfman McInnes - -snes_fd - Uses (slow!) finite differences to compute Jacobian 1822c1f60f51SBarry Smith 182336851e7fSLois Curfman McInnes Level: beginner 182436851e7fSLois Curfman McInnes 182595452b02SPatrick Sanan Developer Notes: 1826f6dfbefdSBarry Smith `SNES` always creates a `KSP` object even though many `SNES` methods do not use it. This is 1827efd4aadfSBarry Smith unfortunate and should be fixed at some point. The flag snes->usesksp indicates if the 1828f6dfbefdSBarry Smith particular method does use `KSP` and regulates if the information about the `KSP` is printed 1829f6dfbefdSBarry Smith in `SNESView()`. 1830efd4aadfSBarry Smith 1831f6dfbefdSBarry Smith `TSSetFromOptions()` does call `SNESSetFromOptions()` which can lead to users being confused 1832f6dfbefdSBarry Smith by help messages about meaningless `SNES` options. 1833f6dfbefdSBarry Smith 1834dc4c0fb0SBarry Smith `SNES` always creates the snes->kspconvctx even though it is used by only one type. This should be fixed. 1835efd4aadfSBarry Smith 1836e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()` 18379b94acceSBarry Smith @*/ 1838d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESCreate(MPI_Comm comm, SNES *outsnes) 1839d71ae5a4SJacob Faibussowitsch { 18409b94acceSBarry Smith SNES snes; 1841fa9f3622SBarry Smith SNESKSPEW *kctx; 184237fcc0dbSBarry Smith 18433a40ed3dSBarry Smith PetscFunctionBegin; 18444f572ea9SToby Isaac PetscAssertPointer(outsnes, 2); 18459566063dSJacob Faibussowitsch PetscCall(SNESInitializePackage()); 18468ba1e511SMatthew Knepley 18479566063dSJacob Faibussowitsch PetscCall(PetscHeaderCreate(snes, SNES_CLASSID, "SNES", "Nonlinear solver", "SNES", comm, SNESDestroy, SNESView)); 18488d359177SBarry Smith snes->ops->converged = SNESConvergedDefault; 18492c155ee1SBarry Smith snes->usesksp = PETSC_TRUE; 18509b94acceSBarry Smith snes->norm = 0.0; 1851c1e67a49SFande Kong snes->xnorm = 0.0; 1852c1e67a49SFande Kong snes->ynorm = 0.0; 1853365a6726SPeter Brune snes->normschedule = SNES_NORM_ALWAYS; 18546c67d002SPeter Brune snes->functype = SNES_FUNCTION_DEFAULT; 1855b4874afaSBarry Smith snes->ttol = 0.0; 185677e5a1f9SBarry Smith 1857e37c518bSBarry Smith snes->rnorm0 = 0; 18589b94acceSBarry Smith snes->nfuncs = 0; 185950ffb88aSMatthew Knepley snes->numFailures = 0; 186050ffb88aSMatthew Knepley snes->maxFailures = 1; 18617a00f4a9SLois Curfman McInnes snes->linear_its = 0; 1862e35cf81dSBarry Smith snes->lagjacobian = 1; 186337ec4e1aSPeter Brune snes->jac_iter = 0; 186437ec4e1aSPeter Brune snes->lagjac_persist = PETSC_FALSE; 1865a8054027SBarry Smith snes->lagpreconditioner = 1; 186637ec4e1aSPeter Brune snes->pre_iter = 0; 186737ec4e1aSPeter Brune snes->lagpre_persist = PETSC_FALSE; 1868639f9d9dSBarry Smith snes->numbermonitors = 0; 1869c4421ceaSFande Kong snes->numberreasonviews = 0; 18709e5d0892SLisandro Dalcin snes->data = NULL; 18714dc4c822SBarry Smith snes->setupcalled = PETSC_FALSE; 1872186905e3SBarry Smith snes->ksp_ewconv = PETSC_FALSE; 18736f24a144SLois Curfman McInnes snes->nwork = 0; 18749e5d0892SLisandro Dalcin snes->work = NULL; 187558c9b817SLisandro Dalcin snes->nvwork = 0; 18769e5d0892SLisandro Dalcin snes->vwork = NULL; 1877758f92a0SBarry Smith snes->conv_hist_len = 0; 1878758f92a0SBarry Smith snes->conv_hist_max = 0; 18790298fd71SBarry Smith snes->conv_hist = NULL; 18800298fd71SBarry Smith snes->conv_hist_its = NULL; 1881758f92a0SBarry Smith snes->conv_hist_reset = PETSC_TRUE; 1882971e163fSPeter Brune snes->counters_reset = PETSC_TRUE; 1883e4ed7901SPeter Brune snes->vec_func_init_set = PETSC_FALSE; 1884184914b5SBarry Smith snes->reason = SNES_CONVERGED_ITERATING; 1885efd4aadfSBarry Smith snes->npcside = PC_RIGHT; 1886b3cd9a81SMatthew G. Knepley snes->setfromoptionscalled = 0; 1887c40d0f55SPeter Brune 1888d8f46077SPeter Brune snes->mf = PETSC_FALSE; 1889d8f46077SPeter Brune snes->mf_operator = PETSC_FALSE; 1890d8f46077SPeter Brune snes->mf_version = 1; 1891d8f46077SPeter Brune 18923d4c4710SBarry Smith snes->numLinearSolveFailures = 0; 18933d4c4710SBarry Smith snes->maxLinearSolveFailures = 1; 18943d4c4710SBarry Smith 1895349187a7SBarry Smith snes->vizerotolerance = 1.e-8; 189676bd3646SJed Brown snes->checkjacdomainerror = PetscDefined(USE_DEBUG) ? PETSC_TRUE : PETSC_FALSE; 1897349187a7SBarry Smith 18984fc747eaSLawrence Mitchell /* Set this to true if the implementation of SNESSolve_XXX does compute the residual at the final solution. */ 18994fc747eaSLawrence Mitchell snes->alwayscomputesfinalresidual = PETSC_FALSE; 19004fc747eaSLawrence Mitchell 19019b94acceSBarry Smith /* Create context to compute Eisenstat-Walker relative tolerance for KSP */ 19024dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&kctx)); 1903f5af7f23SKarl Rupp 1904*835f2295SStefano Zampini snes->kspconvctx = kctx; 19059b94acceSBarry Smith kctx->version = 2; 19060f0abf79SStefano Zampini kctx->rtol_0 = 0.3; /* Eisenstat and Walker suggest rtol_0=.5, but 19079b94acceSBarry Smith this was too large for some test cases */ 190875567043SBarry Smith kctx->rtol_last = 0.0; 19090f0abf79SStefano Zampini kctx->rtol_max = 0.9; 19109b94acceSBarry Smith kctx->gamma = 1.0; 19110f0abf79SStefano Zampini kctx->alpha = 0.5 * (1.0 + PetscSqrtReal(5.0)); 191271f87433Sdalcinl kctx->alpha2 = kctx->alpha; 19130f0abf79SStefano Zampini kctx->threshold = 0.1; 191475567043SBarry Smith kctx->lresid_last = 0.0; 191575567043SBarry Smith kctx->norm_last = 0.0; 19169b94acceSBarry Smith 19170f0abf79SStefano Zampini kctx->rk_last = 0.0; 19180f0abf79SStefano Zampini kctx->rk_last_2 = 0.0; 19190f0abf79SStefano Zampini kctx->rtol_last_2 = 0.0; 19200f0abf79SStefano Zampini kctx->v4_p1 = 0.1; 19210f0abf79SStefano Zampini kctx->v4_p2 = 0.4; 19220f0abf79SStefano Zampini kctx->v4_p3 = 0.7; 19230f0abf79SStefano Zampini kctx->v4_m1 = 0.8; 19240f0abf79SStefano Zampini kctx->v4_m2 = 0.5; 19250f0abf79SStefano Zampini kctx->v4_m3 = 0.1; 19260f0abf79SStefano Zampini kctx->v4_m4 = 0.5; 19270f0abf79SStefano Zampini 1928b50c806fSBarry Smith PetscCall(SNESParametersInitialize(snes)); 19299b94acceSBarry Smith *outsnes = snes; 19303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19319b94acceSBarry Smith } 19329b94acceSBarry Smith 19339b94acceSBarry Smith /*@C 19349b94acceSBarry Smith SNESSetFunction - Sets the function evaluation routine and function 1935f6dfbefdSBarry Smith vector for use by the `SNES` routines in solving systems of nonlinear 19369b94acceSBarry Smith equations. 19379b94acceSBarry Smith 1938c3339decSBarry Smith Logically Collective 1939fee21e36SBarry Smith 1940c7afd0dbSLois Curfman McInnes Input Parameters: 1941f6dfbefdSBarry Smith + snes - the `SNES` context 1942dc4c0fb0SBarry Smith . r - vector to store function values, may be `NULL` 19438434afd1SBarry Smith . f - function evaluation routine; for calling sequence see `SNESFunctionFn` 1944c7afd0dbSLois Curfman McInnes - ctx - [optional] user-defined context for private data for the 1945dc4c0fb0SBarry Smith function evaluation routine (may be `NULL`) 19469b94acceSBarry Smith 194736851e7fSLois Curfman McInnes Level: beginner 194836851e7fSLois Curfman McInnes 19498434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetPicard()`, `SNESFunctionFn` 19509b94acceSBarry Smith @*/ 19518434afd1SBarry Smith PetscErrorCode SNESSetFunction(SNES snes, Vec r, SNESFunctionFn *f, void *ctx) 1952d71ae5a4SJacob Faibussowitsch { 19536cab3a1bSJed Brown DM dm; 19546cab3a1bSJed Brown 19553a40ed3dSBarry Smith PetscFunctionBegin; 19560700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1957d2a683ecSLisandro Dalcin if (r) { 1958d2a683ecSLisandro Dalcin PetscValidHeaderSpecific(r, VEC_CLASSID, 2); 1959d2a683ecSLisandro Dalcin PetscCheckSameComm(snes, 1, r, 2); 19609566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)r)); 19619566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_func)); 196285385478SLisandro Dalcin snes->vec_func = r; 1963d2a683ecSLisandro Dalcin } 19649566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 19659566063dSJacob Faibussowitsch PetscCall(DMSNESSetFunction(dm, f, ctx)); 196648a46eb9SPierre Jolivet if (f == SNESPicardComputeFunction) PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx)); 19673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19689b94acceSBarry Smith } 19699b94acceSBarry Smith 1970e4ed7901SPeter Brune /*@C 19710b4db180SJacob Faibussowitsch SNESSetInitialFunction - Set an already computed function evaluation at the initial guess to be reused by `SNESSolve()`. 1972e4ed7901SPeter Brune 1973c3339decSBarry Smith Logically Collective 1974e4ed7901SPeter Brune 1975e4ed7901SPeter Brune Input Parameters: 1976f6dfbefdSBarry Smith + snes - the `SNES` context 1977e4ed7901SPeter Brune - f - vector to store function value 1978e4ed7901SPeter Brune 1979dc4c0fb0SBarry Smith Level: developer 1980dc4c0fb0SBarry Smith 1981e4ed7901SPeter Brune Notes: 1982e4ed7901SPeter Brune This should not be modified during the solution procedure. 1983e4ed7901SPeter Brune 1984f6dfbefdSBarry Smith This is used extensively in the `SNESFAS` hierarchy and in nonlinear preconditioning. 1985e4ed7901SPeter Brune 19861cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetInitialFunctionNorm()` 1987e4ed7901SPeter Brune @*/ 1988d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetInitialFunction(SNES snes, Vec f) 1989d71ae5a4SJacob Faibussowitsch { 1990e4ed7901SPeter Brune Vec vec_func; 1991e4ed7901SPeter Brune 1992e4ed7901SPeter Brune PetscFunctionBegin; 1993e4ed7901SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1994e4ed7901SPeter Brune PetscValidHeaderSpecific(f, VEC_CLASSID, 2); 1995e4ed7901SPeter Brune PetscCheckSameComm(snes, 1, f, 2); 1996efd4aadfSBarry Smith if (snes->npcside == PC_LEFT && snes->functype == SNES_FUNCTION_PRECONDITIONED) { 1997902f982fSPeter Brune snes->vec_func_init_set = PETSC_FALSE; 19983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1999902f982fSPeter Brune } 20009566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &vec_func, NULL, NULL)); 20019566063dSJacob Faibussowitsch PetscCall(VecCopy(f, vec_func)); 2002f5af7f23SKarl Rupp 2003217b9c2eSPeter Brune snes->vec_func_init_set = PETSC_TRUE; 20043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2005e4ed7901SPeter Brune } 2006e4ed7901SPeter Brune 2007534ebe21SPeter Brune /*@ 2008f6dfbefdSBarry Smith SNESSetNormSchedule - Sets the `SNESNormSchedule` used in convergence and monitoring 2009f6dfbefdSBarry Smith of the `SNES` method, when norms are computed in the solving process 2010534ebe21SPeter Brune 2011c3339decSBarry Smith Logically Collective 2012534ebe21SPeter Brune 2013534ebe21SPeter Brune Input Parameters: 2014f6dfbefdSBarry Smith + snes - the `SNES` context 2015365a6726SPeter Brune - normschedule - the frequency of norm computation 2016534ebe21SPeter Brune 2017517f1916SMatthew G. Knepley Options Database Key: 201867b8a455SSatish Balay . -snes_norm_schedule <none, always, initialonly, finalonly, initialfinalonly> - set the schedule 2019517f1916SMatthew G. Knepley 2020dc4c0fb0SBarry Smith Level: advanced 2021dc4c0fb0SBarry Smith 2022534ebe21SPeter Brune Notes: 2023f6dfbefdSBarry Smith Only certain `SNES` methods support certain `SNESNormSchedules`. Most require evaluation 2024534ebe21SPeter Brune of the nonlinear function and the taking of its norm at every iteration to 2025534ebe21SPeter Brune even ensure convergence at all. However, methods such as custom Gauss-Seidel methods 2026f6dfbefdSBarry Smith `SNESNGS` and the like do not require the norm of the function to be computed, and therefore 2027534ebe21SPeter Brune may either be monitored for convergence or not. As these are often used as nonlinear 2028534ebe21SPeter Brune preconditioners, monitoring the norm of their error is not a useful enterprise within 2029534ebe21SPeter Brune their solution. 2030534ebe21SPeter Brune 2031e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNESNormSchedule`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()` 2032534ebe21SPeter Brune @*/ 2033d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNormSchedule(SNES snes, SNESNormSchedule normschedule) 2034d71ae5a4SJacob Faibussowitsch { 2035534ebe21SPeter Brune PetscFunctionBegin; 2036534ebe21SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2037365a6726SPeter Brune snes->normschedule = normschedule; 20383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2039534ebe21SPeter Brune } 2040534ebe21SPeter Brune 2041534ebe21SPeter Brune /*@ 2042f6dfbefdSBarry Smith SNESGetNormSchedule - Gets the `SNESNormSchedule` used in convergence and monitoring 2043f6dfbefdSBarry Smith of the `SNES` method. 2044534ebe21SPeter Brune 2045c3339decSBarry Smith Logically Collective 2046534ebe21SPeter Brune 2047534ebe21SPeter Brune Input Parameters: 2048f6dfbefdSBarry Smith + snes - the `SNES` context 2049365a6726SPeter Brune - normschedule - the type of the norm used 2050534ebe21SPeter Brune 2051534ebe21SPeter Brune Level: advanced 2052534ebe21SPeter Brune 20531cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 2054534ebe21SPeter Brune @*/ 2055d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNormSchedule(SNES snes, SNESNormSchedule *normschedule) 2056d71ae5a4SJacob Faibussowitsch { 2057534ebe21SPeter Brune PetscFunctionBegin; 2058534ebe21SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2059365a6726SPeter Brune *normschedule = snes->normschedule; 20603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2061534ebe21SPeter Brune } 2062534ebe21SPeter Brune 2063c5ce4427SMatthew G. Knepley /*@ 2064c5ce4427SMatthew G. Knepley SNESSetFunctionNorm - Sets the last computed residual norm. 2065c5ce4427SMatthew G. Knepley 2066c3339decSBarry Smith Logically Collective 2067c5ce4427SMatthew G. Knepley 2068c5ce4427SMatthew G. Knepley Input Parameters: 2069f6dfbefdSBarry Smith + snes - the `SNES` context 2070f6dfbefdSBarry Smith - norm - the value of the norm 2071c5ce4427SMatthew G. Knepley 2072c5ce4427SMatthew G. Knepley Level: developer 2073c5ce4427SMatthew G. Knepley 20741cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 2075c5ce4427SMatthew G. Knepley @*/ 2076d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionNorm(SNES snes, PetscReal norm) 2077d71ae5a4SJacob Faibussowitsch { 2078c5ce4427SMatthew G. Knepley PetscFunctionBegin; 2079c5ce4427SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2080c5ce4427SMatthew G. Knepley snes->norm = norm; 20813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2082c5ce4427SMatthew G. Knepley } 2083c5ce4427SMatthew G. Knepley 2084c5ce4427SMatthew G. Knepley /*@ 2085c5ce4427SMatthew G. Knepley SNESGetFunctionNorm - Gets the last computed norm of the residual 2086c5ce4427SMatthew G. Knepley 2087c5ce4427SMatthew G. Knepley Not Collective 2088c5ce4427SMatthew G. Knepley 2089c5ce4427SMatthew G. Knepley Input Parameter: 2090f6dfbefdSBarry Smith . snes - the `SNES` context 2091c5ce4427SMatthew G. Knepley 2092c5ce4427SMatthew G. Knepley Output Parameter: 2093c5ce4427SMatthew G. Knepley . norm - the last computed residual norm 2094c5ce4427SMatthew G. Knepley 2095c5ce4427SMatthew G. Knepley Level: developer 2096c5ce4427SMatthew G. Knepley 20971cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 2098c5ce4427SMatthew G. Knepley @*/ 2099d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionNorm(SNES snes, PetscReal *norm) 2100d71ae5a4SJacob Faibussowitsch { 2101c5ce4427SMatthew G. Knepley PetscFunctionBegin; 2102c5ce4427SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 21034f572ea9SToby Isaac PetscAssertPointer(norm, 2); 2104c5ce4427SMatthew G. Knepley *norm = snes->norm; 21053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2106c5ce4427SMatthew G. Knepley } 2107c5ce4427SMatthew G. Knepley 2108c1e67a49SFande Kong /*@ 2109f6dfbefdSBarry Smith SNESGetUpdateNorm - Gets the last computed norm of the solution update 2110c1e67a49SFande Kong 2111c1e67a49SFande Kong Not Collective 2112c1e67a49SFande Kong 2113c1e67a49SFande Kong Input Parameter: 2114f6dfbefdSBarry Smith . snes - the `SNES` context 2115c1e67a49SFande Kong 2116c1e67a49SFande Kong Output Parameter: 2117c1e67a49SFande Kong . ynorm - the last computed update norm 2118c1e67a49SFande Kong 2119c1e67a49SFande Kong Level: developer 2120c1e67a49SFande Kong 2121f6dfbefdSBarry Smith Note: 2122f6dfbefdSBarry Smith The new solution is the current solution plus the update, so this norm is an indication of the size of the update 2123f6dfbefdSBarry Smith 21241cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()` 2125c1e67a49SFande Kong @*/ 2126d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUpdateNorm(SNES snes, PetscReal *ynorm) 2127d71ae5a4SJacob Faibussowitsch { 2128c1e67a49SFande Kong PetscFunctionBegin; 2129c1e67a49SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 21304f572ea9SToby Isaac PetscAssertPointer(ynorm, 2); 2131c1e67a49SFande Kong *ynorm = snes->ynorm; 21323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2133c1e67a49SFande Kong } 2134c1e67a49SFande Kong 2135c1e67a49SFande Kong /*@ 21364591eaf2SFande Kong SNESGetSolutionNorm - Gets the last computed norm of the solution 2137c1e67a49SFande Kong 2138c1e67a49SFande Kong Not Collective 2139c1e67a49SFande Kong 2140c1e67a49SFande Kong Input Parameter: 2141f6dfbefdSBarry Smith . snes - the `SNES` context 2142c1e67a49SFande Kong 2143c1e67a49SFande Kong Output Parameter: 2144c1e67a49SFande Kong . xnorm - the last computed solution norm 2145c1e67a49SFande Kong 2146c1e67a49SFande Kong Level: developer 2147c1e67a49SFande Kong 21481cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`, `SNESGetUpdateNorm()` 2149c1e67a49SFande Kong @*/ 2150d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionNorm(SNES snes, PetscReal *xnorm) 2151d71ae5a4SJacob Faibussowitsch { 2152c1e67a49SFande Kong PetscFunctionBegin; 2153c1e67a49SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 21544f572ea9SToby Isaac PetscAssertPointer(xnorm, 2); 2155c1e67a49SFande Kong *xnorm = snes->xnorm; 21563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2157c1e67a49SFande Kong } 2158c1e67a49SFande Kong 2159cc4c1da9SBarry Smith /*@ 2160f6dfbefdSBarry Smith SNESSetFunctionType - Sets the `SNESFunctionType` 2161f6dfbefdSBarry Smith of the `SNES` method. 216247073ea2SPeter Brune 2163c3339decSBarry Smith Logically Collective 216447073ea2SPeter Brune 216547073ea2SPeter Brune Input Parameters: 2166f6dfbefdSBarry Smith + snes - the `SNES` context 2167f6dfbefdSBarry Smith - type - the function type 216847073ea2SPeter Brune 216947073ea2SPeter Brune Level: developer 217047073ea2SPeter Brune 2171420bcc1bSBarry Smith Values of the function type\: 2172f6dfbefdSBarry Smith + `SNES_FUNCTION_DEFAULT` - the default for the given `SNESType` 2173f6dfbefdSBarry Smith . `SNES_FUNCTION_UNPRECONDITIONED` - an unpreconditioned function evaluation (this is the function provided with `SNESSetFunction()` 2174f6dfbefdSBarry Smith - `SNES_FUNCTION_PRECONDITIONED` - a transformation of the function provided with `SNESSetFunction()` 2175f6dfbefdSBarry Smith 2176420bcc1bSBarry Smith Note: 2177f6dfbefdSBarry Smith Different `SNESType`s use this value in different ways 2178f6dfbefdSBarry Smith 21791cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFunctionType`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 218047073ea2SPeter Brune @*/ 2181d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionType(SNES snes, SNESFunctionType type) 2182d71ae5a4SJacob Faibussowitsch { 218347073ea2SPeter Brune PetscFunctionBegin; 218447073ea2SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 218547073ea2SPeter Brune snes->functype = type; 21863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 218747073ea2SPeter Brune } 218847073ea2SPeter Brune 2189cc4c1da9SBarry Smith /*@ 2190f6dfbefdSBarry Smith SNESGetFunctionType - Gets the `SNESFunctionType` used in convergence and monitoring set with `SNESSetFunctionType()` 219147073ea2SPeter Brune of the SNES method. 219247073ea2SPeter Brune 2193c3339decSBarry Smith Logically Collective 219447073ea2SPeter Brune 219547073ea2SPeter Brune Input Parameters: 2196f6dfbefdSBarry Smith + snes - the `SNES` context 2197f6dfbefdSBarry Smith - type - the type of the function evaluation, see `SNESSetFunctionType()` 219847073ea2SPeter Brune 219947073ea2SPeter Brune Level: advanced 220047073ea2SPeter Brune 22011cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetFunctionType()`, `SNESFunctionType`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 220247073ea2SPeter Brune @*/ 2203d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionType(SNES snes, SNESFunctionType *type) 2204d71ae5a4SJacob Faibussowitsch { 220547073ea2SPeter Brune PetscFunctionBegin; 220647073ea2SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 220747073ea2SPeter Brune *type = snes->functype; 22083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2209534ebe21SPeter Brune } 2210534ebe21SPeter Brune 2211c79ef259SPeter Brune /*@C 2212be95d8f1SBarry Smith SNESSetNGS - Sets the user nonlinear Gauss-Seidel routine for 2213c79ef259SPeter Brune use with composed nonlinear solvers. 2214c79ef259SPeter Brune 2215c79ef259SPeter Brune Input Parameters: 22169bcc50f1SBarry Smith + snes - the `SNES` context, usually of the `SNESType` `SNESNGS` 22178434afd1SBarry Smith . f - function evaluation routine to apply Gauss-Seidel, see `SNESNGSFn` for calling sequence 221877e5a1f9SBarry Smith - ctx - [optional] user-defined context for private data for the smoother evaluation routine (may be `NULL`) 2219c79ef259SPeter Brune 2220dc4c0fb0SBarry Smith Level: intermediate 2221dc4c0fb0SBarry Smith 2222f6dfbefdSBarry Smith Note: 2223f6dfbefdSBarry Smith The `SNESNGS` routines are used by the composed nonlinear solver to generate 2224f6dfbefdSBarry Smith a problem appropriate update to the solution, particularly `SNESFAS`. 2225c79ef259SPeter Brune 22268434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGS`, `SNESGetNGS()`, `SNESNCG`, `SNESGetFunction()`, `SNESComputeNGS()`, `SNESNGSFn` 2227c79ef259SPeter Brune @*/ 22288434afd1SBarry Smith PetscErrorCode SNESSetNGS(SNES snes, SNESNGSFn *f, void *ctx) 2229d71ae5a4SJacob Faibussowitsch { 22306cab3a1bSJed Brown DM dm; 22316cab3a1bSJed Brown 2232646217ecSPeter Brune PetscFunctionBegin; 22336cab3a1bSJed Brown PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 22349566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 22359566063dSJacob Faibussowitsch PetscCall(DMSNESSetNGS(dm, f, ctx)); 22363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2237646217ecSPeter Brune } 2238646217ecSPeter Brune 2239bbc1464cSBarry Smith /* 2240bbc1464cSBarry Smith This is used for -snes_mf_operator; it uses a duplicate of snes->jacobian_pre because snes->jacobian_pre cannot be 2241bbc1464cSBarry Smith changed during the KSPSolve() 2242bbc1464cSBarry Smith */ 2243d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeMFFunction(SNES snes, Vec x, Vec f, void *ctx) 2244d71ae5a4SJacob Faibussowitsch { 2245bbc1464cSBarry Smith DM dm; 2246bbc1464cSBarry Smith DMSNES sdm; 2247bbc1464cSBarry Smith 2248bbc1464cSBarry Smith PetscFunctionBegin; 22499566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 22509566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 2251bbc1464cSBarry Smith /* A(x)*x - b(x) */ 2252bbc1464cSBarry Smith if (sdm->ops->computepfunction) { 2253792fecdfSBarry Smith PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx)); 22549566063dSJacob Faibussowitsch PetscCall(VecScale(f, -1.0)); 22550df40c35SBarry Smith /* Cannot share nonzero pattern because of the possible use of SNESComputeJacobianDefault() */ 2256ef1023bdSBarry Smith if (!snes->picard) PetscCall(MatDuplicate(snes->jacobian_pre, MAT_DO_NOT_COPY_VALUES, &snes->picard)); 2257792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx)); 22589566063dSJacob Faibussowitsch PetscCall(MatMultAdd(snes->picard, x, f, f)); 2259bbc1464cSBarry Smith } else { 2260792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx)); 22619566063dSJacob Faibussowitsch PetscCall(MatMult(snes->picard, x, f)); 2262bbc1464cSBarry Smith } 22633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2264bbc1464cSBarry Smith } 2265bbc1464cSBarry Smith 2266d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeFunction(SNES snes, Vec x, Vec f, void *ctx) 2267d71ae5a4SJacob Faibussowitsch { 2268e03ab78fSPeter Brune DM dm; 2269942e3340SBarry Smith DMSNES sdm; 22706cab3a1bSJed Brown 22718b0a5094SBarry Smith PetscFunctionBegin; 22729566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 22739566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 22748b0a5094SBarry Smith /* A(x)*x - b(x) */ 2275bbc1464cSBarry Smith if (sdm->ops->computepfunction) { 2276792fecdfSBarry Smith PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx)); 22779566063dSJacob Faibussowitsch PetscCall(VecScale(f, -1.0)); 2278792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx)); 22799566063dSJacob Faibussowitsch PetscCall(MatMultAdd(snes->jacobian_pre, x, f, f)); 2280bbc1464cSBarry Smith } else { 2281792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx)); 22829566063dSJacob Faibussowitsch PetscCall(MatMult(snes->jacobian_pre, x, f)); 2283bbc1464cSBarry Smith } 22843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22858b0a5094SBarry Smith } 22868b0a5094SBarry Smith 2287d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeJacobian(SNES snes, Vec x1, Mat J, Mat B, void *ctx) 2288d71ae5a4SJacob Faibussowitsch { 22898b0a5094SBarry Smith PetscFunctionBegin; 2290e03ab78fSPeter Brune /* the jacobian matrix should be pre-filled in SNESPicardComputeFunction */ 2291bbc1464cSBarry Smith /* must assembly if matrix-free to get the last SNES solution */ 22929566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 22939566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 22943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22958b0a5094SBarry Smith } 22968b0a5094SBarry Smith 22978b0a5094SBarry Smith /*@C 22981d27aa22SBarry Smith SNESSetPicard - Use `SNES` to solve the system $A(x) x = bp(x) + b $ via a Picard type iteration (Picard linearization) 22998b0a5094SBarry Smith 2300c3339decSBarry Smith Logically Collective 23018b0a5094SBarry Smith 23028b0a5094SBarry Smith Input Parameters: 2303f6dfbefdSBarry Smith + snes - the `SNES` context 2304dc4c0fb0SBarry Smith . r - vector to store function values, may be `NULL` 23058434afd1SBarry Smith . bp - function evaluation routine, may be `NULL`, for the calling sequence see `SNESFunctionFn` 23066b7fb656SBarry Smith . Amat - matrix with which A(x) x - bp(x) - b is to be computed 2307dc4c0fb0SBarry Smith . Pmat - matrix from which preconditioner is computed (usually the same as `Amat`) 23088434afd1SBarry Smith . J - function to compute matrix values, for the calling sequence see `SNESJacobianFn` 2309dc4c0fb0SBarry Smith - ctx - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`) 2310dc4c0fb0SBarry Smith 2311dc4c0fb0SBarry Smith Level: intermediate 23128b0a5094SBarry Smith 23138b0a5094SBarry Smith Notes: 23146b7fb656SBarry Smith It is often better to provide the nonlinear function F() and some approximation to its Jacobian directly and use 2315f450aa47SBarry 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. 2316f450aa47SBarry Smith 2317f6dfbefdSBarry Smith One can call `SNESSetPicard()` or `SNESSetFunction()` (and possibly `SNESSetJacobian()`) but cannot call both 23188b0a5094SBarry Smith 23191d27aa22SBarry 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}$. 23201d27aa22SBarry Smith When an exact solver is used this corresponds to the "classic" Picard $A(x^{n}) x^{n+1} = bp(x^{n}) + b$ iteration. 23218b0a5094SBarry Smith 2322dc4c0fb0SBarry Smith Run with `-snes_mf_operator` to solve the system with Newton's method using A(x^{n}) to construct the preconditioner. 23238b0a5094SBarry Smith 23240d04baf8SBarry Smith We implement the defect correction form of the Picard iteration because it converges much more generally when inexact linear solvers are used then 23251d27aa22SBarry Smith the direct Picard iteration $A(x^n) x^{n+1} = bp(x^n) + b$ 23268b0a5094SBarry Smith 23278b0a5094SBarry 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 23281d27aa22SBarry 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 23291d27aa22SBarry Smith different please contact us at petsc-dev@mcs.anl.gov and we'll have an entirely new argument \:-). 23308b0a5094SBarry Smith 23311d27aa22SBarry 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 2332f6dfbefdSBarry Smith A(x^{n}) is used to build the preconditioner 23336b7fb656SBarry Smith 233415229ffcSPierre 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. 23356b7fb656SBarry Smith 2336dc4c0fb0SBarry 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 23376b7fb656SBarry 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 2338f6dfbefdSBarry 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`. 2339aaa8cc7dSPierre Jolivet See the comment in src/snes/tutorials/ex15.c. 2340bbc1464cSBarry Smith 23419bcc50f1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESGetPicard()`, `SNESLineSearchPreCheckPicard()`, 23428434afd1SBarry Smith `SNESFunctionFn`, `SNESJacobianFn` 23438b0a5094SBarry Smith @*/ 23448434afd1SBarry Smith PetscErrorCode SNESSetPicard(SNES snes, Vec r, SNESFunctionFn *bp, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx) 2345d71ae5a4SJacob Faibussowitsch { 2346e03ab78fSPeter Brune DM dm; 2347e03ab78fSPeter Brune 23488b0a5094SBarry Smith PetscFunctionBegin; 23498b0a5094SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 23509566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 23519566063dSJacob Faibussowitsch PetscCall(DMSNESSetPicard(dm, bp, J, ctx)); 23529566063dSJacob Faibussowitsch PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx)); 23539566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes, r, SNESPicardComputeFunction, ctx)); 23549566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESPicardComputeJacobian, ctx)); 23553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23568b0a5094SBarry Smith } 23578b0a5094SBarry Smith 23587971a8bfSPeter Brune /*@C 23597971a8bfSPeter Brune SNESGetPicard - Returns the context for the Picard iteration 23607971a8bfSPeter Brune 2361f6dfbefdSBarry Smith Not Collective, but `Vec` is parallel if `SNES` is parallel. Collective if `Vec` is requested, but has not been created yet. 23627971a8bfSPeter Brune 23637971a8bfSPeter Brune Input Parameter: 2364f6dfbefdSBarry Smith . snes - the `SNES` context 23657971a8bfSPeter Brune 2366d8d19677SJose E. Roman Output Parameters: 2367dc4c0fb0SBarry Smith + r - the function (or `NULL`) 23688434afd1SBarry Smith . f - the function (or `NULL`); for calling sequence see `SNESFunctionFn` 2369dc4c0fb0SBarry Smith . Amat - the matrix used to defined the operation A(x) x - b(x) (or `NULL`) 2370dc4c0fb0SBarry Smith . Pmat - the matrix from which the preconditioner will be constructed (or `NULL`) 23718434afd1SBarry Smith . J - the function for matrix evaluation (or `NULL`); for calling sequence see `SNESJacobianFn` 2372dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`) 23737971a8bfSPeter Brune 23747971a8bfSPeter Brune Level: advanced 23757971a8bfSPeter Brune 23768434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetFunction()`, `SNESSetPicard()`, `SNESGetFunction()`, `SNESGetJacobian()`, `SNESGetDM()`, `SNESFunctionFn`, `SNESJacobianFn` 23777971a8bfSPeter Brune @*/ 23788434afd1SBarry Smith PetscErrorCode SNESGetPicard(SNES snes, Vec *r, SNESFunctionFn **f, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx) 2379d71ae5a4SJacob Faibussowitsch { 23807971a8bfSPeter Brune DM dm; 23817971a8bfSPeter Brune 23827971a8bfSPeter Brune PetscFunctionBegin; 23837971a8bfSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 23849566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, r, NULL, NULL)); 23859566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL)); 23869566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 23879566063dSJacob Faibussowitsch PetscCall(DMSNESGetPicard(dm, f, J, ctx)); 23883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23897971a8bfSPeter Brune } 23907971a8bfSPeter Brune 2391d25893d9SBarry Smith /*@C 2392dc4c0fb0SBarry Smith SNESSetComputeInitialGuess - Sets a routine used to compute an initial guess for the nonlinear problem 2393d25893d9SBarry Smith 2394c3339decSBarry Smith Logically Collective 2395d25893d9SBarry Smith 2396d25893d9SBarry Smith Input Parameters: 2397f6dfbefdSBarry Smith + snes - the `SNES` context 23988434afd1SBarry Smith . func - function evaluation routine, see `SNESInitialGuessFn` for the calling sequence 2399d25893d9SBarry Smith - ctx - [optional] user-defined context for private data for the 2400dc4c0fb0SBarry Smith function evaluation routine (may be `NULL`) 2401d25893d9SBarry Smith 2402d25893d9SBarry Smith Level: intermediate 2403d25893d9SBarry Smith 24048434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESInitialGuessFn` 2405d25893d9SBarry Smith @*/ 24068434afd1SBarry Smith PetscErrorCode SNESSetComputeInitialGuess(SNES snes, SNESInitialGuessFn *func, void *ctx) 2407d71ae5a4SJacob Faibussowitsch { 2408d25893d9SBarry Smith PetscFunctionBegin; 2409d25893d9SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2410d25893d9SBarry Smith if (func) snes->ops->computeinitialguess = func; 2411d25893d9SBarry Smith if (ctx) snes->initialguessP = ctx; 24123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2413d25893d9SBarry Smith } 2414d25893d9SBarry Smith 24151096aae1SMatthew Knepley /*@C 2416dc4c0fb0SBarry Smith SNESGetRhs - Gets the vector for solving F(x) = `rhs`. If `rhs` is not set 2417dd8e379bSPierre Jolivet it assumes a zero right-hand side. 24181096aae1SMatthew Knepley 2419c3339decSBarry Smith Logically Collective 24201096aae1SMatthew Knepley 24211096aae1SMatthew Knepley Input Parameter: 2422f6dfbefdSBarry Smith . snes - the `SNES` context 24231096aae1SMatthew Knepley 24241096aae1SMatthew Knepley Output Parameter: 2425dd8e379bSPierre Jolivet . rhs - the right-hand side vector or `NULL` if there is no right-hand side vector 24261096aae1SMatthew Knepley 24271096aae1SMatthew Knepley Level: intermediate 24281096aae1SMatthew Knepley 24291cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetFunction()` 24301096aae1SMatthew Knepley @*/ 2431d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetRhs(SNES snes, Vec *rhs) 2432d71ae5a4SJacob Faibussowitsch { 24331096aae1SMatthew Knepley PetscFunctionBegin; 24340700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 24354f572ea9SToby Isaac PetscAssertPointer(rhs, 2); 243685385478SLisandro Dalcin *rhs = snes->vec_rhs; 24373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24381096aae1SMatthew Knepley } 24391096aae1SMatthew Knepley 24409b94acceSBarry Smith /*@ 2441f6dfbefdSBarry Smith SNESComputeFunction - Calls the function that has been set with `SNESSetFunction()`. 24429b94acceSBarry Smith 2443c3339decSBarry Smith Collective 2444c7afd0dbSLois Curfman McInnes 24459b94acceSBarry Smith Input Parameters: 2446f6dfbefdSBarry Smith + snes - the `SNES` context 2447c7afd0dbSLois Curfman McInnes - x - input vector 24489b94acceSBarry Smith 24499b94acceSBarry Smith Output Parameter: 2450f6dfbefdSBarry Smith . y - function vector, as set by `SNESSetFunction()` 24519b94acceSBarry Smith 2452dc4c0fb0SBarry Smith Level: developer 2453dc4c0fb0SBarry Smith 245400677de2SStefano Zampini Notes: 2455f6dfbefdSBarry Smith `SNESComputeFunction()` is typically used within nonlinear solvers 2456bbc1464cSBarry Smith implementations, so users would not generally call this routine themselves. 245736851e7fSLois Curfman McInnes 245800677de2SStefano Zampini When solving for $F(x) = b$, this routine computes $y = F(x) - b$. 245900677de2SStefano Zampini 24601cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeMFFunction()` 24619b94acceSBarry Smith @*/ 2462d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeFunction(SNES snes, Vec x, Vec y) 2463d71ae5a4SJacob Faibussowitsch { 24646cab3a1bSJed Brown DM dm; 2465942e3340SBarry Smith DMSNES sdm; 24669b94acceSBarry Smith 24673a40ed3dSBarry Smith PetscFunctionBegin; 24680700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 24690700a824SBarry Smith PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 24700700a824SBarry Smith PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2471c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, x, 2); 2472c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, y, 3); 2473e0f629ddSJacob Faibussowitsch PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2474184914b5SBarry Smith 24759566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 24769566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 24770fdf79fbSJacob 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()."); 247832f3f7c2SPeter Brune if (sdm->ops->computefunction) { 247948a46eb9SPierre Jolivet if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0)); 24809566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(x)); 24818ddeebeaSSteve Benbow /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */ 24828ddeebeaSSteve Benbow snes->domainerror = PETSC_FALSE; 2483800f99ffSJeremy L Thompson { 2484800f99ffSJeremy L Thompson void *ctx; 24858434afd1SBarry Smith SNESFunctionFn *computefunction; 2486800f99ffSJeremy L Thompson PetscCall(DMSNESGetFunction(dm, &computefunction, &ctx)); 2487800f99ffSJeremy L Thompson PetscCallBack("SNES callback function", (*computefunction)(snes, x, y, ctx)); 2488800f99ffSJeremy L Thompson } 24899566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(x)); 249048a46eb9SPierre Jolivet if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0)); 24910fdf79fbSJacob Faibussowitsch } else /* if (snes->vec_rhs) */ { 24929566063dSJacob Faibussowitsch PetscCall(MatMult(snes->jacobian, x, y)); 24930fdf79fbSJacob Faibussowitsch } 24941baa6e33SBarry Smith if (snes->vec_rhs) PetscCall(VecAXPY(y, -1.0, snes->vec_rhs)); 2495ae3c334cSLois Curfman McInnes snes->nfuncs++; 2496422a814eSBarry Smith /* 2497422a814eSBarry Smith domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will 2498422a814eSBarry Smith propagate the value to all processes 2499422a814eSBarry Smith */ 2500f480ea8aSBarry Smith PetscCall(VecFlag(y, snes->domainerror)); 25013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 25029b94acceSBarry Smith } 25039b94acceSBarry Smith 2504c79ef259SPeter Brune /*@ 2505f6dfbefdSBarry Smith SNESComputeMFFunction - Calls the function that has been set with `SNESSetMFFunction()`. 2506bbc1464cSBarry Smith 2507c3339decSBarry Smith Collective 2508bbc1464cSBarry Smith 2509bbc1464cSBarry Smith Input Parameters: 2510f6dfbefdSBarry Smith + snes - the `SNES` context 2511bbc1464cSBarry Smith - x - input vector 2512bbc1464cSBarry Smith 2513bbc1464cSBarry Smith Output Parameter: 2514f6dfbefdSBarry Smith . y - function vector, as set by `SNESSetMFFunction()` 2515bbc1464cSBarry Smith 2516dc4c0fb0SBarry Smith Level: developer 2517dc4c0fb0SBarry Smith 2518bbc1464cSBarry Smith Notes: 2519420bcc1bSBarry Smith `SNESComputeMFFunction()` is used within the matrix-vector products called by the matrix created with `MatCreateSNESMF()` 2520bbc1464cSBarry Smith so users would not generally call this routine themselves. 2521bbc1464cSBarry Smith 2522dd8e379bSPierre Jolivet Since this function is intended for use with finite differencing it does not subtract the right-hand side vector provided with `SNESSolve()` 2523f6dfbefdSBarry Smith while `SNESComputeFunction()` does. As such, this routine cannot be used with `MatMFFDSetBase()` with a provided F function value even if it applies the 2524dd8e379bSPierre 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. 2525bbc1464cSBarry Smith 25261cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `MatCreateSNESMF` 2527bbc1464cSBarry Smith @*/ 2528d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeMFFunction(SNES snes, Vec x, Vec y) 2529d71ae5a4SJacob Faibussowitsch { 2530bbc1464cSBarry Smith DM dm; 2531bbc1464cSBarry Smith DMSNES sdm; 2532bbc1464cSBarry Smith 2533bbc1464cSBarry Smith PetscFunctionBegin; 2534bbc1464cSBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2535bbc1464cSBarry Smith PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2536bbc1464cSBarry Smith PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2537bbc1464cSBarry Smith PetscCheckSameComm(snes, 1, x, 2); 2538bbc1464cSBarry Smith PetscCheckSameComm(snes, 1, y, 3); 2539e0f629ddSJacob Faibussowitsch PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2540bbc1464cSBarry Smith 25419566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 25429566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 25439566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0)); 25449566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(x)); 2545bbc1464cSBarry Smith /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */ 2546bbc1464cSBarry Smith snes->domainerror = PETSC_FALSE; 2547792fecdfSBarry Smith PetscCallBack("SNES callback function", (*sdm->ops->computemffunction)(snes, x, y, sdm->mffunctionctx)); 25489566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(x)); 25499566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0)); 2550bbc1464cSBarry Smith snes->nfuncs++; 2551bbc1464cSBarry Smith /* 2552bbc1464cSBarry Smith domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will 2553bbc1464cSBarry Smith propagate the value to all processes 2554bbc1464cSBarry Smith */ 2555f480ea8aSBarry Smith PetscCall(VecFlag(y, snes->domainerror)); 25563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2557bbc1464cSBarry Smith } 2558bbc1464cSBarry Smith 2559bbc1464cSBarry Smith /*@ 2560f6dfbefdSBarry Smith SNESComputeNGS - Calls the Gauss-Seidel function that has been set with `SNESSetNGS()`. 2561c79ef259SPeter Brune 2562c3339decSBarry Smith Collective 2563c79ef259SPeter Brune 2564c79ef259SPeter Brune Input Parameters: 2565f6dfbefdSBarry Smith + snes - the `SNES` context 2566c79ef259SPeter Brune . x - input vector 2567c79ef259SPeter Brune - b - rhs vector 2568c79ef259SPeter Brune 2569c79ef259SPeter Brune Output Parameter: 2570c79ef259SPeter Brune . x - new solution vector 2571c79ef259SPeter Brune 2572dc4c0fb0SBarry Smith Level: developer 2573dc4c0fb0SBarry Smith 2574f6dfbefdSBarry Smith Note: 2575f6dfbefdSBarry Smith `SNESComputeNGS()` is typically used within composed nonlinear solver 2576c79ef259SPeter Brune implementations, so most users would not generally call this routine 2577c79ef259SPeter Brune themselves. 2578c79ef259SPeter Brune 25798434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGSFn`, `SNESSetNGS()`, `SNESComputeFunction()`, `SNESNGS` 2580c79ef259SPeter Brune @*/ 2581d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeNGS(SNES snes, Vec b, Vec x) 2582d71ae5a4SJacob Faibussowitsch { 25836cab3a1bSJed Brown DM dm; 2584942e3340SBarry Smith DMSNES sdm; 2585646217ecSPeter Brune 2586646217ecSPeter Brune PetscFunctionBegin; 2587646217ecSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2588064a246eSJacob Faibussowitsch PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 2589064a246eSJacob Faibussowitsch if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 2590064a246eSJacob Faibussowitsch PetscCheckSameComm(snes, 1, x, 3); 2591064a246eSJacob Faibussowitsch if (b) PetscCheckSameComm(snes, 1, b, 2); 2592e0f629ddSJacob Faibussowitsch if (b) PetscCall(VecValidValues_Internal(b, 2, PETSC_TRUE)); 25939566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_NGSEval, snes, x, b, 0)); 25949566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 25959566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 25960fdf79fbSJacob Faibussowitsch PetscCheck(sdm->ops->computegs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetNGS() before SNESComputeNGS(), likely called from SNESSolve()."); 25979566063dSJacob Faibussowitsch if (b) PetscCall(VecLockReadPush(b)); 2598792fecdfSBarry Smith PetscCallBack("SNES callback NGS", (*sdm->ops->computegs)(snes, x, b, sdm->gsctx)); 25999566063dSJacob Faibussowitsch if (b) PetscCall(VecLockReadPop(b)); 26009566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_NGSEval, snes, x, b, 0)); 26013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2602646217ecSPeter Brune } 2603646217ecSPeter Brune 2604494a190aSStefano Zampini static PetscErrorCode SNESComputeFunction_FD(SNES snes, Vec Xin, Vec G) 2605494a190aSStefano Zampini { 2606494a190aSStefano Zampini Vec X; 2607494a190aSStefano Zampini PetscScalar *g; 2608494a190aSStefano Zampini PetscReal f, f2; 2609494a190aSStefano Zampini PetscInt low, high, N, i; 2610494a190aSStefano Zampini PetscBool flg; 2611494a190aSStefano Zampini PetscReal h = .5 * PETSC_SQRT_MACHINE_EPSILON; 2612494a190aSStefano Zampini 2613494a190aSStefano Zampini PetscFunctionBegin; 2614494a190aSStefano Zampini PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_fd_delta", &h, &flg)); 2615494a190aSStefano Zampini PetscCall(VecDuplicate(Xin, &X)); 2616494a190aSStefano Zampini PetscCall(VecCopy(Xin, X)); 2617494a190aSStefano Zampini PetscCall(VecGetSize(X, &N)); 2618494a190aSStefano Zampini PetscCall(VecGetOwnershipRange(X, &low, &high)); 2619494a190aSStefano Zampini PetscCall(VecSetOption(X, VEC_IGNORE_OFF_PROC_ENTRIES, PETSC_TRUE)); 2620494a190aSStefano Zampini PetscCall(VecGetArray(G, &g)); 2621494a190aSStefano Zampini for (i = 0; i < N; i++) { 2622494a190aSStefano Zampini PetscCall(VecSetValue(X, i, -h, ADD_VALUES)); 2623494a190aSStefano Zampini PetscCall(VecAssemblyBegin(X)); 2624494a190aSStefano Zampini PetscCall(VecAssemblyEnd(X)); 2625494a190aSStefano Zampini PetscCall(SNESComputeObjective(snes, X, &f)); 2626494a190aSStefano Zampini PetscCall(VecSetValue(X, i, 2.0 * h, ADD_VALUES)); 2627494a190aSStefano Zampini PetscCall(VecAssemblyBegin(X)); 2628494a190aSStefano Zampini PetscCall(VecAssemblyEnd(X)); 2629494a190aSStefano Zampini PetscCall(SNESComputeObjective(snes, X, &f2)); 2630494a190aSStefano Zampini PetscCall(VecSetValue(X, i, -h, ADD_VALUES)); 2631494a190aSStefano Zampini PetscCall(VecAssemblyBegin(X)); 2632494a190aSStefano Zampini PetscCall(VecAssemblyEnd(X)); 2633494a190aSStefano Zampini if (i >= low && i < high) g[i - low] = (f2 - f) / (2.0 * h); 2634494a190aSStefano Zampini } 2635494a190aSStefano Zampini PetscCall(VecRestoreArray(G, &g)); 2636494a190aSStefano Zampini PetscCall(VecDestroy(&X)); 2637494a190aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2638494a190aSStefano Zampini } 2639494a190aSStefano Zampini 2640494a190aSStefano Zampini PetscErrorCode SNESTestFunction(SNES snes) 2641494a190aSStefano Zampini { 2642494a190aSStefano Zampini Vec x, g1, g2, g3; 2643494a190aSStefano Zampini PetscBool complete_print = PETSC_FALSE, test = PETSC_FALSE; 2644494a190aSStefano Zampini PetscReal hcnorm, fdnorm, hcmax, fdmax, diffmax, diffnorm; 2645494a190aSStefano Zampini PetscScalar dot; 2646494a190aSStefano Zampini MPI_Comm comm; 2647494a190aSStefano Zampini PetscViewer viewer, mviewer; 2648494a190aSStefano Zampini PetscViewerFormat format; 2649494a190aSStefano Zampini PetscInt tabs; 2650494a190aSStefano Zampini static PetscBool directionsprinted = PETSC_FALSE; 26518434afd1SBarry Smith SNESObjectiveFn *objective; 2652494a190aSStefano Zampini 2653494a190aSStefano Zampini PetscFunctionBegin; 2654494a190aSStefano Zampini PetscCall(SNESGetObjective(snes, &objective, NULL)); 2655494a190aSStefano Zampini if (!objective) PetscFunctionReturn(PETSC_SUCCESS); 2656494a190aSStefano Zampini 2657494a190aSStefano Zampini PetscObjectOptionsBegin((PetscObject)snes); 2658494a190aSStefano Zampini PetscCall(PetscOptionsName("-snes_test_function", "Compare hand-coded and finite difference function", "None", &test)); 2659494a190aSStefano Zampini PetscCall(PetscOptionsViewer("-snes_test_function_view", "View difference between hand-coded and finite difference function element entries", "None", &mviewer, &format, &complete_print)); 2660494a190aSStefano Zampini PetscOptionsEnd(); 2661494a190aSStefano Zampini if (!test) { 2662494a190aSStefano Zampini if (complete_print) PetscCall(PetscViewerDestroy(&mviewer)); 2663494a190aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2664494a190aSStefano Zampini } 2665494a190aSStefano Zampini 2666494a190aSStefano Zampini PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 2667494a190aSStefano Zampini PetscCall(PetscViewerASCIIGetStdout(comm, &viewer)); 2668494a190aSStefano Zampini PetscCall(PetscViewerASCIIGetTab(viewer, &tabs)); 2669494a190aSStefano Zampini PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel)); 2670494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Function -------------\n")); 2671494a190aSStefano Zampini if (!complete_print && !directionsprinted) { 2672494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Run with -snes_test_function_view and optionally -snes_test_function <threshold> to show difference\n")); 2673494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " of hand-coded and finite difference function entries greater than <threshold>.\n")); 2674494a190aSStefano Zampini } 2675494a190aSStefano Zampini if (!directionsprinted) { 2676494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Testing hand-coded Function, if (for double precision runs) ||F - Ffd||/||F|| is\n")); 2677494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " O(1.e-8), the hand-coded Function is probably correct.\n")); 2678494a190aSStefano Zampini directionsprinted = PETSC_TRUE; 2679494a190aSStefano Zampini } 2680494a190aSStefano Zampini if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format)); 2681494a190aSStefano Zampini 2682494a190aSStefano Zampini PetscCall(SNESGetSolution(snes, &x)); 2683494a190aSStefano Zampini PetscCall(VecDuplicate(x, &g1)); 2684494a190aSStefano Zampini PetscCall(VecDuplicate(x, &g2)); 2685494a190aSStefano Zampini PetscCall(VecDuplicate(x, &g3)); 2686494a190aSStefano Zampini PetscCall(SNESComputeFunction(snes, x, g1)); 2687494a190aSStefano Zampini PetscCall(SNESComputeFunction_FD(snes, x, g2)); 2688494a190aSStefano Zampini 2689494a190aSStefano Zampini PetscCall(VecNorm(g2, NORM_2, &fdnorm)); 2690494a190aSStefano Zampini PetscCall(VecNorm(g1, NORM_2, &hcnorm)); 2691494a190aSStefano Zampini PetscCall(VecNorm(g2, NORM_INFINITY, &fdmax)); 2692494a190aSStefano Zampini PetscCall(VecNorm(g1, NORM_INFINITY, &hcmax)); 2693494a190aSStefano Zampini PetscCall(VecDot(g1, g2, &dot)); 2694494a190aSStefano Zampini PetscCall(VecCopy(g1, g3)); 2695494a190aSStefano Zampini PetscCall(VecAXPY(g3, -1.0, g2)); 2696494a190aSStefano Zampini PetscCall(VecNorm(g3, NORM_2, &diffnorm)); 2697494a190aSStefano Zampini PetscCall(VecNorm(g3, NORM_INFINITY, &diffmax)); 2698494a190aSStefano 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)))); 2699494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " 2-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffnorm / PetscMax(hcnorm, fdnorm)), (double)diffnorm)); 2700494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " max-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffmax / PetscMax(hcmax, fdmax)), (double)diffmax)); 2701494a190aSStefano Zampini 2702494a190aSStefano Zampini if (complete_print) { 2703494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded function ----------\n")); 2704494a190aSStefano Zampini PetscCall(VecView(g1, mviewer)); 2705494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Finite difference function ----------\n")); 2706494a190aSStefano Zampini PetscCall(VecView(g2, mviewer)); 2707494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded minus finite-difference function ----------\n")); 2708494a190aSStefano Zampini PetscCall(VecView(g3, mviewer)); 2709494a190aSStefano Zampini } 2710494a190aSStefano Zampini PetscCall(VecDestroy(&g1)); 2711494a190aSStefano Zampini PetscCall(VecDestroy(&g2)); 2712494a190aSStefano Zampini PetscCall(VecDestroy(&g3)); 2713494a190aSStefano Zampini 2714494a190aSStefano Zampini if (complete_print) { 2715494a190aSStefano Zampini PetscCall(PetscViewerPopFormat(mviewer)); 2716494a190aSStefano Zampini PetscCall(PetscViewerDestroy(&mviewer)); 2717494a190aSStefano Zampini } 2718494a190aSStefano Zampini PetscCall(PetscViewerASCIISetTab(viewer, tabs)); 2719494a190aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2720494a190aSStefano Zampini } 2721494a190aSStefano Zampini 2722d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestJacobian(SNES snes) 2723d71ae5a4SJacob Faibussowitsch { 272412837594SBarry Smith Mat A, B, C, D, jacobian; 27254df93895SStefano Zampini Vec x = snes->vec_sol, f; 2726e885f1abSBarry Smith PetscReal nrm, gnorm; 272781e7118cSBarry Smith PetscReal threshold = 1.e-5; 27280e276705SLisandro Dalcin MatType mattype; 2729e885f1abSBarry Smith PetscInt m, n, M, N; 2730e885f1abSBarry Smith void *functx; 27312cd624f9SStefano Zampini PetscBool complete_print = PETSC_FALSE, threshold_print = PETSC_FALSE, test = PETSC_FALSE, flg, istranspose; 27323325ff46SBarry Smith PetscViewer viewer, mviewer; 2733e885f1abSBarry Smith MPI_Comm comm; 2734e885f1abSBarry Smith PetscInt tabs; 273512837594SBarry Smith static PetscBool directionsprinted = PETSC_FALSE; 27363325ff46SBarry Smith PetscViewerFormat format; 2737e885f1abSBarry Smith 2738e885f1abSBarry Smith PetscFunctionBegin; 2739d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)snes); 27409566063dSJacob Faibussowitsch PetscCall(PetscOptionsName("-snes_test_jacobian", "Compare hand-coded and finite difference Jacobians", "None", &test)); 27419566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-snes_test_jacobian", "Threshold for element difference between hand-coded and finite difference being meaningful", "None", threshold, &threshold, NULL)); 27429566063dSJacob Faibussowitsch PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display", "-snes_test_jacobian_view", "3.13", NULL)); 27434ead3382SBarry Smith PetscCall(PetscOptionsViewer("-snes_test_jacobian_view", "View difference between hand-coded and finite difference Jacobians element entries", "None", &mviewer, &format, &complete_print)); 27449566063dSJacob Faibussowitsch PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display_threshold", "-snes_test_jacobian", "3.13", "-snes_test_jacobian accepts an optional threshold (since v3.10)")); 27459566063dSJacob 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)); 2746d0609cedSBarry Smith PetscOptionsEnd(); 27473ba16761SJacob Faibussowitsch if (!test) PetscFunctionReturn(PETSC_SUCCESS); 2748e885f1abSBarry Smith 27499566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 27509566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(comm, &viewer)); 27519566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetTab(viewer, &tabs)); 27529566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel)); 27539566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Jacobian -------------\n")); 275412837594SBarry Smith if (!complete_print && !directionsprinted) { 27559566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Run with -snes_test_jacobian_view and optionally -snes_test_jacobian <threshold> to show difference\n")); 27569566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " of hand-coded and finite difference Jacobian entries greater than <threshold>.\n")); 275712837594SBarry Smith } 275812837594SBarry Smith if (!directionsprinted) { 27599566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Testing hand-coded Jacobian, if (for double precision runs) ||J - Jfd||_F/||J||_F is\n")); 27609566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " O(1.e-8), the hand-coded Jacobian is probably correct.\n")); 276112837594SBarry Smith directionsprinted = PETSC_TRUE; 2762e885f1abSBarry Smith } 27631baa6e33SBarry Smith if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format)); 2764e885f1abSBarry Smith 27659566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes->jacobian, MATMFFD, &flg)); 276612837594SBarry Smith if (!flg) jacobian = snes->jacobian; 276712837594SBarry Smith else jacobian = snes->jacobian_pre; 276812837594SBarry Smith 27694df93895SStefano Zampini if (!x) PetscCall(MatCreateVecs(jacobian, &x, NULL)); 27704df93895SStefano Zampini else PetscCall(PetscObjectReference((PetscObject)x)); 27719566063dSJacob Faibussowitsch PetscCall(VecDuplicate(x, &f)); 27724df93895SStefano Zampini 2773a82339d0SMatthew G. Knepley /* evaluate the function at this point because SNESComputeJacobianDefault() assumes that the function has been evaluated and put into snes->vec_func */ 27749566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, x, f)); 27759566063dSJacob Faibussowitsch PetscCall(VecDestroy(&f)); 27769566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESKSPTRANSPOSEONLY, &istranspose)); 277712837594SBarry Smith while (jacobian) { 27782cd624f9SStefano Zampini Mat JT = NULL, Jsave = NULL; 27792cd624f9SStefano Zampini 27802cd624f9SStefano Zampini if (istranspose) { 27819566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(jacobian, &JT)); 27822cd624f9SStefano Zampini Jsave = jacobian; 27832cd624f9SStefano Zampini jacobian = JT; 27842cd624f9SStefano Zampini } 27859566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)jacobian, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, "")); 278612837594SBarry Smith if (flg) { 278712837594SBarry Smith A = jacobian; 27889566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 278912837594SBarry Smith } else { 27909566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(jacobian, MATAIJ, &A)); 279112837594SBarry Smith } 2792e885f1abSBarry Smith 27939566063dSJacob Faibussowitsch PetscCall(MatGetType(A, &mattype)); 27949566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &M, &N)); 27959566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &m, &n)); 27969566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B)); 27979566063dSJacob Faibussowitsch PetscCall(MatSetType(B, mattype)); 27989566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, m, n, M, N)); 27999566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(B, A, A)); 28009566063dSJacob Faibussowitsch PetscCall(MatSetUp(B)); 28019566063dSJacob Faibussowitsch PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 2802e885f1abSBarry Smith 28039566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, NULL, &functx)); 28049566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobianDefault(snes, x, B, B, functx)); 280512837594SBarry Smith 28069566063dSJacob Faibussowitsch PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &D)); 28079566063dSJacob Faibussowitsch PetscCall(MatAYPX(D, -1.0, A, DIFFERENT_NONZERO_PATTERN)); 28089566063dSJacob Faibussowitsch PetscCall(MatNorm(D, NORM_FROBENIUS, &nrm)); 28099566063dSJacob Faibussowitsch PetscCall(MatNorm(A, NORM_FROBENIUS, &gnorm)); 28109566063dSJacob Faibussowitsch PetscCall(MatDestroy(&D)); 281112837594SBarry Smith if (!gnorm) gnorm = 1; /* just in case */ 28129566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " ||J - Jfd||_F/||J||_F = %g, ||J - Jfd||_F = %g\n", (double)(nrm / gnorm), (double)nrm)); 281312837594SBarry Smith 2814e885f1abSBarry Smith if (complete_print) { 28159566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded Jacobian ----------\n")); 28169566063dSJacob Faibussowitsch PetscCall(MatView(A, mviewer)); 28179566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Finite difference Jacobian ----------\n")); 28189566063dSJacob Faibussowitsch PetscCall(MatView(B, mviewer)); 2819e885f1abSBarry Smith } 2820e885f1abSBarry Smith 2821df10fb39SFande Kong if (threshold_print || complete_print) { 2822e885f1abSBarry Smith PetscInt Istart, Iend, *ccols, bncols, cncols, j, row; 2823e885f1abSBarry Smith PetscScalar *cvals; 2824e885f1abSBarry Smith const PetscInt *bcols; 2825e885f1abSBarry Smith const PetscScalar *bvals; 2826e885f1abSBarry Smith 28279566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C)); 28289566063dSJacob Faibussowitsch PetscCall(MatSetType(C, mattype)); 28299566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, m, n, M, N)); 28309566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(C, A, A)); 28319566063dSJacob Faibussowitsch PetscCall(MatSetUp(C)); 28329566063dSJacob Faibussowitsch PetscCall(MatSetOption(C, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 28330e276705SLisandro Dalcin 28349566063dSJacob Faibussowitsch PetscCall(MatAYPX(B, -1.0, A, DIFFERENT_NONZERO_PATTERN)); 28359566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(B, &Istart, &Iend)); 2836e885f1abSBarry Smith 2837e885f1abSBarry Smith for (row = Istart; row < Iend; row++) { 28389566063dSJacob Faibussowitsch PetscCall(MatGetRow(B, row, &bncols, &bcols, &bvals)); 28399566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(bncols, &ccols, bncols, &cvals)); 2840e885f1abSBarry Smith for (j = 0, cncols = 0; j < bncols; j++) { 284123a52b1dSBarry Smith if (PetscAbsScalar(bvals[j]) > threshold) { 2842e885f1abSBarry Smith ccols[cncols] = bcols[j]; 2843e885f1abSBarry Smith cvals[cncols] = bvals[j]; 2844e885f1abSBarry Smith cncols += 1; 2845e885f1abSBarry Smith } 2846e885f1abSBarry Smith } 284748a46eb9SPierre Jolivet if (cncols) PetscCall(MatSetValues(C, 1, &row, cncols, ccols, cvals, INSERT_VALUES)); 28489566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(B, row, &bncols, &bcols, &bvals)); 28499566063dSJacob Faibussowitsch PetscCall(PetscFree2(ccols, cvals)); 2850e885f1abSBarry Smith } 28519566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 28529566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 28539566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded minus finite-difference Jacobian with tolerance %g ----------\n", (double)threshold)); 28549566063dSJacob Faibussowitsch PetscCall(MatView(C, complete_print ? mviewer : viewer)); 28559566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C)); 2856e885f1abSBarry Smith } 28579566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A)); 28589566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 28599566063dSJacob Faibussowitsch PetscCall(MatDestroy(&JT)); 28602cd624f9SStefano Zampini if (Jsave) jacobian = Jsave; 286112837594SBarry Smith if (jacobian != snes->jacobian_pre) { 286212837594SBarry Smith jacobian = snes->jacobian_pre; 28639566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Jacobian for preconditioner -------------\n")); 28649371c9d4SSatish Balay } else jacobian = NULL; 286512837594SBarry Smith } 28669566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); 28671baa6e33SBarry Smith if (complete_print) PetscCall(PetscViewerPopFormat(mviewer)); 2868648c30bcSBarry Smith if (mviewer) PetscCall(PetscViewerDestroy(&mviewer)); 28699566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISetTab(viewer, tabs)); 28703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2871e885f1abSBarry Smith } 2872e885f1abSBarry Smith 287362fef451SLois Curfman McInnes /*@ 2874f6dfbefdSBarry Smith SNESComputeJacobian - Computes the Jacobian matrix that has been set with `SNESSetJacobian()`. 287562fef451SLois Curfman McInnes 2876c3339decSBarry Smith Collective 2877c7afd0dbSLois Curfman McInnes 287862fef451SLois Curfman McInnes Input Parameters: 2879f6dfbefdSBarry Smith + snes - the `SNES` context 2880e4094ef1SJacob Faibussowitsch - X - input vector 288162fef451SLois Curfman McInnes 288262fef451SLois Curfman McInnes Output Parameters: 2883c7afd0dbSLois Curfman McInnes + A - Jacobian matrix 2884420bcc1bSBarry Smith - B - optional matrix for building the preconditioner, usually the same as `A` 2885fee21e36SBarry Smith 2886e35cf81dSBarry Smith Options Database Keys: 288767b8a455SSatish Balay + -snes_lag_preconditioner <lag> - how often to rebuild preconditioner 288867b8a455SSatish Balay . -snes_lag_jacobian <lag> - how often to rebuild Jacobian 2889455a5933SJed 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. 2890455a5933SJed 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 2891693365a8SJed Brown . -snes_compare_explicit - Compare the computed Jacobian to the finite difference Jacobian and output the differences 2892693365a8SJed Brown . -snes_compare_explicit_draw - Compare the computed Jacobian to the finite difference Jacobian and draw the result 2893693365a8SJed Brown . -snes_compare_explicit_contour - Compare the computed Jacobian to the finite difference Jacobian and draw a contour plot with the result 28944c30e9fbSJed Brown . -snes_compare_operator - Make the comparison options above use the operator instead of the preconditioning matrix 289594d6a431SBarry Smith . -snes_compare_coloring - Compute the finite difference Jacobian using coloring and display norms of difference 2896a5b23f4aSJose E. Roman . -snes_compare_coloring_display - Compute the finite difference Jacobian using coloring and display verbose differences 2897c01495d3SJed Brown . -snes_compare_coloring_threshold - Display only those matrix entries that differ by more than a given threshold 2898dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_atol - Absolute tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold` 2899dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_rtol - Relative tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold` 2900a5b23f4aSJose E. Roman . -snes_compare_coloring_draw - Compute the finite difference Jacobian using coloring and draw differences 2901a5b23f4aSJose E. Roman - -snes_compare_coloring_draw_contour - Compute the finite difference Jacobian using coloring and show contours of matrices and differences 2902c01495d3SJed Brown 2903dc4c0fb0SBarry Smith Level: developer 2904dc4c0fb0SBarry Smith 2905f6dfbefdSBarry Smith Note: 290662fef451SLois Curfman McInnes Most users should not need to explicitly call this routine, as it 290762fef451SLois Curfman McInnes is used internally within the nonlinear solvers. 290862fef451SLois Curfman McInnes 2909420bcc1bSBarry Smith Developer Note: 2910dc4c0fb0SBarry 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 2911420bcc1bSBarry Smith with the `SNESType` of test that has been removed. 2912e885f1abSBarry Smith 29131cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetJacobian()`, `KSPSetOperators()`, `MatStructure`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()` 291462fef451SLois Curfman McInnes @*/ 2915d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeJacobian(SNES snes, Vec X, Mat A, Mat B) 2916d71ae5a4SJacob Faibussowitsch { 2917ace3abfcSBarry Smith PetscBool flag; 29186cab3a1bSJed Brown DM dm; 2919942e3340SBarry Smith DMSNES sdm; 2920e0e3a89bSBarry Smith KSP ksp; 29213a40ed3dSBarry Smith 29223a40ed3dSBarry Smith PetscFunctionBegin; 29230700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 29240700a824SBarry Smith PetscValidHeaderSpecific(X, VEC_CLASSID, 2); 2925c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, X, 2); 2926e0f629ddSJacob Faibussowitsch PetscCall(VecValidValues_Internal(X, 2, PETSC_TRUE)); 29279566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 29289566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 29293232da50SPeter Brune 293001c1178eSBarry Smith /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix-free */ 2931fe3ffe1eSBarry Smith if (snes->lagjacobian == -2) { 2932fe3ffe1eSBarry Smith snes->lagjacobian = -1; 2933f5af7f23SKarl Rupp 29349566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n")); 2935fe3ffe1eSBarry Smith } else if (snes->lagjacobian == -1) { 29369566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is -1\n")); 29379566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag)); 2938ebd3b9afSBarry Smith if (flag) { 29399566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 29409566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 2941ebd3b9afSBarry Smith } 29423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 294337ec4e1aSPeter Brune } else if (snes->lagjacobian > 1 && (snes->iter + snes->jac_iter) % snes->lagjacobian) { 294463a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagjacobian, snes->iter)); 29459566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag)); 2946ebd3b9afSBarry Smith if (flag) { 29479566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 29489566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 2949ebd3b9afSBarry Smith } 29503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2951e35cf81dSBarry Smith } 2952efd4aadfSBarry Smith if (snes->npc && snes->npcside == PC_LEFT) { 29539566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 29549566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 29553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2956d728fb7dSPeter Brune } 2957e35cf81dSBarry Smith 29589566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_JacobianEval, snes, X, A, B)); 29599566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(X)); 2960800f99ffSJeremy L Thompson { 2961800f99ffSJeremy L Thompson void *ctx; 29628434afd1SBarry Smith SNESJacobianFn *J; 2963800f99ffSJeremy L Thompson PetscCall(DMSNESGetJacobian(dm, &J, &ctx)); 2964800f99ffSJeremy L Thompson PetscCallBack("SNES callback Jacobian", (*J)(snes, X, A, B, ctx)); 2965800f99ffSJeremy L Thompson } 29669566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(X)); 29679566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_JacobianEval, snes, X, A, B)); 296828d58a37SPierre Jolivet 296928d58a37SPierre Jolivet /* attach latest linearization point to the preconditioning matrix */ 29709566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)B, "__SNES_latest_X", (PetscObject)X)); 2971a8054027SBarry Smith 2972e0e3a89bSBarry Smith /* the next line ensures that snes->ksp exists */ 29739566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 29743b4f5425SBarry Smith if (snes->lagpreconditioner == -2) { 29759566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Rebuilding preconditioner exactly once since lag is -2\n")); 29769566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE)); 29773b4f5425SBarry Smith snes->lagpreconditioner = -1; 29783b4f5425SBarry Smith } else if (snes->lagpreconditioner == -1) { 29799566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is -1\n")); 29809566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE)); 298137ec4e1aSPeter Brune } else if (snes->lagpreconditioner > 1 && (snes->iter + snes->pre_iter) % snes->lagpreconditioner) { 298263a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagpreconditioner, snes->iter)); 29839566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE)); 2984d1e9a80fSBarry Smith } else { 29859566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Rebuilding preconditioner\n")); 29869566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE)); 2987a8054027SBarry Smith } 2988a8054027SBarry Smith 29894df93895SStefano Zampini /* monkey business to allow testing Jacobians in multilevel solvers. 29904df93895SStefano Zampini This is needed because the SNESTestXXX interface does not accept vectors and matrices */ 29914df93895SStefano Zampini { 29924df93895SStefano Zampini Vec xsave = snes->vec_sol; 29934df93895SStefano Zampini Mat jacobiansave = snes->jacobian; 29944df93895SStefano Zampini Mat jacobian_presave = snes->jacobian_pre; 29954df93895SStefano Zampini 29964df93895SStefano Zampini snes->vec_sol = X; 29974df93895SStefano Zampini snes->jacobian = A; 29984df93895SStefano Zampini snes->jacobian_pre = B; 2999494a190aSStefano Zampini PetscCall(SNESTestFunction(snes)); 30009566063dSJacob Faibussowitsch PetscCall(SNESTestJacobian(snes)); 3001494a190aSStefano Zampini 30024df93895SStefano Zampini snes->vec_sol = xsave; 30034df93895SStefano Zampini snes->jacobian = jacobiansave; 30044df93895SStefano Zampini snes->jacobian_pre = jacobian_presave; 30054df93895SStefano Zampini } 30064df93895SStefano Zampini 3007693365a8SJed Brown { 3008693365a8SJed Brown PetscBool flag = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_operator = PETSC_FALSE; 3009648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit", NULL, NULL, &flag)); 3010648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw", NULL, NULL, &flag_draw)); 3011648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw_contour", NULL, NULL, &flag_contour)); 3012648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_operator", NULL, NULL, &flag_operator)); 3013693365a8SJed Brown if (flag || flag_draw || flag_contour) { 30140298fd71SBarry Smith Mat Bexp_mine = NULL, Bexp, FDexp; 3015693365a8SJed Brown PetscViewer vdraw, vstdout; 30166b3a5b13SJed Brown PetscBool flg; 3017693365a8SJed Brown if (flag_operator) { 30189566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(A, MATAIJ, &Bexp_mine)); 3019693365a8SJed Brown Bexp = Bexp_mine; 3020693365a8SJed Brown } else { 3021693365a8SJed Brown /* See if the preconditioning matrix can be viewed and added directly */ 30229566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)B, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPIBAIJ, "")); 302394ab13aaSBarry Smith if (flg) Bexp = B; 3024693365a8SJed Brown else { 3025693365a8SJed Brown /* If the "preconditioning" matrix is itself MATSHELL or some other type without direct support */ 30269566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(B, MATAIJ, &Bexp_mine)); 3027693365a8SJed Brown Bexp = Bexp_mine; 3028693365a8SJed Brown } 3029693365a8SJed Brown } 30309566063dSJacob Faibussowitsch PetscCall(MatConvert(Bexp, MATSAME, MAT_INITIAL_MATRIX, &FDexp)); 30319566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobianDefault(snes, X, FDexp, FDexp, NULL)); 30329566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout)); 3033693365a8SJed Brown if (flag_draw || flag_contour) { 30349566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Explicit Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw)); 30359566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 30360298fd71SBarry Smith } else vdraw = NULL; 30379566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit %s\n", flag_operator ? "Jacobian" : "preconditioning Jacobian")); 30389566063dSJacob Faibussowitsch if (flag) PetscCall(MatView(Bexp, vstdout)); 30399566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(Bexp, vdraw)); 30409566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Finite difference Jacobian\n")); 30419566063dSJacob Faibussowitsch if (flag) PetscCall(MatView(FDexp, vstdout)); 30429566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(FDexp, vdraw)); 30439566063dSJacob Faibussowitsch PetscCall(MatAYPX(FDexp, -1.0, Bexp, SAME_NONZERO_PATTERN)); 30449566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian\n")); 30459566063dSJacob Faibussowitsch if (flag) PetscCall(MatView(FDexp, vstdout)); 3046693365a8SJed Brown if (vdraw) { /* Always use contour for the difference */ 30479566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 30489566063dSJacob Faibussowitsch PetscCall(MatView(FDexp, vdraw)); 30499566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(vdraw)); 3050693365a8SJed Brown } 30519566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw)); 30529566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&vdraw)); 30539566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bexp_mine)); 30549566063dSJacob Faibussowitsch PetscCall(MatDestroy(&FDexp)); 3055693365a8SJed Brown } 3056693365a8SJed Brown } 30574c30e9fbSJed Brown { 30586719d8e4SJed Brown PetscBool flag = PETSC_FALSE, flag_display = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_threshold = PETSC_FALSE; 30596719d8e4SJed Brown PetscReal threshold_atol = PETSC_SQRT_MACHINE_EPSILON, threshold_rtol = 10 * PETSC_SQRT_MACHINE_EPSILON; 3060648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring", NULL, NULL, &flag)); 3061648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_display", NULL, NULL, &flag_display)); 3062648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw", NULL, NULL, &flag_draw)); 3063648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw_contour", NULL, NULL, &flag_contour)); 3064648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold", NULL, NULL, &flag_threshold)); 306527b0f280SBarry Smith if (flag_threshold) { 30669566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_rtol", &threshold_rtol, NULL)); 30679566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_atol", &threshold_atol, NULL)); 306827b0f280SBarry Smith } 30696719d8e4SJed Brown if (flag || flag_display || flag_draw || flag_contour || flag_threshold) { 30704c30e9fbSJed Brown Mat Bfd; 30714c30e9fbSJed Brown PetscViewer vdraw, vstdout; 3072335efc43SPeter Brune MatColoring coloring; 30734c30e9fbSJed Brown ISColoring iscoloring; 30744c30e9fbSJed Brown MatFDColoring matfdcoloring; 30758434afd1SBarry Smith SNESFunctionFn *func; 30764c30e9fbSJed Brown void *funcctx; 30776719d8e4SJed Brown PetscReal norm1, norm2, normmax; 30784c30e9fbSJed Brown 30799566063dSJacob Faibussowitsch PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &Bfd)); 30809566063dSJacob Faibussowitsch PetscCall(MatColoringCreate(Bfd, &coloring)); 30819566063dSJacob Faibussowitsch PetscCall(MatColoringSetType(coloring, MATCOLORINGSL)); 30829566063dSJacob Faibussowitsch PetscCall(MatColoringSetFromOptions(coloring)); 30839566063dSJacob Faibussowitsch PetscCall(MatColoringApply(coloring, &iscoloring)); 30849566063dSJacob Faibussowitsch PetscCall(MatColoringDestroy(&coloring)); 30859566063dSJacob Faibussowitsch PetscCall(MatFDColoringCreate(Bfd, iscoloring, &matfdcoloring)); 30869566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFromOptions(matfdcoloring)); 30879566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetUp(Bfd, iscoloring, matfdcoloring)); 30889566063dSJacob Faibussowitsch PetscCall(ISColoringDestroy(&iscoloring)); 30894c30e9fbSJed Brown 30904c30e9fbSJed Brown /* This method of getting the function is currently unreliable since it doesn't work for DM local functions. */ 30919566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, &func, &funcctx)); 30929566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFunction(matfdcoloring, (PetscErrorCode (*)(void))func, funcctx)); 30939566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)matfdcoloring, ((PetscObject)snes)->prefix)); 30949566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)matfdcoloring, "coloring_")); 30959566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFromOptions(matfdcoloring)); 30969566063dSJacob Faibussowitsch PetscCall(MatFDColoringApply(Bfd, matfdcoloring, X, snes)); 30979566063dSJacob Faibussowitsch PetscCall(MatFDColoringDestroy(&matfdcoloring)); 30984c30e9fbSJed Brown 30999566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout)); 31004c30e9fbSJed Brown if (flag_draw || flag_contour) { 31019566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Colored Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw)); 31029566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 31030298fd71SBarry Smith } else vdraw = NULL; 31049566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit preconditioning Jacobian\n")); 31059566063dSJacob Faibussowitsch if (flag_display) PetscCall(MatView(B, vstdout)); 31069566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(B, vdraw)); 31079566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Colored Finite difference Jacobian\n")); 31089566063dSJacob Faibussowitsch if (flag_display) PetscCall(MatView(Bfd, vstdout)); 31099566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(Bfd, vdraw)); 31109566063dSJacob Faibussowitsch PetscCall(MatAYPX(Bfd, -1.0, B, SAME_NONZERO_PATTERN)); 31119566063dSJacob Faibussowitsch PetscCall(MatNorm(Bfd, NORM_1, &norm1)); 31129566063dSJacob Faibussowitsch PetscCall(MatNorm(Bfd, NORM_FROBENIUS, &norm2)); 31139566063dSJacob Faibussowitsch PetscCall(MatNorm(Bfd, NORM_MAX, &normmax)); 31149566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian, norm1=%g normFrob=%g normmax=%g\n", (double)norm1, (double)norm2, (double)normmax)); 31159566063dSJacob Faibussowitsch if (flag_display) PetscCall(MatView(Bfd, vstdout)); 31164c30e9fbSJed Brown if (vdraw) { /* Always use contour for the difference */ 31179566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 31189566063dSJacob Faibussowitsch PetscCall(MatView(Bfd, vdraw)); 31199566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(vdraw)); 31204c30e9fbSJed Brown } 31219566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw)); 31226719d8e4SJed Brown 31236719d8e4SJed Brown if (flag_threshold) { 31246719d8e4SJed Brown PetscInt bs, rstart, rend, i; 31259566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(B, &bs)); 31269566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(B, &rstart, &rend)); 31276719d8e4SJed Brown for (i = rstart; i < rend; i++) { 31286719d8e4SJed Brown const PetscScalar *ba, *ca; 31296719d8e4SJed Brown const PetscInt *bj, *cj; 31306719d8e4SJed Brown PetscInt bn, cn, j, maxentrycol = -1, maxdiffcol = -1, maxrdiffcol = -1; 31316719d8e4SJed Brown PetscReal maxentry = 0, maxdiff = 0, maxrdiff = 0; 31329566063dSJacob Faibussowitsch PetscCall(MatGetRow(B, i, &bn, &bj, &ba)); 31339566063dSJacob Faibussowitsch PetscCall(MatGetRow(Bfd, i, &cn, &cj, &ca)); 31345f80ce2aSJacob Faibussowitsch PetscCheck(bn == cn, ((PetscObject)A)->comm, PETSC_ERR_PLIB, "Unexpected different nonzero pattern in -snes_compare_coloring_threshold"); 31356719d8e4SJed Brown for (j = 0; j < bn; j++) { 31366719d8e4SJed Brown PetscReal rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j])); 31376719d8e4SJed Brown if (PetscAbsScalar(ba[j]) > PetscAbs(maxentry)) { 31386719d8e4SJed Brown maxentrycol = bj[j]; 31396719d8e4SJed Brown maxentry = PetscRealPart(ba[j]); 31406719d8e4SJed Brown } 31416719d8e4SJed Brown if (PetscAbsScalar(ca[j]) > PetscAbs(maxdiff)) { 31426719d8e4SJed Brown maxdiffcol = bj[j]; 31436719d8e4SJed Brown maxdiff = PetscRealPart(ca[j]); 31446719d8e4SJed Brown } 31456719d8e4SJed Brown if (rdiff > maxrdiff) { 31466719d8e4SJed Brown maxrdiffcol = bj[j]; 31476719d8e4SJed Brown maxrdiff = rdiff; 31486719d8e4SJed Brown } 31496719d8e4SJed Brown } 31506719d8e4SJed Brown if (maxrdiff > 1) { 315163a3b9bcSJacob 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)); 31526719d8e4SJed Brown for (j = 0; j < bn; j++) { 31536719d8e4SJed Brown PetscReal rdiff; 31546719d8e4SJed Brown rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j])); 315548a46eb9SPierre Jolivet if (rdiff > 1) PetscCall(PetscViewerASCIIPrintf(vstdout, " (%" PetscInt_FMT ",%g:%g)", bj[j], (double)PetscRealPart(ba[j]), (double)PetscRealPart(ca[j]))); 31566719d8e4SJed Brown } 315763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "\n")); 31586719d8e4SJed Brown } 31599566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(B, i, &bn, &bj, &ba)); 31609566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(Bfd, i, &cn, &cj, &ca)); 31616719d8e4SJed Brown } 31626719d8e4SJed Brown } 31639566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&vdraw)); 31649566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bfd)); 31654c30e9fbSJed Brown } 31664c30e9fbSJed Brown } 31673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 31689b94acceSBarry Smith } 31699b94acceSBarry Smith 31709b94acceSBarry Smith /*@C 31719b94acceSBarry Smith SNESSetJacobian - Sets the function to compute Jacobian as well as the 3172044dda88SLois Curfman McInnes location to store the matrix. 31739b94acceSBarry Smith 3174c3339decSBarry Smith Logically Collective 3175c7afd0dbSLois Curfman McInnes 31769b94acceSBarry Smith Input Parameters: 3177f6dfbefdSBarry Smith + snes - the `SNES` context 3178e5d3d808SBarry Smith . Amat - the matrix that defines the (approximate) Jacobian 3179dc4c0fb0SBarry Smith . Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`. 31808434afd1SBarry Smith . J - Jacobian evaluation routine (if `NULL` then `SNES` retains any previously set value), see `SNESJacobianFn` for details 3181c7afd0dbSLois Curfman McInnes - ctx - [optional] user-defined context for private data for the 3182dc4c0fb0SBarry Smith Jacobian evaluation routine (may be `NULL`) (if `NULL` then `SNES` retains any previously set value) 3183dc4c0fb0SBarry Smith 3184dc4c0fb0SBarry Smith Level: beginner 31859b94acceSBarry Smith 31869b94acceSBarry Smith Notes: 3187dc4c0fb0SBarry Smith If the `Amat` matrix and `Pmat` matrix are different you must call `MatAssemblyBegin()`/`MatAssemblyEnd()` on 318816913363SBarry Smith each matrix. 318916913363SBarry Smith 3190dc4c0fb0SBarry Smith If you know the operator `Amat` has a null space you can use `MatSetNullSpace()` and `MatSetTransposeNullSpace()` to supply the null 3191dc4c0fb0SBarry Smith space to `Amat` and the `KSP` solvers will automatically use that null space as needed during the solution process. 3192895c21f2SBarry Smith 3193dc4c0fb0SBarry Smith If using `SNESComputeJacobianDefaultColor()` to assemble a Jacobian, the `ctx` argument 3194f6dfbefdSBarry Smith must be a `MatFDColoring`. 3195a8a26c1eSJed Brown 3196c3cc8fd1SJed Brown Other defect-correction schemes can be used by computing a different matrix in place of the Jacobian. One common 3197f6dfbefdSBarry Smith example is to use the "Picard linearization" which only differentiates through the highest order parts of each term using `SNESSetPicard()` 3198c3cc8fd1SJed Brown 31991cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSPSetOperators()`, `SNESSetFunction()`, `MatMFFDComputeJacobian()`, `SNESComputeJacobianDefaultColor()`, `MatStructure`, 32008434afd1SBarry Smith `SNESSetPicard()`, `SNESJacobianFn`, `SNESFunctionFn` 32019b94acceSBarry Smith @*/ 32028434afd1SBarry Smith PetscErrorCode SNESSetJacobian(SNES snes, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx) 3203d71ae5a4SJacob Faibussowitsch { 32046cab3a1bSJed Brown DM dm; 32053a7fca6bSBarry Smith 32063a40ed3dSBarry Smith PetscFunctionBegin; 32070700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3208e5d3d808SBarry Smith if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2); 3209e5d3d808SBarry Smith if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3); 3210e5d3d808SBarry Smith if (Amat) PetscCheckSameComm(snes, 1, Amat, 2); 3211e5d3d808SBarry Smith if (Pmat) PetscCheckSameComm(snes, 1, Pmat, 3); 32129566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 32139566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, J, ctx)); 3214e5d3d808SBarry Smith if (Amat) { 32159566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)Amat)); 32169566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian)); 3217f5af7f23SKarl Rupp 3218e5d3d808SBarry Smith snes->jacobian = Amat; 32193a7fca6bSBarry Smith } 3220e5d3d808SBarry Smith if (Pmat) { 32219566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)Pmat)); 32229566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian_pre)); 3223f5af7f23SKarl Rupp 3224e5d3d808SBarry Smith snes->jacobian_pre = Pmat; 32253a7fca6bSBarry Smith } 32263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 32279b94acceSBarry Smith } 322862fef451SLois Curfman McInnes 3229c2aafc4cSSatish Balay /*@C 3230b4fd4287SBarry Smith SNESGetJacobian - Returns the Jacobian matrix and optionally the user 3231b4fd4287SBarry Smith provided context for evaluating the Jacobian. 3232b4fd4287SBarry Smith 3233420bcc1bSBarry Smith Not Collective, but `Mat` object will be parallel if `SNES` is 3234c7afd0dbSLois Curfman McInnes 3235b4fd4287SBarry Smith Input Parameter: 3236b4fd4287SBarry Smith . snes - the nonlinear solver context 3237b4fd4287SBarry Smith 3238b4fd4287SBarry Smith Output Parameters: 3239dc4c0fb0SBarry Smith + Amat - location to stash (approximate) Jacobian matrix (or `NULL`) 3240dc4c0fb0SBarry Smith . Pmat - location to stash matrix used to compute the preconditioner (or `NULL`) 32418434afd1SBarry Smith . J - location to put Jacobian function (or `NULL`), for calling sequence see `SNESJacobianFn` 3242dc4c0fb0SBarry Smith - ctx - location to stash Jacobian ctx (or `NULL`) 3243fee21e36SBarry Smith 324436851e7fSLois Curfman McInnes Level: advanced 324536851e7fSLois Curfman McInnes 32468434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `Mat`, `SNESSetJacobian()`, `SNESComputeJacobian()`, `SNESJacobianFn`, `SNESGetFunction()` 3247b4fd4287SBarry Smith @*/ 32488434afd1SBarry Smith PetscErrorCode SNESGetJacobian(SNES snes, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx) 3249d71ae5a4SJacob Faibussowitsch { 32506cab3a1bSJed Brown DM dm; 32516cab3a1bSJed Brown 32523a40ed3dSBarry Smith PetscFunctionBegin; 32530700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3254e5d3d808SBarry Smith if (Amat) *Amat = snes->jacobian; 3255e5d3d808SBarry Smith if (Pmat) *Pmat = snes->jacobian_pre; 32569566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 3257800f99ffSJeremy L Thompson PetscCall(DMSNESGetJacobian(dm, J, ctx)); 32583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3259b4fd4287SBarry Smith } 3260b4fd4287SBarry Smith 3261d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetDefaultComputeJacobian(SNES snes) 3262d71ae5a4SJacob Faibussowitsch { 326358b371f3SBarry Smith DM dm; 326458b371f3SBarry Smith DMSNES sdm; 326558b371f3SBarry Smith 326658b371f3SBarry Smith PetscFunctionBegin; 32679566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 32689566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 326958b371f3SBarry Smith if (!sdm->ops->computejacobian && snes->jacobian_pre) { 327058b371f3SBarry Smith DM dm; 327158b371f3SBarry Smith PetscBool isdense, ismf; 327258b371f3SBarry Smith 32739566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 32749566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &isdense, MATSEQDENSE, MATMPIDENSE, MATDENSE, NULL)); 32759566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &ismf, MATMFFD, MATSHELL, NULL)); 327658b371f3SBarry Smith if (isdense) { 32779566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefault, NULL)); 327858b371f3SBarry Smith } else if (!ismf) { 32799566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefaultColor, NULL)); 328058b371f3SBarry Smith } 328158b371f3SBarry Smith } 32823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 328358b371f3SBarry Smith } 328458b371f3SBarry Smith 32859b94acceSBarry Smith /*@ 32869b94acceSBarry Smith SNESSetUp - Sets up the internal data structures for the later use 3287272ac6f2SLois Curfman McInnes of a nonlinear solver. 32889b94acceSBarry Smith 3289c3339decSBarry Smith Collective 3290fee21e36SBarry Smith 32912fe279fdSBarry Smith Input Parameter: 3292f6dfbefdSBarry Smith . snes - the `SNES` context 3293c7afd0dbSLois Curfman McInnes 3294dc4c0fb0SBarry Smith Level: advanced 3295dc4c0fb0SBarry Smith 3296f6dfbefdSBarry Smith Note: 3297f6dfbefdSBarry Smith For basic use of the `SNES` solvers the user need not explicitly call 3298f6dfbefdSBarry Smith `SNESSetUp()`, since these actions will automatically occur during 3299f6dfbefdSBarry Smith the call to `SNESSolve()`. However, if one wishes to control this 3300f6dfbefdSBarry Smith phase separately, `SNESSetUp()` should be called after `SNESCreate()` 3301f6dfbefdSBarry Smith and optional routines of the form SNESSetXXX(), but before `SNESSolve()`. 3302272ac6f2SLois Curfman McInnes 33031cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`, `SNESDestroy()` 33049b94acceSBarry Smith @*/ 3305d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUp(SNES snes) 3306d71ae5a4SJacob Faibussowitsch { 33076cab3a1bSJed Brown DM dm; 3308942e3340SBarry Smith DMSNES sdm; 3309c35f09e5SBarry Smith SNESLineSearch linesearch, pclinesearch; 33106e2a1849SPeter Brune void *lsprectx, *lspostctx; 33119b5c1c08SStefano Zampini PetscBool mf_operator, mf; 33129b5c1c08SStefano Zampini Vec f, fpc; 33139b5c1c08SStefano Zampini void *funcctx; 33149b5c1c08SStefano Zampini void *jacctx, *appctx; 33159b5c1c08SStefano Zampini Mat j, jpre; 33166b2b7091SBarry Smith PetscErrorCode (*precheck)(SNESLineSearch, Vec, Vec, PetscBool *, void *); 33176b2b7091SBarry Smith PetscErrorCode (*postcheck)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *); 33188434afd1SBarry Smith SNESFunctionFn *func; 33198434afd1SBarry Smith SNESJacobianFn *jac; 33203a40ed3dSBarry Smith 33213a40ed3dSBarry Smith PetscFunctionBegin; 33220700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 33233ba16761SJacob Faibussowitsch if (snes->setupcalled) PetscFunctionReturn(PETSC_SUCCESS); 3324fc8bc0e3SRichard Tran Mills PetscCall(PetscLogEventBegin(SNES_SetUp, snes, 0, 0, 0)); 33259b94acceSBarry Smith 332648a46eb9SPierre Jolivet if (!((PetscObject)snes)->type_name) PetscCall(SNESSetType(snes, SNESNEWTONLS)); 332785385478SLisandro Dalcin 33289566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &snes->vec_func, NULL, NULL)); 332958c9b817SLisandro Dalcin 33309566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 33319566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 33329566063dSJacob Faibussowitsch PetscCall(SNESSetDefaultComputeJacobian(snes)); 333358b371f3SBarry Smith 333448a46eb9SPierre Jolivet if (!snes->vec_func) PetscCall(DMCreateGlobalVector(dm, &snes->vec_func)); 3335efd51863SBarry Smith 333648a46eb9SPierre Jolivet if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 3337b710008aSBarry Smith 3338d8d34be6SBarry Smith if (snes->linesearch) { 33399566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 33409566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetFunction(snes->linesearch, SNESComputeFunction)); 3341d8d34be6SBarry Smith } 33429e764e56SPeter Brune 33439b5c1c08SStefano Zampini PetscCall(SNESGetUseMatrixFree(snes, &mf_operator, &mf)); 3344b552625fSStefano Zampini if (snes->npc && snes->npcside == PC_LEFT) { 3345172a4300SPeter Brune snes->mf = PETSC_TRUE; 3346172a4300SPeter Brune snes->mf_operator = PETSC_FALSE; 3347172a4300SPeter Brune } 3348d8f46077SPeter Brune 3349efd4aadfSBarry Smith if (snes->npc) { 33506e2a1849SPeter Brune /* copy the DM over */ 33519566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 33529566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes->npc, dm)); 33536e2a1849SPeter Brune 33549566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &f, &func, &funcctx)); 33559566063dSJacob Faibussowitsch PetscCall(VecDuplicate(f, &fpc)); 33569566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes->npc, fpc, func, funcctx)); 33579566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, &j, &jpre, &jac, &jacctx)); 33589566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes->npc, j, jpre, jac, jacctx)); 33599566063dSJacob Faibussowitsch PetscCall(SNESGetApplicationContext(snes, &appctx)); 33609566063dSJacob Faibussowitsch PetscCall(SNESSetApplicationContext(snes->npc, appctx)); 33619b5c1c08SStefano Zampini PetscCall(SNESSetUseMatrixFree(snes->npc, mf_operator, mf)); 33629566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fpc)); 33636e2a1849SPeter Brune 33646e2a1849SPeter Brune /* copy the function pointers over */ 33659566063dSJacob Faibussowitsch PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)snes->npc)); 33666e2a1849SPeter Brune 33676e2a1849SPeter Brune /* default to 1 iteration */ 33689566063dSJacob Faibussowitsch PetscCall(SNESSetTolerances(snes->npc, 0.0, 0.0, 0.0, 1, snes->npc->max_funcs)); 3369efd4aadfSBarry Smith if (snes->npcside == PC_RIGHT) { 33709566063dSJacob Faibussowitsch PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_FINAL_ONLY)); 3371a9936a0cSPeter Brune } else { 33729566063dSJacob Faibussowitsch PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_NONE)); 3373a9936a0cSPeter Brune } 33749566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes->npc)); 33756e2a1849SPeter Brune 33766e2a1849SPeter Brune /* copy the line search context over */ 3377d8d34be6SBarry Smith if (snes->linesearch && snes->npc->linesearch) { 33789566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &linesearch)); 33799566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes->npc, &pclinesearch)); 33809566063dSJacob Faibussowitsch PetscCall(SNESLineSearchGetPreCheck(linesearch, &precheck, &lsprectx)); 33819566063dSJacob Faibussowitsch PetscCall(SNESLineSearchGetPostCheck(linesearch, &postcheck, &lspostctx)); 33829566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetPreCheck(pclinesearch, precheck, lsprectx)); 33839566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetPostCheck(pclinesearch, postcheck, lspostctx)); 33849566063dSJacob Faibussowitsch PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch)); 33856e2a1849SPeter Brune } 3386d8d34be6SBarry Smith } 33871baa6e33SBarry Smith if (snes->mf) PetscCall(SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version)); 3388*835f2295SStefano Zampini if (snes->ops->usercompute && !snes->ctx) PetscCallBack("SNES callback compute application context", (*snes->ops->usercompute)(snes, &snes->ctx)); 33896e2a1849SPeter Brune 339037ec4e1aSPeter Brune snes->jac_iter = 0; 339137ec4e1aSPeter Brune snes->pre_iter = 0; 339237ec4e1aSPeter Brune 3393dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, setup); 339458c9b817SLisandro Dalcin 33959566063dSJacob Faibussowitsch PetscCall(SNESSetDefaultComputeJacobian(snes)); 339658b371f3SBarry Smith 3397b552625fSStefano Zampini if (snes->npc && snes->npcside == PC_LEFT) { 33986c67d002SPeter Brune if (snes->functype == SNES_FUNCTION_PRECONDITIONED) { 3399d8d34be6SBarry Smith if (snes->linesearch) { 34009566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &linesearch)); 34019566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunctionDefaultNPC)); 34026c67d002SPeter Brune } 34036c67d002SPeter Brune } 3404d8d34be6SBarry Smith } 3405fc8bc0e3SRichard Tran Mills PetscCall(PetscLogEventEnd(SNES_SetUp, snes, 0, 0, 0)); 34067aaed0d8SBarry Smith snes->setupcalled = PETSC_TRUE; 34073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 34089b94acceSBarry Smith } 34099b94acceSBarry Smith 341037596af1SLisandro Dalcin /*@ 3411f6dfbefdSBarry Smith SNESReset - Resets a `SNES` context to the snessetupcalled = 0 state and removes any allocated `Vec`s and `Mat`s 341237596af1SLisandro Dalcin 3413c3339decSBarry Smith Collective 341437596af1SLisandro Dalcin 341537596af1SLisandro Dalcin Input Parameter: 3416f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 341737596af1SLisandro Dalcin 3418d25893d9SBarry Smith Level: intermediate 3419d25893d9SBarry Smith 342095452b02SPatrick Sanan Notes: 3421f6dfbefdSBarry Smith Call this if you wish to reuse a `SNES` but with different size vectors 342237596af1SLisandro Dalcin 3423f6dfbefdSBarry Smith Also calls the application context destroy routine set with `SNESSetComputeApplicationContext()` 3424f6dfbefdSBarry Smith 34251cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESDestroy()`, `SNESCreate()`, `SNESSetUp()`, `SNESSolve()` 342637596af1SLisandro Dalcin @*/ 3427d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESReset(SNES snes) 3428d71ae5a4SJacob Faibussowitsch { 342937596af1SLisandro Dalcin PetscFunctionBegin; 343037596af1SLisandro Dalcin PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 343149abdd8aSBarry Smith if (snes->ops->ctxdestroy && snes->ctx) { 3432*835f2295SStefano Zampini PetscCallBack("SNES callback destroy application context", (*snes->ops->ctxdestroy)(&snes->ctx)); 343349abdd8aSBarry Smith snes->ctx = NULL; 3434d25893d9SBarry Smith } 34351baa6e33SBarry Smith if (snes->npc) PetscCall(SNESReset(snes->npc)); 34368a23116dSBarry Smith 3437dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, reset); 34381baa6e33SBarry Smith if (snes->ksp) PetscCall(KSPReset(snes->ksp)); 34399e764e56SPeter Brune 34401baa6e33SBarry Smith if (snes->linesearch) PetscCall(SNESLineSearchReset(snes->linesearch)); 34419e764e56SPeter Brune 34429566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_rhs)); 34439566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol)); 34449566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol_update)); 34459566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_func)); 34469566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian)); 34479566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian_pre)); 34489566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->picard)); 34499566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(snes->nwork, &snes->work)); 34509566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(snes->nvwork, &snes->vwork)); 3451f5af7f23SKarl Rupp 345240fdac6aSLawrence Mitchell snes->alwayscomputesfinalresidual = PETSC_FALSE; 345340fdac6aSLawrence Mitchell 345437596af1SLisandro Dalcin snes->nwork = snes->nvwork = 0; 345537596af1SLisandro Dalcin snes->setupcalled = PETSC_FALSE; 34563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 345737596af1SLisandro Dalcin } 345837596af1SLisandro Dalcin 345952baeb72SSatish Balay /*@ 346036d43d94SBarry Smith SNESConvergedReasonViewCancel - Clears all the reason view functions for a `SNES` object provided with `SNESConvergedReasonViewSet()` also 346136d43d94SBarry Smith removes the default viewer. 3462c4421ceaSFande Kong 3463c3339decSBarry Smith Collective 3464c4421ceaSFande Kong 3465c4421ceaSFande Kong Input Parameter: 3466f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 3467c4421ceaSFande Kong 3468c4421ceaSFande Kong Level: intermediate 3469c4421ceaSFande Kong 3470420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESReset()`, `SNESConvergedReasonViewSet()` 3471c4421ceaSFande Kong @*/ 3472d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewCancel(SNES snes) 3473d71ae5a4SJacob Faibussowitsch { 3474c4421ceaSFande Kong PetscInt i; 3475c4421ceaSFande Kong 3476c4421ceaSFande Kong PetscFunctionBegin; 3477c4421ceaSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3478c4421ceaSFande Kong for (i = 0; i < snes->numberreasonviews; i++) { 347948a46eb9SPierre Jolivet if (snes->reasonviewdestroy[i]) PetscCall((*snes->reasonviewdestroy[i])(&snes->reasonviewcontext[i])); 3480c4421ceaSFande Kong } 3481c4421ceaSFande Kong snes->numberreasonviews = 0; 3482648c30bcSBarry Smith PetscCall(PetscViewerDestroy(&snes->convergedreasonviewer)); 34833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3484c4421ceaSFande Kong } 3485c4421ceaSFande Kong 34860764c050SBarry Smith /*@ 34879b94acceSBarry Smith SNESDestroy - Destroys the nonlinear solver context that was created 3488f6dfbefdSBarry Smith with `SNESCreate()`. 34899b94acceSBarry Smith 3490c3339decSBarry Smith Collective 3491c7afd0dbSLois Curfman McInnes 34929b94acceSBarry Smith Input Parameter: 3493f6dfbefdSBarry Smith . snes - the `SNES` context 34949b94acceSBarry Smith 349536851e7fSLois Curfman McInnes Level: beginner 349636851e7fSLois Curfman McInnes 34971cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()` 34989b94acceSBarry Smith @*/ 3499d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESDestroy(SNES *snes) 3500d71ae5a4SJacob Faibussowitsch { 35013a40ed3dSBarry Smith PetscFunctionBegin; 35023ba16761SJacob Faibussowitsch if (!*snes) PetscFunctionReturn(PETSC_SUCCESS); 3503f4f49eeaSPierre Jolivet PetscValidHeaderSpecific(*snes, SNES_CLASSID, 1); 3504f4f49eeaSPierre Jolivet if (--((PetscObject)*snes)->refct > 0) { 35059371c9d4SSatish Balay *snes = NULL; 35063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 35079371c9d4SSatish Balay } 3508d4bb536fSBarry Smith 3509f4f49eeaSPierre Jolivet PetscCall(SNESReset(*snes)); 35109566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&(*snes)->npc)); 35116b8b9a38SLisandro Dalcin 3512e04113cfSBarry Smith /* if memory was published with SAWs then destroy it */ 35139566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsViewOff((PetscObject)*snes)); 3514f4f49eeaSPierre Jolivet PetscTryTypeMethod(*snes, destroy); 35156d4c513bSLisandro Dalcin 35169566063dSJacob Faibussowitsch if ((*snes)->dm) PetscCall(DMCoarsenHookRemove((*snes)->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, *snes)); 35179566063dSJacob Faibussowitsch PetscCall(DMDestroy(&(*snes)->dm)); 35189566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&(*snes)->ksp)); 35199566063dSJacob Faibussowitsch PetscCall(SNESLineSearchDestroy(&(*snes)->linesearch)); 35206b8b9a38SLisandro Dalcin 35219566063dSJacob Faibussowitsch PetscCall(PetscFree((*snes)->kspconvctx)); 352248a46eb9SPierre Jolivet if ((*snes)->ops->convergeddestroy) PetscCall((*(*snes)->ops->convergeddestroy)((*snes)->cnvP)); 352348a46eb9SPierre Jolivet if ((*snes)->conv_hist_alloc) PetscCall(PetscFree2((*snes)->conv_hist, (*snes)->conv_hist_its)); 3524f4f49eeaSPierre Jolivet PetscCall(SNESMonitorCancel(*snes)); 3525f4f49eeaSPierre Jolivet PetscCall(SNESConvergedReasonViewCancel(*snes)); 35269566063dSJacob Faibussowitsch PetscCall(PetscHeaderDestroy(snes)); 35273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 35289b94acceSBarry Smith } 35299b94acceSBarry Smith 35309b94acceSBarry Smith /* ----------- Routines to set solver parameters ---------- */ 35319b94acceSBarry Smith 3532a8054027SBarry Smith /*@ 3533a8054027SBarry Smith SNESSetLagPreconditioner - Determines when the preconditioner is rebuilt in the nonlinear solve. 3534a8054027SBarry Smith 3535c3339decSBarry Smith Logically Collective 3536a8054027SBarry Smith 3537a8054027SBarry Smith Input Parameters: 3538f6dfbefdSBarry Smith + snes - the `SNES` context 3539d8e291bfSBarry Smith - lag - 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 3542a8054027SBarry Smith Options Database Keys: 3543420bcc1bSBarry Smith + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple `SNESSolve()` 35443d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 3545420bcc1bSBarry Smith . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple `SNESSolve()` 35463d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 3547a8054027SBarry Smith 3548dc4c0fb0SBarry Smith Level: intermediate 3549dc4c0fb0SBarry Smith 3550420bcc1bSBarry Smith Notes: 3551a8054027SBarry Smith The default is 1 3552420bcc1bSBarry Smith 3553f6dfbefdSBarry Smith The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagPreconditionerPersists()` was called 3554d8e291bfSBarry Smith 3555f6dfbefdSBarry Smith `SNESSetLagPreconditionerPersists()` allows using the same uniform lagging (for example every second linear solve) across multiple nonlinear solves. 3556a8054027SBarry Smith 35573201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetLagPreconditionerPersists()`, 3558f6dfbefdSBarry Smith `SNESSetLagJacobianPersists()`, `SNES`, `SNESSolve()` 3559a8054027SBarry Smith @*/ 3560d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditioner(SNES snes, PetscInt lag) 3561d71ae5a4SJacob Faibussowitsch { 3562a8054027SBarry Smith PetscFunctionBegin; 35630700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 35645f80ce2aSJacob Faibussowitsch PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater"); 35655f80ce2aSJacob Faibussowitsch PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0"); 3566c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, lag, 2); 3567a8054027SBarry Smith snes->lagpreconditioner = lag; 35683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3569a8054027SBarry Smith } 3570a8054027SBarry Smith 3571efd51863SBarry Smith /*@ 3572f6dfbefdSBarry Smith SNESSetGridSequence - sets the number of steps of grid sequencing that `SNES` will do 3573efd51863SBarry Smith 3574c3339decSBarry Smith Logically Collective 3575efd51863SBarry Smith 3576efd51863SBarry Smith Input Parameters: 3577f6dfbefdSBarry Smith + snes - the `SNES` context 3578efd51863SBarry Smith - steps - the number of refinements to do, defaults to 0 3579efd51863SBarry Smith 3580f6dfbefdSBarry Smith Options Database Key: 358167b8a455SSatish Balay . -snes_grid_sequence <steps> - Use grid sequencing to generate initial guess 3582efd51863SBarry Smith 3583efd51863SBarry Smith Level: intermediate 3584efd51863SBarry Smith 3585f6dfbefdSBarry Smith Note: 3586f6dfbefdSBarry Smith Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing. 3587c0df2a02SJed Brown 35883201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetGridSequence()`, 3589420bcc1bSBarry Smith `SNESetDM()` 3590efd51863SBarry Smith @*/ 3591d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetGridSequence(SNES snes, PetscInt steps) 3592d71ae5a4SJacob Faibussowitsch { 3593efd51863SBarry Smith PetscFunctionBegin; 3594efd51863SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3595efd51863SBarry Smith PetscValidLogicalCollectiveInt(snes, steps, 2); 3596efd51863SBarry Smith snes->gridsequence = steps; 35973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3598efd51863SBarry Smith } 3599efd51863SBarry Smith 3600fa19ca70SBarry Smith /*@ 3601f6dfbefdSBarry Smith SNESGetGridSequence - gets the number of steps of grid sequencing that `SNES` will do 3602fa19ca70SBarry Smith 3603c3339decSBarry Smith Logically Collective 3604fa19ca70SBarry Smith 3605fa19ca70SBarry Smith Input Parameter: 3606f6dfbefdSBarry Smith . snes - the `SNES` context 3607fa19ca70SBarry Smith 3608fa19ca70SBarry Smith Output Parameter: 3609fa19ca70SBarry Smith . steps - the number of refinements to do, defaults to 0 3610fa19ca70SBarry Smith 3611fa19ca70SBarry Smith Level: intermediate 3612fa19ca70SBarry Smith 36133201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetGridSequence()` 3614fa19ca70SBarry Smith @*/ 3615d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetGridSequence(SNES snes, PetscInt *steps) 3616d71ae5a4SJacob Faibussowitsch { 3617fa19ca70SBarry Smith PetscFunctionBegin; 3618fa19ca70SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3619fa19ca70SBarry Smith *steps = snes->gridsequence; 36203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3621fa19ca70SBarry Smith } 3622fa19ca70SBarry Smith 3623a8054027SBarry Smith /*@ 3624f6dfbefdSBarry Smith SNESGetLagPreconditioner - Return how often the preconditioner is rebuilt 3625a8054027SBarry Smith 36263f9fe445SBarry Smith Not Collective 3627a8054027SBarry Smith 3628a8054027SBarry Smith Input Parameter: 3629f6dfbefdSBarry Smith . snes - the `SNES` context 3630a8054027SBarry Smith 3631a8054027SBarry Smith Output Parameter: 3632a8054027SBarry 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 36333b4f5425SBarry Smith the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that 3634a8054027SBarry Smith 3635dc4c0fb0SBarry Smith Level: intermediate 3636dc4c0fb0SBarry Smith 3637a8054027SBarry Smith Notes: 3638a8054027SBarry Smith The default is 1 3639f6dfbefdSBarry Smith 3640a8054027SBarry Smith The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 3641a8054027SBarry Smith 36423201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3643a8054027SBarry Smith @*/ 3644d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagPreconditioner(SNES snes, PetscInt *lag) 3645d71ae5a4SJacob Faibussowitsch { 3646a8054027SBarry Smith PetscFunctionBegin; 36470700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3648a8054027SBarry Smith *lag = snes->lagpreconditioner; 36493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3650a8054027SBarry Smith } 3651a8054027SBarry Smith 3652e35cf81dSBarry Smith /*@ 3653f6dfbefdSBarry Smith SNESSetLagJacobian - Set when the Jacobian is rebuilt in the nonlinear solve. See `SNESSetLagPreconditioner()` for determining how 3654e35cf81dSBarry Smith often the preconditioner is rebuilt. 3655e35cf81dSBarry Smith 3656c3339decSBarry Smith Logically Collective 3657e35cf81dSBarry Smith 3658e35cf81dSBarry Smith Input Parameters: 3659f6dfbefdSBarry Smith + snes - the `SNES` context 3660e35cf81dSBarry 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 3661fe3ffe1eSBarry Smith the Jacobian is built etc. -2 means rebuild at next chance but then never again 3662e35cf81dSBarry Smith 3663e35cf81dSBarry Smith Options Database Keys: 366479a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 36653d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 366679a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 36673d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag. 3668e35cf81dSBarry Smith 3669dc4c0fb0SBarry Smith Level: intermediate 3670dc4c0fb0SBarry Smith 3671e35cf81dSBarry Smith Notes: 3672e35cf81dSBarry Smith The default is 1 3673f6dfbefdSBarry Smith 3674e35cf81dSBarry Smith The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 3675f6dfbefdSBarry Smith 3676fe3ffe1eSBarry 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 3677fe3ffe1eSBarry Smith at the next Newton step but never again (unless it is reset to another value) 3678e35cf81dSBarry Smith 36793201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagPreconditioner()`, `SNESGetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3680e35cf81dSBarry Smith @*/ 3681d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobian(SNES snes, PetscInt lag) 3682d71ae5a4SJacob Faibussowitsch { 3683e35cf81dSBarry Smith PetscFunctionBegin; 36840700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 36855f80ce2aSJacob Faibussowitsch PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater"); 36865f80ce2aSJacob Faibussowitsch PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0"); 3687c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, lag, 2); 3688e35cf81dSBarry Smith snes->lagjacobian = lag; 36893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3690e35cf81dSBarry Smith } 3691e35cf81dSBarry Smith 3692e35cf81dSBarry Smith /*@ 3693f6dfbefdSBarry Smith SNESGetLagJacobian - Get how often the Jacobian is rebuilt. See `SNESGetLagPreconditioner()` to determine when the preconditioner is rebuilt 3694e35cf81dSBarry Smith 36953f9fe445SBarry Smith Not Collective 3696e35cf81dSBarry Smith 3697e35cf81dSBarry Smith Input Parameter: 3698f6dfbefdSBarry Smith . snes - the `SNES` context 3699e35cf81dSBarry Smith 3700e35cf81dSBarry Smith Output Parameter: 3701e35cf81dSBarry 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 3702e35cf81dSBarry Smith the Jacobian is built etc. 3703e35cf81dSBarry Smith 3704dc4c0fb0SBarry Smith Level: intermediate 3705dc4c0fb0SBarry Smith 3706e35cf81dSBarry Smith Notes: 3707e35cf81dSBarry Smith The default is 1 3708f6dfbefdSBarry Smith 3709f6dfbefdSBarry Smith The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagJacobianPersists()` was called. 3710e35cf81dSBarry Smith 37113201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobian()`, `SNESSetLagPreconditioner()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3712e35cf81dSBarry Smith 3713e35cf81dSBarry Smith @*/ 3714d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagJacobian(SNES snes, PetscInt *lag) 3715d71ae5a4SJacob Faibussowitsch { 3716e35cf81dSBarry Smith PetscFunctionBegin; 37170700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3718e35cf81dSBarry Smith *lag = snes->lagjacobian; 37193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3720e35cf81dSBarry Smith } 3721e35cf81dSBarry Smith 372237ec4e1aSPeter Brune /*@ 3723f6dfbefdSBarry Smith SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple nonlinear solves 372437ec4e1aSPeter Brune 3725c3339decSBarry Smith Logically collective 372637ec4e1aSPeter Brune 3727d8d19677SJose E. Roman Input Parameters: 3728f6dfbefdSBarry Smith + snes - the `SNES` context 37299d7e2deaSPeter Brune - flg - jacobian lagging persists if true 373037ec4e1aSPeter Brune 373137ec4e1aSPeter Brune Options Database Keys: 373279a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 37333d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 373479a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 37353d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 37363d5a8a6aSBarry Smith 3737dc4c0fb0SBarry Smith Level: advanced 3738dc4c0fb0SBarry Smith 373995452b02SPatrick Sanan Notes: 3740420bcc1bSBarry Smith Normally when `SNESSetLagJacobian()` is used, the Jacobian is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior 3741f6dfbefdSBarry Smith 374295452b02SPatrick Sanan This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by 374337ec4e1aSPeter Brune several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several 374437ec4e1aSPeter Brune timesteps may present huge efficiency gains. 374537ec4e1aSPeter Brune 374642747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditionerPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()` 374737ec4e1aSPeter Brune @*/ 3748d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobianPersists(SNES snes, PetscBool flg) 3749d71ae5a4SJacob Faibussowitsch { 375037ec4e1aSPeter Brune PetscFunctionBegin; 375137ec4e1aSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 375237ec4e1aSPeter Brune PetscValidLogicalCollectiveBool(snes, flg, 2); 375337ec4e1aSPeter Brune snes->lagjac_persist = flg; 37543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 375537ec4e1aSPeter Brune } 375637ec4e1aSPeter Brune 375737ec4e1aSPeter Brune /*@ 3758d8e291bfSBarry Smith SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple nonlinear solves 375937ec4e1aSPeter Brune 3760c3339decSBarry Smith Logically Collective 376137ec4e1aSPeter Brune 3762d8d19677SJose E. Roman Input Parameters: 3763f6dfbefdSBarry Smith + snes - the `SNES` context 37649d7e2deaSPeter Brune - flg - preconditioner lagging persists if true 376537ec4e1aSPeter Brune 376637ec4e1aSPeter Brune Options Database Keys: 376779a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 37683d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 376979a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 37703d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 377137ec4e1aSPeter Brune 3772dc4c0fb0SBarry Smith Level: developer 3773dc4c0fb0SBarry Smith 377495452b02SPatrick Sanan Notes: 3775420bcc1bSBarry Smith Normally when `SNESSetLagPreconditioner()` is used, the preconditioner is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior 3776f6dfbefdSBarry Smith 377795452b02SPatrick Sanan This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale 377837ec4e1aSPeter Brune by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over 377937ec4e1aSPeter Brune several timesteps may present huge efficiency gains. 378037ec4e1aSPeter Brune 37811cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobianPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagPreconditioner()` 378237ec4e1aSPeter Brune @*/ 3783d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes, PetscBool flg) 3784d71ae5a4SJacob Faibussowitsch { 378537ec4e1aSPeter Brune PetscFunctionBegin; 378637ec4e1aSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 378737ec4e1aSPeter Brune PetscValidLogicalCollectiveBool(snes, flg, 2); 378837ec4e1aSPeter Brune snes->lagpre_persist = flg; 37893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 379037ec4e1aSPeter Brune } 379137ec4e1aSPeter Brune 37929b94acceSBarry Smith /*@ 3793f6dfbefdSBarry Smith SNESSetForceIteration - force `SNESSolve()` to take at least one iteration regardless of the initial residual norm 3794be5caee7SBarry Smith 3795c3339decSBarry Smith Logically Collective 3796be5caee7SBarry Smith 3797be5caee7SBarry Smith Input Parameters: 3798f6dfbefdSBarry Smith + snes - the `SNES` context 3799f6dfbefdSBarry Smith - force - `PETSC_TRUE` require at least one iteration 3800be5caee7SBarry Smith 3801f6dfbefdSBarry Smith Options Database Key: 3802be5caee7SBarry Smith . -snes_force_iteration <force> - Sets forcing an iteration 3803be5caee7SBarry Smith 3804dc4c0fb0SBarry Smith Level: intermediate 3805dc4c0fb0SBarry Smith 3806f6dfbefdSBarry Smith Note: 3807f6dfbefdSBarry Smith This is used sometimes with `TS` to prevent `TS` from detecting a false steady state solution 3808be5caee7SBarry Smith 38093201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `TS`, `SNESSetDivergenceTolerance()` 3810be5caee7SBarry Smith @*/ 3811d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetForceIteration(SNES snes, PetscBool force) 3812d71ae5a4SJacob Faibussowitsch { 3813be5caee7SBarry Smith PetscFunctionBegin; 3814be5caee7SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3815be5caee7SBarry Smith snes->forceiteration = force; 38163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3817be5caee7SBarry Smith } 3818be5caee7SBarry Smith 381985216dc7SFande Kong /*@ 3820f6dfbefdSBarry Smith SNESGetForceIteration - Check whether or not `SNESSolve()` take at least one iteration regardless of the initial residual norm 382185216dc7SFande Kong 3822c3339decSBarry Smith Logically Collective 382385216dc7SFande Kong 38242fe279fdSBarry Smith Input Parameter: 3825f6dfbefdSBarry Smith . snes - the `SNES` context 382685216dc7SFande Kong 382785216dc7SFande Kong Output Parameter: 3828dc4c0fb0SBarry Smith . force - `PETSC_TRUE` requires at least one iteration. 382985216dc7SFande Kong 383006dd6b0eSSatish Balay Level: intermediate 383106dd6b0eSSatish Balay 38323201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetForceIteration()`, `SNESSetDivergenceTolerance()` 383385216dc7SFande Kong @*/ 3834d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetForceIteration(SNES snes, PetscBool *force) 3835d71ae5a4SJacob Faibussowitsch { 383685216dc7SFande Kong PetscFunctionBegin; 383785216dc7SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 383885216dc7SFande Kong *force = snes->forceiteration; 38393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 384085216dc7SFande Kong } 3841be5caee7SBarry Smith 3842be5caee7SBarry Smith /*@ 3843f6dfbefdSBarry Smith SNESSetTolerances - Sets `SNES` various parameters used in convergence tests. 38449b94acceSBarry Smith 3845c3339decSBarry Smith Logically Collective 3846c7afd0dbSLois Curfman McInnes 38479b94acceSBarry Smith Input Parameters: 3848f6dfbefdSBarry Smith + snes - the `SNES` context 384970441072SBarry Smith . abstol - absolute convergence tolerance 385033174efeSLois Curfman McInnes . rtol - relative convergence tolerance 38515358d0d4SBarry Smith . stol - convergence tolerance in terms of the norm of the change in the solution between steps, || delta x || < stol*|| x || 3852f6dfbefdSBarry Smith . maxit - maximum number of iterations, default 50. 385377e5a1f9SBarry Smith - maxf - maximum number of function evaluations (use `PETSC_UNLIMITED` indicates no limit), default 10,000 3854fee21e36SBarry Smith 385533174efeSLois Curfman McInnes Options Database Keys: 385677e5a1f9SBarry Smith + -snes_atol <abstol> - Sets `abstol` 385777e5a1f9SBarry Smith . -snes_rtol <rtol> - Sets `rtol` 385877e5a1f9SBarry Smith . -snes_stol <stol> - Sets `stol` 385977e5a1f9SBarry Smith . -snes_max_it <maxit> - Sets `maxit` 386077e5a1f9SBarry Smith - -snes_max_funcs <maxf> - Sets `maxf` (use `unlimited` to have no maximum) 38619b94acceSBarry Smith 386236851e7fSLois Curfman McInnes Level: intermediate 386336851e7fSLois Curfman McInnes 386477e5a1f9SBarry Smith Note: 386577e5a1f9SBarry Smith All parameters must be non-negative 386677e5a1f9SBarry Smith 386777e5a1f9SBarry Smith Use `PETSC_CURRENT` to retain the current value of any parameter and `PETSC_DETERMINE` to use the default value for the given `SNES`. 386877e5a1f9SBarry Smith The default value is the value in the object when its type is set. 386977e5a1f9SBarry Smith 387077e5a1f9SBarry Smith Use `PETSC_UNLIMITED` on `maxit` or `maxf` to indicate there is no bound on the number of iterations or number of function evaluations. 387177e5a1f9SBarry Smith 387277e5a1f9SBarry Smith Fortran Note: 387377e5a1f9SBarry Smith Use `PETSC_CURRENT_INTEGER`, `PETSC_CURRENT_REAL`, `PETSC_UNLIMITED_INTEGER`, `PETSC_DETERMINE_INTEGER`, or `PETSC_DETERMINE_REAL` 387477e5a1f9SBarry Smith 38753201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESSolve()`, `SNES`, `SNESSetDivergenceTolerance()`, `SNESSetForceIteration()` 38769b94acceSBarry Smith @*/ 3877d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTolerances(SNES snes, PetscReal abstol, PetscReal rtol, PetscReal stol, PetscInt maxit, PetscInt maxf) 3878d71ae5a4SJacob Faibussowitsch { 38793a40ed3dSBarry Smith PetscFunctionBegin; 38800700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3881c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, abstol, 2); 3882c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, rtol, 3); 3883c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, stol, 4); 3884c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, maxit, 5); 3885c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, maxf, 6); 3886c5eb9154SBarry Smith 388777e5a1f9SBarry Smith if (abstol == (PetscReal)PETSC_DETERMINE) { 388877e5a1f9SBarry Smith snes->abstol = snes->default_abstol; 388977e5a1f9SBarry Smith } else if (abstol != (PetscReal)PETSC_CURRENT) { 38905f80ce2aSJacob Faibussowitsch PetscCheck(abstol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)abstol); 3891ab54825eSJed Brown snes->abstol = abstol; 3892ab54825eSJed Brown } 389377e5a1f9SBarry Smith 389477e5a1f9SBarry Smith if (rtol == (PetscReal)PETSC_DETERMINE) { 389577e5a1f9SBarry Smith snes->rtol = snes->default_rtol; 389677e5a1f9SBarry Smith } else if (rtol != (PetscReal)PETSC_CURRENT) { 38975f80ce2aSJacob 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); 3898ab54825eSJed Brown snes->rtol = rtol; 3899ab54825eSJed Brown } 390077e5a1f9SBarry Smith 390177e5a1f9SBarry Smith if (stol == (PetscReal)PETSC_DETERMINE) { 390277e5a1f9SBarry Smith snes->stol = snes->default_stol; 390377e5a1f9SBarry Smith } else if (stol != (PetscReal)PETSC_CURRENT) { 39045f80ce2aSJacob Faibussowitsch PetscCheck(stol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Step tolerance %g must be non-negative", (double)stol); 3905c60f73f4SPeter Brune snes->stol = stol; 3906ab54825eSJed Brown } 390777e5a1f9SBarry Smith 3908*835f2295SStefano Zampini if (maxit == PETSC_DETERMINE) { 390977e5a1f9SBarry Smith snes->max_its = snes->default_max_its; 3910*835f2295SStefano Zampini } else if (maxit == PETSC_UNLIMITED) { 391177e5a1f9SBarry Smith snes->max_its = PETSC_INT_MAX; 391277e5a1f9SBarry Smith } else if (maxit != PETSC_CURRENT) { 391363a3b9bcSJacob Faibussowitsch PetscCheck(maxit >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", maxit); 3914ab54825eSJed Brown snes->max_its = maxit; 3915ab54825eSJed Brown } 391677e5a1f9SBarry Smith 3917*835f2295SStefano Zampini if (maxf == PETSC_DETERMINE) { 391877e5a1f9SBarry Smith snes->max_funcs = snes->default_max_funcs; 3919*835f2295SStefano Zampini } else if (maxf == PETSC_UNLIMITED || maxf == -1) { 392077e5a1f9SBarry Smith snes->max_funcs = PETSC_UNLIMITED; 392177e5a1f9SBarry Smith } else if (maxf != PETSC_CURRENT) { 392277e5a1f9SBarry Smith PetscCheck(maxf >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations %" PetscInt_FMT " must be nonnegative", maxf); 3923ab54825eSJed Brown snes->max_funcs = maxf; 3924ab54825eSJed Brown } 39253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 39269b94acceSBarry Smith } 39279b94acceSBarry Smith 3928e4d06f11SPatrick Farrell /*@ 3929f6dfbefdSBarry Smith SNESSetDivergenceTolerance - Sets the divergence tolerance used for the `SNES` divergence test. 3930e4d06f11SPatrick Farrell 3931c3339decSBarry Smith Logically Collective 3932e4d06f11SPatrick Farrell 3933e4d06f11SPatrick Farrell Input Parameters: 3934f6dfbefdSBarry Smith + snes - the `SNES` context 39353201ab8dSStefano Zampini - divtol - the divergence tolerance. Use `PETSC_UNLIMITED` to deactivate the test. 3936e4d06f11SPatrick Farrell 3937f6dfbefdSBarry Smith Options Database Key: 3938dc4c0fb0SBarry Smith . -snes_divergence_tolerance <divtol> - Sets `divtol` 3939e4d06f11SPatrick Farrell 3940e4d06f11SPatrick Farrell Level: intermediate 3941e4d06f11SPatrick Farrell 394277e5a1f9SBarry Smith Notes: 394377e5a1f9SBarry Smith Use `PETSC_DETERMINE` to use the default value from when the object's type was set. 3944e5cd489fSStefano Zampini 394577e5a1f9SBarry Smith Fortran Note: 394677e5a1f9SBarry Smith Use ``PETSC_DETERMINE_REAL` or `PETSC_UNLIMITED_REAL` 394777e5a1f9SBarry Smith 394877e5a1f9SBarry Smith Developer Note: 394977e5a1f9SBarry Smith Also supports the deprecated -1 to indicate no bound on the growth of the residual 395077e5a1f9SBarry Smith 395177e5a1f9SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetTolerances()`, `SNESGetDivergenceTolerance()` 3952e4d06f11SPatrick Farrell @*/ 3953d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDivergenceTolerance(SNES snes, PetscReal divtol) 3954d71ae5a4SJacob Faibussowitsch { 3955e4d06f11SPatrick Farrell PetscFunctionBegin; 3956e4d06f11SPatrick Farrell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3957e4d06f11SPatrick Farrell PetscValidLogicalCollectiveReal(snes, divtol, 2); 395877e5a1f9SBarry Smith 395977e5a1f9SBarry Smith if (divtol == (PetscReal)PETSC_DETERMINE) { 396077e5a1f9SBarry Smith snes->divtol = snes->default_divtol; 396177e5a1f9SBarry Smith } else if (divtol == (PetscReal)PETSC_UNLIMITED || divtol == -1) { 396277e5a1f9SBarry Smith snes->divtol = PETSC_UNLIMITED; 396377e5a1f9SBarry Smith } else if (divtol != (PetscReal)PETSC_CURRENT) { 396477e5a1f9SBarry Smith PetscCheck(divtol >= 1.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Divergence tolerance %g must be greater than 1.0", (double)divtol); 396577e5a1f9SBarry Smith snes->divtol = divtol; 396677e5a1f9SBarry Smith } 39673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3968e4d06f11SPatrick Farrell } 3969e4d06f11SPatrick Farrell 39709b94acceSBarry Smith /*@ 397133174efeSLois Curfman McInnes SNESGetTolerances - Gets various parameters used in convergence tests. 397233174efeSLois Curfman McInnes 3973c7afd0dbSLois Curfman McInnes Not Collective 3974c7afd0dbSLois Curfman McInnes 397577e5a1f9SBarry Smith Input Parameter: 397677e5a1f9SBarry Smith . snes - the `SNES` context 397777e5a1f9SBarry Smith 397877e5a1f9SBarry Smith Output Parameters: 397977e5a1f9SBarry Smith + atol - absolute convergence tolerance 398033174efeSLois Curfman McInnes . rtol - relative convergence tolerance 398177e5a1f9SBarry Smith . stol - convergence tolerance in terms of the norm of the change in the solution between steps 398233174efeSLois Curfman McInnes . maxit - maximum number of iterations 398377e5a1f9SBarry Smith - maxf - maximum number of function evaluations, `PETSC_UNLIMITED` indicates no bound 3984fee21e36SBarry Smith 398536851e7fSLois Curfman McInnes Level: intermediate 398636851e7fSLois Curfman McInnes 3987dc4c0fb0SBarry Smith Note: 3988dc4c0fb0SBarry Smith The user can specify `NULL` for any parameter that is not needed. 3989dc4c0fb0SBarry Smith 39901cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTolerances()` 399133174efeSLois Curfman McInnes @*/ 3992d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetTolerances(SNES snes, PetscReal *atol, PetscReal *rtol, PetscReal *stol, PetscInt *maxit, PetscInt *maxf) 3993d71ae5a4SJacob Faibussowitsch { 39943a40ed3dSBarry Smith PetscFunctionBegin; 39950700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 399685385478SLisandro Dalcin if (atol) *atol = snes->abstol; 399733174efeSLois Curfman McInnes if (rtol) *rtol = snes->rtol; 3998c60f73f4SPeter Brune if (stol) *stol = snes->stol; 399933174efeSLois Curfman McInnes if (maxit) *maxit = snes->max_its; 400033174efeSLois Curfman McInnes if (maxf) *maxf = snes->max_funcs; 40013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 400233174efeSLois Curfman McInnes } 400333174efeSLois Curfman McInnes 4004e4d06f11SPatrick Farrell /*@ 4005e4d06f11SPatrick Farrell SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test. 4006e4d06f11SPatrick Farrell 4007e4d06f11SPatrick Farrell Not Collective 4008e4d06f11SPatrick Farrell 4009e4d06f11SPatrick Farrell Input Parameters: 4010f6dfbefdSBarry Smith + snes - the `SNES` context 4011e4d06f11SPatrick Farrell - divtol - divergence tolerance 4012e4d06f11SPatrick Farrell 4013e4d06f11SPatrick Farrell Level: intermediate 4014e4d06f11SPatrick Farrell 40151cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetDivergenceTolerance()` 4016e4d06f11SPatrick Farrell @*/ 4017d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDivergenceTolerance(SNES snes, PetscReal *divtol) 4018d71ae5a4SJacob Faibussowitsch { 4019e4d06f11SPatrick Farrell PetscFunctionBegin; 4020e4d06f11SPatrick Farrell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4021e4d06f11SPatrick Farrell if (divtol) *divtol = snes->divtol; 40223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4023e4d06f11SPatrick Farrell } 4024e4d06f11SPatrick Farrell 40256ba87a44SLisandro Dalcin PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *); 40266ba87a44SLisandro Dalcin 4027d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorLGRange(SNES snes, PetscInt n, PetscReal rnorm, void *monctx) 4028d71ae5a4SJacob Faibussowitsch { 4029b271bb04SBarry Smith PetscDrawLG lg; 4030b271bb04SBarry Smith PetscReal x, y, per; 4031b271bb04SBarry Smith PetscViewer v = (PetscViewer)monctx; 4032b271bb04SBarry Smith static PetscReal prev; /* should be in the context */ 4033b271bb04SBarry Smith PetscDraw draw; 4034b271bb04SBarry Smith 4035459f5d12SBarry Smith PetscFunctionBegin; 40364d4332d5SBarry Smith PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 4); 40379566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 0, &lg)); 40389566063dSJacob Faibussowitsch if (!n) PetscCall(PetscDrawLGReset(lg)); 40399566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 40409566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "Residual norm")); 4041b271bb04SBarry Smith x = (PetscReal)n; 404277b4d14cSPeter Brune if (rnorm > 0.0) y = PetscLog10Real(rnorm); 404394c9c6d3SKarl Rupp else y = -15.0; 40449566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 40456934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 40469566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 40479566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 4048b271bb04SBarry Smith } 4049b271bb04SBarry Smith 40509566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 1, &lg)); 40519566063dSJacob Faibussowitsch if (!n) PetscCall(PetscDrawLGReset(lg)); 40529566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 4053aaa8cc7dSPierre Jolivet PetscCall(PetscDrawSetTitle(draw, "% elements > .2*max element")); 40549566063dSJacob Faibussowitsch PetscCall(SNESMonitorRange_Private(snes, n, &per)); 4055b271bb04SBarry Smith x = (PetscReal)n; 4056b271bb04SBarry Smith y = 100.0 * per; 40579566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 40586934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 40599566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 40609566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 4061b271bb04SBarry Smith } 4062b271bb04SBarry Smith 40639566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 2, &lg)); 40649371c9d4SSatish Balay if (!n) { 40659371c9d4SSatish Balay prev = rnorm; 40669371c9d4SSatish Balay PetscCall(PetscDrawLGReset(lg)); 40679371c9d4SSatish Balay } 40689566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 40699566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm")); 4070b271bb04SBarry Smith x = (PetscReal)n; 4071b271bb04SBarry Smith y = (prev - rnorm) / prev; 40729566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 40736934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 40749566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 40759566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 4076b271bb04SBarry Smith } 4077b271bb04SBarry Smith 40789566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 3, &lg)); 40799566063dSJacob Faibussowitsch if (!n) PetscCall(PetscDrawLGReset(lg)); 40809566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 40819566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm*(% > .2 max)")); 4082b271bb04SBarry Smith x = (PetscReal)n; 4083b271bb04SBarry Smith y = (prev - rnorm) / (prev * per); 4084b271bb04SBarry Smith if (n > 2) { /*skip initial crazy value */ 40859566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 4086b271bb04SBarry Smith } 40876934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 40889566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 40899566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 4090b271bb04SBarry Smith } 4091b271bb04SBarry Smith prev = rnorm; 40923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4093b271bb04SBarry Smith } 4094b271bb04SBarry Smith 4095228d79bcSJed Brown /*@ 40962d157150SStefano Zampini SNESConverged - Run the convergence test and update the `SNESConvergedReason`. 40972d157150SStefano Zampini 40982d157150SStefano Zampini Collective 40992d157150SStefano Zampini 41002d157150SStefano Zampini Input Parameters: 41012d157150SStefano Zampini + snes - the `SNES` context 41022d157150SStefano Zampini . it - current iteration 41032d157150SStefano Zampini . xnorm - 2-norm of current iterate 41042d157150SStefano Zampini . snorm - 2-norm of current step 41052d157150SStefano Zampini - fnorm - 2-norm of function 41062d157150SStefano Zampini 41072d157150SStefano Zampini Level: developer 41082d157150SStefano Zampini 41092d157150SStefano Zampini Note: 4110420bcc1bSBarry Smith This routine is called by the `SNESSolve()` implementations. 41112d157150SStefano Zampini It does not typically need to be called by the user. 41122d157150SStefano Zampini 4113be50c303SSatish Balay .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`, `SNESGetConvergenceTest()` 41142d157150SStefano Zampini @*/ 41152d157150SStefano Zampini PetscErrorCode SNESConverged(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm) 41162d157150SStefano Zampini { 41172d157150SStefano Zampini PetscFunctionBegin; 41182d157150SStefano Zampini if (!snes->reason) { 41192d157150SStefano Zampini if (snes->normschedule == SNES_NORM_ALWAYS) PetscUseTypeMethod(snes, converged, it, xnorm, snorm, fnorm, &snes->reason, snes->cnvP); 41202d157150SStefano Zampini if (it == snes->max_its && !snes->reason) { 41212d157150SStefano Zampini if (snes->normschedule == SNES_NORM_ALWAYS) { 41222d157150SStefano Zampini PetscCall(PetscInfo(snes, "Maximum number of iterations has been reached: %" PetscInt_FMT "\n", snes->max_its)); 41232d157150SStefano Zampini snes->reason = SNES_DIVERGED_MAX_IT; 41242d157150SStefano Zampini } else snes->reason = SNES_CONVERGED_ITS; 41252d157150SStefano Zampini } 41262d157150SStefano Zampini } 41272d157150SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 41282d157150SStefano Zampini } 41292d157150SStefano Zampini 41302d157150SStefano Zampini /*@ 4131228d79bcSJed Brown SNESMonitor - runs the user provided monitor routines, if they exist 4132228d79bcSJed Brown 4133c3339decSBarry Smith Collective 4134228d79bcSJed Brown 4135228d79bcSJed Brown Input Parameters: 4136f6dfbefdSBarry Smith + snes - nonlinear solver context obtained from `SNESCreate()` 4137228d79bcSJed Brown . iter - iteration number 4138228d79bcSJed Brown - rnorm - relative norm of the residual 4139228d79bcSJed Brown 4140dc4c0fb0SBarry Smith Level: developer 4141dc4c0fb0SBarry Smith 4142f6dfbefdSBarry Smith Note: 4143420bcc1bSBarry Smith This routine is called by the `SNESSolve()` implementations. 4144228d79bcSJed Brown It does not typically need to be called by the user. 4145228d79bcSJed Brown 41461cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorSet()` 4147228d79bcSJed Brown @*/ 4148d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitor(SNES snes, PetscInt iter, PetscReal rnorm) 4149d71ae5a4SJacob Faibussowitsch { 41507a03ce2fSLisandro Dalcin PetscInt i, n = snes->numbermonitors; 41517a03ce2fSLisandro Dalcin 41527a03ce2fSLisandro Dalcin PetscFunctionBegin; 41535f3c5e7aSBarry Smith if (n > 0) SNESCheckFunctionNorm(snes, rnorm); 41549566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(snes->vec_sol)); 415548a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall((*snes->monitor[i])(snes, iter, rnorm, snes->monitorcontext[i])); 41569566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(snes->vec_sol)); 41573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 41587a03ce2fSLisandro Dalcin } 41597a03ce2fSLisandro Dalcin 41609b94acceSBarry Smith /* ------------ Routines to set performance monitoring options ----------- */ 41619b94acceSBarry Smith 4162bf388a1fSBarry Smith /*MC 4163f6dfbefdSBarry Smith SNESMonitorFunction - functional form passed to `SNESMonitorSet()` to monitor convergence of nonlinear solver 4164bf388a1fSBarry Smith 4165bf388a1fSBarry Smith Synopsis: 4166aaa7dc30SBarry Smith #include <petscsnes.h> 416737fdd005SBarry Smith PetscErrorCode SNESMonitorFunction(SNES snes, PetscInt its, PetscReal norm, void *mctx) 4168bf388a1fSBarry Smith 4169c3339decSBarry Smith Collective 41701843f636SBarry Smith 41711843f636SBarry Smith Input Parameters: 4172f6dfbefdSBarry Smith + snes - the `SNES` context 4173bf388a1fSBarry Smith . its - iteration number 4174bf388a1fSBarry Smith . norm - 2-norm function value (may be estimated) 4175bf388a1fSBarry Smith - mctx - [optional] monitoring context 4176bf388a1fSBarry Smith 4177878cb397SSatish Balay Level: advanced 4178878cb397SSatish Balay 41791cc06b55SBarry Smith .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSet()`, `SNESMonitorGet()` 4180bf388a1fSBarry Smith M*/ 4181bf388a1fSBarry Smith 41829b94acceSBarry Smith /*@C 4183a6570f20SBarry Smith SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every 41849b94acceSBarry Smith iteration of the nonlinear solver to display the iteration's 41859b94acceSBarry Smith progress. 41869b94acceSBarry Smith 4187c3339decSBarry Smith Logically Collective 4188fee21e36SBarry Smith 4189c7afd0dbSLois Curfman McInnes Input Parameters: 4190f6dfbefdSBarry Smith + snes - the `SNES` context 419120f4b53cSBarry Smith . f - the monitor function, for the calling sequence see `SNESMonitorFunction` 4192420bcc1bSBarry Smith . mctx - [optional] user-defined context for private data for the monitor routine (use `NULL` if no context is desired) 419349abdd8aSBarry Smith - monitordestroy - [optional] routine that frees monitor context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence 41949b94acceSBarry Smith 41959665c990SLois Curfman McInnes Options Database Keys: 4196f6dfbefdSBarry Smith + -snes_monitor - sets `SNESMonitorDefault()` 4197798534f6SMatthew G. Knepley . -snes_monitor draw::draw_lg - sets line graph monitor, 4198dc4c0fb0SBarry 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 4199c7afd0dbSLois Curfman McInnes the options database. 42009665c990SLois Curfman McInnes 4201dc4c0fb0SBarry Smith Level: intermediate 4202dc4c0fb0SBarry Smith 4203f6dfbefdSBarry Smith Note: 42046bc08f3fSLois Curfman McInnes Several different monitoring routines may be set by calling 4205f6dfbefdSBarry Smith `SNESMonitorSet()` multiple times; all will be called in the 42066bc08f3fSLois Curfman McInnes order in which they were set. 4207639f9d9dSBarry Smith 4208420bcc1bSBarry Smith Fortran Note: 4209f6dfbefdSBarry Smith Only a single monitor function can be set for each `SNES` object 4210025f1a04SBarry Smith 421149abdd8aSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESMonitorDefault()`, `SNESMonitorCancel()`, `SNESMonitorFunction`, `PetscCtxDestroyFn` 42129b94acceSBarry Smith @*/ 421349abdd8aSBarry Smith PetscErrorCode SNESMonitorSet(SNES snes, PetscErrorCode (*f)(SNES, PetscInt, PetscReal, void *), void *mctx, PetscCtxDestroyFn *monitordestroy) 4214d71ae5a4SJacob Faibussowitsch { 4215b90d0a6eSBarry Smith PetscInt i; 421678064530SBarry Smith PetscBool identical; 4217b90d0a6eSBarry Smith 42183a40ed3dSBarry Smith PetscFunctionBegin; 42190700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4220b90d0a6eSBarry Smith for (i = 0; i < snes->numbermonitors; i++) { 42219566063dSJacob Faibussowitsch PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))f, mctx, monitordestroy, (PetscErrorCode (*)(void))snes->monitor[i], snes->monitorcontext[i], snes->monitordestroy[i], &identical)); 42223ba16761SJacob Faibussowitsch if (identical) PetscFunctionReturn(PETSC_SUCCESS); 4223649052a6SBarry Smith } 42245f80ce2aSJacob Faibussowitsch PetscCheck(snes->numbermonitors < MAXSNESMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set"); 42256e4dcb14SBarry Smith snes->monitor[snes->numbermonitors] = f; 4226b8a78c4aSBarry Smith snes->monitordestroy[snes->numbermonitors] = monitordestroy; 4227*835f2295SStefano Zampini snes->monitorcontext[snes->numbermonitors++] = mctx; 42283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 42299b94acceSBarry Smith } 42309b94acceSBarry Smith 4231a278d85bSSatish Balay /*@ 4232f6dfbefdSBarry Smith SNESMonitorCancel - Clears all the monitor functions for a `SNES` object. 42335cd90555SBarry Smith 4234c3339decSBarry Smith Logically Collective 4235c7afd0dbSLois Curfman McInnes 42362fe279fdSBarry Smith Input Parameter: 4237f6dfbefdSBarry Smith . snes - the `SNES` context 42385cd90555SBarry Smith 42391a480d89SAdministrator Options Database Key: 4240a6570f20SBarry Smith . -snes_monitor_cancel - cancels all monitors that have been hardwired 4241dc4c0fb0SBarry Smith into a code by calls to `SNESMonitorSet()`, but does not cancel those 4242c7afd0dbSLois Curfman McInnes set via the options database 42435cd90555SBarry Smith 4244dc4c0fb0SBarry Smith Level: intermediate 4245dc4c0fb0SBarry Smith 4246f6dfbefdSBarry Smith Note: 4247f6dfbefdSBarry Smith There is no way to clear one specific monitor from a `SNES` object. 42485cd90555SBarry Smith 42491cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorGet()`, `SNESMonitorDefault()`, `SNESMonitorSet()` 42505cd90555SBarry Smith @*/ 4251d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorCancel(SNES snes) 4252d71ae5a4SJacob Faibussowitsch { 4253d952e501SBarry Smith PetscInt i; 4254d952e501SBarry Smith 42555cd90555SBarry Smith PetscFunctionBegin; 42560700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4257d952e501SBarry Smith for (i = 0; i < snes->numbermonitors; i++) { 425848a46eb9SPierre Jolivet if (snes->monitordestroy[i]) PetscCall((*snes->monitordestroy[i])(&snes->monitorcontext[i])); 4259d952e501SBarry Smith } 42605cd90555SBarry Smith snes->numbermonitors = 0; 42613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 42625cd90555SBarry Smith } 42635cd90555SBarry Smith 4264bf388a1fSBarry Smith /*MC 4265bf388a1fSBarry Smith SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver 4266bf388a1fSBarry Smith 4267bf388a1fSBarry Smith Synopsis: 4268aaa7dc30SBarry Smith #include <petscsnes.h> 426937fdd005SBarry Smith PetscErrorCode SNESConvergenceTest(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *cctx) 4270bf388a1fSBarry Smith 4271c3339decSBarry Smith Collective 42721843f636SBarry Smith 42731843f636SBarry Smith Input Parameters: 4274f6dfbefdSBarry Smith + snes - the `SNES` context 4275bf388a1fSBarry Smith . it - current iteration (0 is the first and is before any Newton step) 4276bf388a1fSBarry Smith . xnorm - 2-norm of current iterate 4277bf388a1fSBarry Smith . gnorm - 2-norm of current step 42781843f636SBarry Smith . f - 2-norm of function 42791843f636SBarry Smith - cctx - [optional] convergence context 42801843f636SBarry Smith 42811843f636SBarry Smith Output Parameter: 42821843f636SBarry Smith . reason - reason for convergence/divergence, only needs to be set when convergence or divergence is detected 4283bf388a1fSBarry Smith 4284878cb397SSatish Balay Level: intermediate 4285bf388a1fSBarry Smith 42861cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`, `SNESGetConvergenceTest()` 4287bf388a1fSBarry Smith M*/ 4288bf388a1fSBarry Smith 42899b94acceSBarry Smith /*@C 42909b94acceSBarry Smith SNESSetConvergenceTest - Sets the function that is to be used 42919b94acceSBarry Smith to test for convergence of the nonlinear iterative solution. 42929b94acceSBarry Smith 4293c3339decSBarry Smith Logically Collective 4294fee21e36SBarry Smith 4295c7afd0dbSLois Curfman McInnes Input Parameters: 4296f6dfbefdSBarry Smith + snes - the `SNES` context 4297e4094ef1SJacob Faibussowitsch . SNESConvergenceTestFunction - routine to test for convergence 4298dc4c0fb0SBarry Smith . cctx - [optional] context for private data for the convergence routine (may be `NULL`) 4299dc4c0fb0SBarry Smith - destroy - [optional] destructor for the context (may be `NULL`; `PETSC_NULL_FUNCTION` in Fortran) 43009b94acceSBarry Smith 430136851e7fSLois Curfman McInnes Level: advanced 430236851e7fSLois Curfman McInnes 43031cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedDefault()`, `SNESConvergedSkip()`, `SNESConvergenceTestFunction` 43049b94acceSBarry Smith @*/ 4305d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceTest(SNES snes, PetscErrorCode (*SNESConvergenceTestFunction)(SNES, PetscInt, PetscReal, PetscReal, PetscReal, SNESConvergedReason *, void *), void *cctx, PetscErrorCode (*destroy)(void *)) 4306d71ae5a4SJacob Faibussowitsch { 43073a40ed3dSBarry Smith PetscFunctionBegin; 43080700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4309e2a6519dSDmitry Karpeev if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip; 43101baa6e33SBarry Smith if (snes->ops->convergeddestroy) PetscCall((*snes->ops->convergeddestroy)(snes->cnvP)); 4311bf388a1fSBarry Smith snes->ops->converged = SNESConvergenceTestFunction; 43127f7931b9SBarry Smith snes->ops->convergeddestroy = destroy; 431385385478SLisandro Dalcin snes->cnvP = cctx; 43143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 43159b94acceSBarry Smith } 43169b94acceSBarry Smith 431752baeb72SSatish Balay /*@ 4318f6dfbefdSBarry Smith SNESGetConvergedReason - Gets the reason the `SNES` iteration was stopped. 4319184914b5SBarry Smith 4320184914b5SBarry Smith Not Collective 4321184914b5SBarry Smith 4322184914b5SBarry Smith Input Parameter: 4323f6dfbefdSBarry Smith . snes - the `SNES` context 4324184914b5SBarry Smith 4325184914b5SBarry Smith Output Parameter: 4326f6dfbefdSBarry Smith . reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` for the individual convergence tests for complete lists 4327184914b5SBarry Smith 4328f6dfbefdSBarry Smith Options Database Key: 43296a4d7782SBarry Smith . -snes_converged_reason - prints the reason to standard out 43306a4d7782SBarry Smith 4331184914b5SBarry Smith Level: intermediate 4332184914b5SBarry Smith 4333f6dfbefdSBarry Smith Note: 4334f6dfbefdSBarry Smith Should only be called after the call the `SNESSolve()` is complete, if it is called earlier it returns the value `SNES__CONVERGED_ITERATING`. 4335184914b5SBarry Smith 43361cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESSetConvergedReason()`, `SNESConvergedReason`, `SNESGetConvergedReasonString()` 4337184914b5SBarry Smith @*/ 4338d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReason(SNES snes, SNESConvergedReason *reason) 4339d71ae5a4SJacob Faibussowitsch { 4340184914b5SBarry Smith PetscFunctionBegin; 43410700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 43424f572ea9SToby Isaac PetscAssertPointer(reason, 2); 4343184914b5SBarry Smith *reason = snes->reason; 43443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4345184914b5SBarry Smith } 4346184914b5SBarry Smith 4347c4421ceaSFande Kong /*@C 4348f6dfbefdSBarry Smith SNESGetConvergedReasonString - Return a human readable string for `SNESConvergedReason` 4349c4421ceaSFande Kong 4350c4421ceaSFande Kong Not Collective 4351c4421ceaSFande Kong 4352c4421ceaSFande Kong Input Parameter: 4353f6dfbefdSBarry Smith . snes - the `SNES` context 4354c4421ceaSFande Kong 4355c4421ceaSFande Kong Output Parameter: 4356dc4c0fb0SBarry Smith . strreason - a human readable string that describes `SNES` converged reason 4357c4421ceaSFande Kong 435899c90e12SSatish Balay Level: beginner 4359c4421ceaSFande Kong 43601cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetConvergedReason()` 4361c4421ceaSFande Kong @*/ 4362d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReasonString(SNES snes, const char **strreason) 4363d71ae5a4SJacob Faibussowitsch { 4364c4421ceaSFande Kong PetscFunctionBegin; 4365c4421ceaSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 43664f572ea9SToby Isaac PetscAssertPointer(strreason, 2); 4367c4421ceaSFande Kong *strreason = SNESConvergedReasons[snes->reason]; 43683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4369c4421ceaSFande Kong } 4370c4421ceaSFande Kong 437133866048SMatthew G. Knepley /*@ 4372f6dfbefdSBarry Smith SNESSetConvergedReason - Sets the reason the `SNES` iteration was stopped. 437333866048SMatthew G. Knepley 437433866048SMatthew G. Knepley Not Collective 437533866048SMatthew G. Knepley 437633866048SMatthew G. Knepley Input Parameters: 4377f6dfbefdSBarry Smith + snes - the `SNES` context 4378f6dfbefdSBarry Smith - reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` or the 437933866048SMatthew G. Knepley manual pages for the individual convergence tests for complete lists 438033866048SMatthew G. Knepley 4381f6dfbefdSBarry Smith Level: developer 4382f6dfbefdSBarry Smith 4383420bcc1bSBarry Smith Developer Note: 4384f6dfbefdSBarry Smith Called inside the various `SNESSolve()` implementations 438533866048SMatthew G. Knepley 43861cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetConvergedReason()`, `SNESSetConvergenceTest()`, `SNESConvergedReason` 438733866048SMatthew G. Knepley @*/ 4388d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergedReason(SNES snes, SNESConvergedReason reason) 4389d71ae5a4SJacob Faibussowitsch { 439033866048SMatthew G. Knepley PetscFunctionBegin; 439133866048SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 43925f3c5e7aSBarry Smith PetscCheck(!snes->errorifnotconverged || reason > 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "SNES code should have previously errored due to negative reason"); 439333866048SMatthew G. Knepley snes->reason = reason; 43943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 439533866048SMatthew G. Knepley } 439633866048SMatthew G. Knepley 4397c9005455SLois Curfman McInnes /*@ 4398420bcc1bSBarry Smith SNESSetConvergenceHistory - Sets the arrays used to hold the convergence history. 4399c9005455SLois Curfman McInnes 4400c3339decSBarry Smith Logically Collective 4401fee21e36SBarry Smith 4402c7afd0dbSLois Curfman McInnes Input Parameters: 4403f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 44048c7482ecSBarry Smith . a - array to hold history, this array will contain the function norms computed at each step 4405cd5578b5SBarry Smith . its - integer array holds the number of linear iterations for each solve. 4406420bcc1bSBarry Smith . na - size of `a` and `its` 4407f6dfbefdSBarry Smith - reset - `PETSC_TRUE` indicates each new nonlinear solve resets the history counter to zero, 4408758f92a0SBarry Smith else it continues storing new values for new nonlinear solves after the old ones 4409c7afd0dbSLois Curfman McInnes 4410dc4c0fb0SBarry Smith Level: intermediate 4411dc4c0fb0SBarry Smith 4412308dcc3eSBarry Smith Notes: 441377e5a1f9SBarry Smith If 'a' and 'its' are `NULL` then space is allocated for the history. If 'na' is `PETSC_DECIDE` then a 441477e5a1f9SBarry Smith default array of length 1,000 is allocated. 4415308dcc3eSBarry Smith 4416c9005455SLois Curfman McInnes This routine is useful, e.g., when running a code for purposes 4417c9005455SLois Curfman McInnes of accurate performance monitoring, when no I/O should be done 4418c9005455SLois Curfman McInnes during the section of code that is being timed. 4419c9005455SLois Curfman McInnes 4420420bcc1bSBarry Smith If the arrays run out of space after a number of iterations then the later values are not saved in the history 4421420bcc1bSBarry Smith 44221cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetConvergenceHistory()` 4423c9005455SLois Curfman McInnes @*/ 4424d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceHistory(SNES snes, PetscReal a[], PetscInt its[], PetscInt na, PetscBool reset) 4425d71ae5a4SJacob Faibussowitsch { 44263a40ed3dSBarry Smith PetscFunctionBegin; 44270700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 44284f572ea9SToby Isaac if (a) PetscAssertPointer(a, 2); 44294f572ea9SToby Isaac if (its) PetscAssertPointer(its, 3); 44307a1ec6d4SBarry Smith if (!a) { 443177e5a1f9SBarry Smith if (na == PETSC_DECIDE) na = 1000; 44329566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(na, &a, na, &its)); 4433071fcb05SBarry Smith snes->conv_hist_alloc = PETSC_TRUE; 4434308dcc3eSBarry Smith } 4435c9005455SLois Curfman McInnes snes->conv_hist = a; 4436758f92a0SBarry Smith snes->conv_hist_its = its; 4437115dd874SBarry Smith snes->conv_hist_max = (size_t)na; 4438a12bc48fSLisandro Dalcin snes->conv_hist_len = 0; 4439758f92a0SBarry Smith snes->conv_hist_reset = reset; 44403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4441758f92a0SBarry Smith } 4442758f92a0SBarry Smith 4443d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB) 4444c6db04a5SJed Brown #include <engine.h> /* MATLAB include file */ 4445c6db04a5SJed Brown #include <mex.h> /* MATLAB include file */ 444699e0435eSBarry Smith 4447d71ae5a4SJacob Faibussowitsch PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes) 4448d71ae5a4SJacob Faibussowitsch { 4449308dcc3eSBarry Smith mxArray *mat; 4450308dcc3eSBarry Smith PetscInt i; 4451308dcc3eSBarry Smith PetscReal *ar; 4452308dcc3eSBarry Smith 4453308dcc3eSBarry Smith mat = mxCreateDoubleMatrix(snes->conv_hist_len, 1, mxREAL); 4454308dcc3eSBarry Smith ar = (PetscReal *)mxGetData(mat); 4455f5af7f23SKarl Rupp for (i = 0; i < snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i]; 445611cc89d2SBarry Smith return mat; 4457308dcc3eSBarry Smith } 4458308dcc3eSBarry Smith #endif 4459308dcc3eSBarry Smith 44600c4c9dddSBarry Smith /*@C 4461420bcc1bSBarry Smith SNESGetConvergenceHistory - Gets the arrays used to hold the convergence history. 4462758f92a0SBarry Smith 44633f9fe445SBarry Smith Not Collective 4464758f92a0SBarry Smith 4465758f92a0SBarry Smith Input Parameter: 4466f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 4467758f92a0SBarry Smith 4468758f92a0SBarry Smith Output Parameters: 4469f6dfbefdSBarry Smith + a - array to hold history, usually was set with `SNESSetConvergenceHistory()` 4470758f92a0SBarry Smith . its - integer array holds the number of linear iterations (or 4471758f92a0SBarry Smith negative if not converged) for each solve. 447220f4b53cSBarry Smith - na - size of `a` and `its` 4473758f92a0SBarry Smith 4474dc4c0fb0SBarry Smith Level: intermediate 4475dc4c0fb0SBarry Smith 447620f4b53cSBarry Smith Note: 447720f4b53cSBarry Smith This routine is useful, e.g., when running a code for purposes 447820f4b53cSBarry Smith of accurate performance monitoring, when no I/O should be done 447920f4b53cSBarry Smith during the section of code that is being timed. 448020f4b53cSBarry Smith 4481420bcc1bSBarry Smith Fortran Note: 4482758f92a0SBarry Smith The calling sequence for this routine in Fortran is 4483dc4c0fb0SBarry Smith .vb 4484dc4c0fb0SBarry Smith call SNESGetConvergenceHistory(SNES snes, integer na, integer ierr) 4485dc4c0fb0SBarry Smith .ve 4486758f92a0SBarry Smith 44871cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceHistory()` 4488758f92a0SBarry Smith @*/ 4489d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergenceHistory(SNES snes, PetscReal *a[], PetscInt *its[], PetscInt *na) 4490d71ae5a4SJacob Faibussowitsch { 4491758f92a0SBarry Smith PetscFunctionBegin; 44920700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4493758f92a0SBarry Smith if (a) *a = snes->conv_hist; 4494758f92a0SBarry Smith if (its) *its = snes->conv_hist_its; 4495115dd874SBarry Smith if (na) *na = (PetscInt)snes->conv_hist_len; 44963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4497c9005455SLois Curfman McInnes } 4498c9005455SLois Curfman McInnes 4499ac226902SBarry Smith /*@C 450076b2cf59SMatthew Knepley SNESSetUpdate - Sets the general-purpose update function called 4501eec8f646SJed Brown at the beginning of every iteration of the nonlinear solve. Specifically 450253e5d35bSStefano Zampini it is called just before the Jacobian is "evaluated" and after the function 450353e5d35bSStefano Zampini evaluation. 450476b2cf59SMatthew Knepley 4505c3339decSBarry Smith Logically Collective 450676b2cf59SMatthew Knepley 450776b2cf59SMatthew Knepley Input Parameters: 4508a2b725a8SWilliam Gropp + snes - The nonlinear solver context 450953e5d35bSStefano Zampini - func - The update function; for calling sequence see `SNESUpdateFn` 451076b2cf59SMatthew Knepley 4511fe97e370SBarry Smith Level: advanced 4512fe97e370SBarry Smith 4513420bcc1bSBarry Smith Notes: 4514f6dfbefdSBarry 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 4515f6dfbefdSBarry Smith to `SNESSetFunction()`, or `SNESSetPicard()` 451653e5d35bSStefano Zampini This is not used by most users, and it is intended to provide a general hook that is run 451753e5d35bSStefano Zampini right before the direction step is computed. 451853e5d35bSStefano Zampini Users are free to modify the current residual vector, 451953e5d35bSStefano Zampini the current linearization point, or any other vector associated to the specific solver used. 452053e5d35bSStefano Zampini If such modifications take place, it is the user responsibility to update all the relevant 452153e5d35bSStefano Zampini vectors. 452276b2cf59SMatthew Knepley 4523aaa8cc7dSPierre 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. 45246b7fb656SBarry Smith 4525e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetJacobian()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRSetPostCheck()`, 452653e5d35bSStefano Zampini `SNESMonitorSet()` 452776b2cf59SMatthew Knepley @*/ 452853e5d35bSStefano Zampini PetscErrorCode SNESSetUpdate(SNES snes, SNESUpdateFn *func) 4529d71ae5a4SJacob Faibussowitsch { 453076b2cf59SMatthew Knepley PetscFunctionBegin; 45310700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4532e7788613SBarry Smith snes->ops->update = func; 45333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 453476b2cf59SMatthew Knepley } 453576b2cf59SMatthew Knepley 4536ffeef943SBarry Smith /*@ 4537f6dfbefdSBarry Smith SNESConvergedReasonView - Displays the reason a `SNES` solve converged or diverged to a viewer 45382a359c20SBarry Smith 4539c3339decSBarry Smith Collective 45402a359c20SBarry Smith 4541e4094ef1SJacob Faibussowitsch Input Parameters: 4542f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 45432a359c20SBarry Smith - viewer - the viewer to display the reason 45442a359c20SBarry Smith 45452a359c20SBarry Smith Options Database Keys: 4546ee300463SSatish Balay + -snes_converged_reason - print reason for converged or diverged, also prints number of iterations 4547ee300463SSatish Balay - -snes_converged_reason ::failed - only print reason and number of iterations when diverged 4548eafd5ff0SAlex Lindsay 4549420bcc1bSBarry Smith Level: beginner 4550420bcc1bSBarry Smith 4551f6dfbefdSBarry Smith Note: 4552f6dfbefdSBarry Smith To change the format of the output call `PetscViewerPushFormat`(viewer,format) before this call. Use `PETSC_VIEWER_DEFAULT` for the default, 4553f6dfbefdSBarry Smith use `PETSC_VIEWER_FAILED` to only display a reason if it fails. 45542a359c20SBarry Smith 45551cc06b55SBarry Smith .seealso: [](ch_snes), `SNESConvergedReason`, `PetscViewer`, `SNES`, 4556f6dfbefdSBarry Smith `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, 4557f6dfbefdSBarry Smith `SNESConvergedReasonViewFromOptions()`, 4558db781477SPatrick Sanan `PetscViewerPushFormat()`, `PetscViewerPopFormat()` 45592a359c20SBarry Smith @*/ 4560d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonView(SNES snes, PetscViewer viewer) 4561d71ae5a4SJacob Faibussowitsch { 456275cca76cSMatthew G. Knepley PetscViewerFormat format; 45632a359c20SBarry Smith PetscBool isAscii; 45642a359c20SBarry Smith 45652a359c20SBarry Smith PetscFunctionBegin; 456619a666eeSBarry Smith if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)); 45679566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii)); 45682a359c20SBarry Smith if (isAscii) { 45699566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 457065bf60d2SBarry Smith PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel + 1)); 457175cca76cSMatthew G. Knepley if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 457275cca76cSMatthew G. Knepley DM dm; 457375cca76cSMatthew G. Knepley Vec u; 457475cca76cSMatthew G. Knepley PetscDS prob; 457575cca76cSMatthew G. Knepley PetscInt Nf, f; 457695cbbfd3SMatthew G. Knepley PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *); 457795cbbfd3SMatthew G. Knepley void **exactCtx; 457875cca76cSMatthew G. Knepley PetscReal error; 457975cca76cSMatthew G. Knepley 45809566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 45819566063dSJacob Faibussowitsch PetscCall(SNESGetSolution(snes, &u)); 45829566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob)); 45839566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(prob, &Nf)); 45849566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(Nf, &exactSol, Nf, &exactCtx)); 45859566063dSJacob Faibussowitsch for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f])); 45869566063dSJacob Faibussowitsch PetscCall(DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error)); 45879566063dSJacob Faibussowitsch PetscCall(PetscFree2(exactSol, exactCtx)); 45889566063dSJacob Faibussowitsch if (error < 1.0e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n")); 458963a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", (double)error)); 459075cca76cSMatthew G. Knepley } 4591eafd5ff0SAlex Lindsay if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) { 45922a359c20SBarry Smith if (((PetscObject)snes)->prefix) { 459363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter)); 45942a359c20SBarry Smith } else { 459563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve converged due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter)); 45962a359c20SBarry Smith } 4597eafd5ff0SAlex Lindsay } else if (snes->reason <= 0) { 45982a359c20SBarry Smith if (((PetscObject)snes)->prefix) { 459963a3b9bcSJacob 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)); 46002a359c20SBarry Smith } else { 460163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve did not converge due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter)); 46022a359c20SBarry Smith } 46032a359c20SBarry Smith } 460465bf60d2SBarry Smith PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel + 1)); 46052a359c20SBarry Smith } 46063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 46072a359c20SBarry Smith } 46082a359c20SBarry Smith 4609c4421ceaSFande Kong /*@C 4610c4421ceaSFande Kong SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the 4611aaa8cc7dSPierre Jolivet end of the nonlinear solver to display the convergence reason of the nonlinear solver. 4612c4421ceaSFande Kong 4613c3339decSBarry Smith Logically Collective 4614c4421ceaSFande Kong 4615c4421ceaSFande Kong Input Parameters: 4616f6dfbefdSBarry Smith + snes - the `SNES` context 4617420bcc1bSBarry Smith . f - the `SNESConvergedReason` view function 4618420bcc1bSBarry Smith . vctx - [optional] user-defined context for private data for the `SNESConvergedReason` view function (use `NULL` if no context is desired) 461949abdd8aSBarry Smith - reasonviewdestroy - [optional] routine that frees the context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence 4620420bcc1bSBarry Smith 4621420bcc1bSBarry Smith Calling sequence of `f`: 4622420bcc1bSBarry Smith + snes - the `SNES` context 462349abdd8aSBarry Smith - vctx - [optional] context for private data for the function 4624c4421ceaSFande Kong 4625c4421ceaSFande Kong Options Database Keys: 4626f6dfbefdSBarry Smith + -snes_converged_reason - sets a default `SNESConvergedReasonView()` 4627420bcc1bSBarry Smith - -snes_converged_reason_view_cancel - cancels all converged reason viewers that have been hardwired into a code by 4628420bcc1bSBarry Smith calls to `SNESConvergedReasonViewSet()`, but does not cancel those set via the options database. 4629c4421ceaSFande Kong 4630dc4c0fb0SBarry Smith Level: intermediate 4631dc4c0fb0SBarry Smith 4632f6dfbefdSBarry Smith Note: 4633c4421ceaSFande Kong Several different converged reason view routines may be set by calling 4634f6dfbefdSBarry Smith `SNESConvergedReasonViewSet()` multiple times; all will be called in the 4635c4421ceaSFande Kong order in which they were set. 4636c4421ceaSFande Kong 463749abdd8aSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`, `SNESConvergedReasonViewCancel()`, 463849abdd8aSBarry Smith `PetscCtxDestroyFn` 4639c4421ceaSFande Kong @*/ 464049abdd8aSBarry Smith PetscErrorCode SNESConvergedReasonViewSet(SNES snes, PetscErrorCode (*f)(SNES snes, void *vctx), void *vctx, PetscCtxDestroyFn *reasonviewdestroy) 4641d71ae5a4SJacob Faibussowitsch { 4642c4421ceaSFande Kong PetscInt i; 4643c4421ceaSFande Kong PetscBool identical; 4644c4421ceaSFande Kong 4645c4421ceaSFande Kong PetscFunctionBegin; 4646c4421ceaSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4647c4421ceaSFande Kong for (i = 0; i < snes->numberreasonviews; i++) { 46489566063dSJacob Faibussowitsch PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))f, vctx, reasonviewdestroy, (PetscErrorCode (*)(void))snes->reasonview[i], snes->reasonviewcontext[i], snes->reasonviewdestroy[i], &identical)); 46493ba16761SJacob Faibussowitsch if (identical) PetscFunctionReturn(PETSC_SUCCESS); 4650c4421ceaSFande Kong } 46515f80ce2aSJacob Faibussowitsch PetscCheck(snes->numberreasonviews < MAXSNESREASONVIEWS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many SNES reasonview set"); 4652c4421ceaSFande Kong snes->reasonview[snes->numberreasonviews] = f; 4653c4421ceaSFande Kong snes->reasonviewdestroy[snes->numberreasonviews] = reasonviewdestroy; 4654*835f2295SStefano Zampini snes->reasonviewcontext[snes->numberreasonviews++] = vctx; 46553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4656c4421ceaSFande Kong } 4657c4421ceaSFande Kong 465891f3e32bSBarry Smith /*@ 4659420bcc1bSBarry Smith SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a `SNESConvergedReason` is to be viewed at the end of `SNESSolve()` 4660c4421ceaSFande Kong All the user-provided convergedReasonView routines will be involved as well, if they exist. 46612a359c20SBarry Smith 4662c3339decSBarry Smith Collective 46632a359c20SBarry Smith 46642fe279fdSBarry Smith Input Parameter: 4665f6dfbefdSBarry Smith . snes - the `SNES` object 46662a359c20SBarry Smith 4667f6dfbefdSBarry Smith Level: advanced 46682a359c20SBarry Smith 46691cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESConvergedReasonViewSet()`, `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, 4670f6dfbefdSBarry Smith `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()` 46712a359c20SBarry Smith @*/ 4672d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes) 4673d71ae5a4SJacob Faibussowitsch { 46742a359c20SBarry Smith static PetscBool incall = PETSC_FALSE; 46752a359c20SBarry Smith 46762a359c20SBarry Smith PetscFunctionBegin; 46773ba16761SJacob Faibussowitsch if (incall) PetscFunctionReturn(PETSC_SUCCESS); 46782a359c20SBarry Smith incall = PETSC_TRUE; 4679c4421ceaSFande Kong 4680c4421ceaSFande Kong /* All user-provided viewers are called first, if they exist. */ 468136d43d94SBarry Smith for (PetscInt i = 0; i < snes->numberreasonviews; i++) PetscCall((*snes->reasonview[i])(snes, snes->reasonviewcontext[i])); 4682c4421ceaSFande Kong 4683c4421ceaSFande Kong /* Call PETSc default routine if users ask for it */ 468436d43d94SBarry Smith if (snes->convergedreasonviewer) { 468536d43d94SBarry Smith PetscCall(PetscViewerPushFormat(snes->convergedreasonviewer, snes->convergedreasonformat)); 468636d43d94SBarry Smith PetscCall(SNESConvergedReasonView(snes, snes->convergedreasonviewer)); 468736d43d94SBarry Smith PetscCall(PetscViewerPopFormat(snes->convergedreasonviewer)); 46882a359c20SBarry Smith } 46892a359c20SBarry Smith incall = PETSC_FALSE; 46903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 46912a359c20SBarry Smith } 46922a359c20SBarry Smith 4693487a658cSBarry Smith /*@ 4694f69a0ea3SMatthew Knepley SNESSolve - Solves a nonlinear system F(x) = b. 46959b94acceSBarry Smith 4696c3339decSBarry Smith Collective 4697c7afd0dbSLois Curfman McInnes 4698b2002411SLois Curfman McInnes Input Parameters: 4699f6dfbefdSBarry Smith + snes - the `SNES` context 4700dc4c0fb0SBarry Smith . b - the constant part of the equation F(x) = b, or `NULL` to use zero. 470185385478SLisandro Dalcin - x - the solution vector. 47029b94acceSBarry Smith 4703dc4c0fb0SBarry Smith Level: beginner 4704dc4c0fb0SBarry Smith 4705f6dfbefdSBarry Smith Note: 4706420bcc1bSBarry Smith The user should initialize the vector, `x`, with the initial guess 4707420bcc1bSBarry Smith for the nonlinear solve prior to calling `SNESSolve()` or use `SNESSetInitialSolution()`. In particular, 47088ddd3da0SLois Curfman McInnes to employ an initial guess of zero, the user should explicitly set 4709f6dfbefdSBarry Smith this vector to zero by calling `VecSet()`. 47108ddd3da0SLois Curfman McInnes 47111cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESSetFunction()`, `SNESSetJacobian()`, `SNESSetGridSequence()`, `SNESGetSolution()`, 4712db781477SPatrick Sanan `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRGetPreCheck()`, `SNESNewtonTRSetPostCheck()`, `SNESNewtonTRGetPostCheck()`, 4713420bcc1bSBarry Smith `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`, `SNESSetInitialSolution()` 47149b94acceSBarry Smith @*/ 4715d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSolve(SNES snes, Vec b, Vec x) 4716d71ae5a4SJacob Faibussowitsch { 4717ace3abfcSBarry Smith PetscBool flg; 4718efd51863SBarry Smith PetscInt grid; 47190298fd71SBarry Smith Vec xcreated = NULL; 4720caa4e7f2SJed Brown DM dm; 4721052efed2SBarry Smith 47223a40ed3dSBarry Smith PetscFunctionBegin; 47230700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4724a69afd8bSBarry Smith if (x) PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4725a69afd8bSBarry Smith if (x) PetscCheckSameComm(snes, 1, x, 3); 47260700a824SBarry Smith if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 472785385478SLisandro Dalcin if (b) PetscCheckSameComm(snes, 1, b, 2); 472885385478SLisandro Dalcin 472934b4d3a8SMatthew G. Knepley /* High level operations using the nonlinear solver */ 473006fc46c8SMatthew G. Knepley { 473106fc46c8SMatthew G. Knepley PetscViewer viewer; 473206fc46c8SMatthew G. Knepley PetscViewerFormat format; 47337c88af5aSMatthew G. Knepley PetscInt num; 473406fc46c8SMatthew G. Knepley PetscBool flg; 473506fc46c8SMatthew G. Knepley static PetscBool incall = PETSC_FALSE; 473606fc46c8SMatthew G. Knepley 473706fc46c8SMatthew G. Knepley if (!incall) { 473834b4d3a8SMatthew G. Knepley /* Estimate the convergence rate of the discretization */ 4739648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg)); 474006fc46c8SMatthew G. Knepley if (flg) { 474106fc46c8SMatthew G. Knepley PetscConvEst conv; 474246079b62SMatthew G. Knepley DM dm; 474346079b62SMatthew G. Knepley PetscReal *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */ 474446079b62SMatthew G. Knepley PetscInt Nf; 474506fc46c8SMatthew G. Knepley 474606fc46c8SMatthew G. Knepley incall = PETSC_TRUE; 47479566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 47489566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 47499566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(Nf, &alpha)); 47509566063dSJacob Faibussowitsch PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)snes), &conv)); 47519566063dSJacob Faibussowitsch PetscCall(PetscConvEstSetSolver(conv, (PetscObject)snes)); 47529566063dSJacob Faibussowitsch PetscCall(PetscConvEstSetFromOptions(conv)); 47539566063dSJacob Faibussowitsch PetscCall(PetscConvEstSetUp(conv)); 47549566063dSJacob Faibussowitsch PetscCall(PetscConvEstGetConvRate(conv, alpha)); 47559566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(viewer, format)); 47569566063dSJacob Faibussowitsch PetscCall(PetscConvEstRateView(conv, alpha, viewer)); 47579566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer)); 4758648c30bcSBarry Smith PetscCall(PetscViewerDestroy(&viewer)); 47599566063dSJacob Faibussowitsch PetscCall(PetscConvEstDestroy(&conv)); 47609566063dSJacob Faibussowitsch PetscCall(PetscFree(alpha)); 476106fc46c8SMatthew G. Knepley incall = PETSC_FALSE; 476206fc46c8SMatthew G. Knepley } 476334b4d3a8SMatthew G. Knepley /* Adaptively refine the initial grid */ 4764b2588ea6SMatthew G. Knepley num = 1; 47659566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_initial", &num, &flg)); 476634b4d3a8SMatthew G. Knepley if (flg) { 476734b4d3a8SMatthew G. Knepley DMAdaptor adaptor; 476834b4d3a8SMatthew G. Knepley 476934b4d3a8SMatthew G. Knepley incall = PETSC_TRUE; 47709566063dSJacob Faibussowitsch PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor)); 47719566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSolver(adaptor, snes)); 47729566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSequenceLength(adaptor, num)); 47739566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetFromOptions(adaptor)); 47749566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetUp(adaptor)); 47759566063dSJacob Faibussowitsch PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x)); 47769566063dSJacob Faibussowitsch PetscCall(DMAdaptorDestroy(&adaptor)); 477734b4d3a8SMatthew G. Knepley incall = PETSC_FALSE; 477834b4d3a8SMatthew G. Knepley } 47797c88af5aSMatthew G. Knepley /* Use grid sequencing to adapt */ 47807c88af5aSMatthew G. Knepley num = 0; 47819566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_sequence", &num, NULL)); 47827c88af5aSMatthew G. Knepley if (num) { 47837c88af5aSMatthew G. Knepley DMAdaptor adaptor; 4784e03fd340SMatthew G. Knepley const char *prefix; 47857c88af5aSMatthew G. Knepley 47867c88af5aSMatthew G. Knepley incall = PETSC_TRUE; 47879566063dSJacob Faibussowitsch PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor)); 4788e03fd340SMatthew G. Knepley PetscCall(SNESGetOptionsPrefix(snes, &prefix)); 4789e03fd340SMatthew G. Knepley PetscCall(DMAdaptorSetOptionsPrefix(adaptor, prefix)); 47909566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSolver(adaptor, snes)); 47919566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSequenceLength(adaptor, num)); 47929566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetFromOptions(adaptor)); 47939566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetUp(adaptor)); 4794e5148a0bSMatthew G. Knepley PetscCall(PetscObjectViewFromOptions((PetscObject)adaptor, NULL, "-snes_adapt_view")); 47959566063dSJacob Faibussowitsch PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x)); 47969566063dSJacob Faibussowitsch PetscCall(DMAdaptorDestroy(&adaptor)); 47977c88af5aSMatthew G. Knepley incall = PETSC_FALSE; 47987c88af5aSMatthew G. Knepley } 479906fc46c8SMatthew G. Knepley } 480006fc46c8SMatthew G. Knepley } 4801ad540459SPierre Jolivet if (!x) x = snes->vec_sol; 4802caa4e7f2SJed Brown if (!x) { 48039566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 48049566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dm, &xcreated)); 4805a69afd8bSBarry Smith x = xcreated; 4806a69afd8bSBarry Smith } 48079566063dSJacob Faibussowitsch PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view_pre")); 4808f05ece33SBarry Smith 48099566063dSJacob Faibussowitsch for (grid = 0; grid < snes->gridsequence; grid++) PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)))); 4810efd51863SBarry Smith for (grid = 0; grid < snes->gridsequence + 1; grid++) { 481185385478SLisandro Dalcin /* set solution vector */ 48129566063dSJacob Faibussowitsch if (!grid) PetscCall(PetscObjectReference((PetscObject)x)); 48139566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol)); 481485385478SLisandro Dalcin snes->vec_sol = x; 48159566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 4816caa4e7f2SJed Brown 4817caa4e7f2SJed Brown /* set affine vector if provided */ 48189566063dSJacob Faibussowitsch if (b) PetscCall(PetscObjectReference((PetscObject)b)); 48199566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_rhs)); 482085385478SLisandro Dalcin snes->vec_rhs = b; 482185385478SLisandro Dalcin 48225f80ce2aSJacob 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"); 48235f80ce2aSJacob Faibussowitsch PetscCheck(snes->vec_func != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be function vector"); 4824dd8e379bSPierre Jolivet PetscCheck(snes->vec_rhs != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be right-hand side vector"); 4825aa624791SPierre Jolivet if (!snes->vec_sol_update /* && snes->vec_sol */) PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_sol_update)); 48269566063dSJacob Faibussowitsch PetscCall(DMShellSetGlobalVector(dm, snes->vec_sol)); 48279566063dSJacob Faibussowitsch PetscCall(SNESSetUp(snes)); 48283f149594SLisandro Dalcin 48297eee914bSBarry Smith if (!grid) { 48309927e4dfSBarry Smith if (snes->ops->computeinitialguess) PetscCallBack("SNES callback compute initial guess", (*snes->ops->computeinitialguess)(snes, snes->vec_sol, snes->initialguessP)); 4831dd568438SSatish Balay } 4832d25893d9SBarry Smith 4833abc0a331SBarry Smith if (snes->conv_hist_reset) snes->conv_hist_len = 0; 483412b1dd1aSStefano Zampini PetscCall(SNESResetCounters(snes)); 48352d157150SStefano Zampini snes->reason = SNES_CONVERGED_ITERATING; 48369566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_Solve, snes, 0, 0, 0)); 4837dbbe0bcdSBarry Smith PetscUseTypeMethod(snes, solve); 48389566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_Solve, snes, 0, 0, 0)); 48392d157150SStefano Zampini PetscCheck(snes->reason, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error, solver %s returned without setting converged reason", ((PetscObject)snes)->type_name); 4840422a814eSBarry Smith snes->domainerror = PETSC_FALSE; /* clear the flag if it has been set */ 48413f149594SLisandro Dalcin 484237ec4e1aSPeter Brune if (snes->lagjac_persist) snes->jac_iter += snes->iter; 484337ec4e1aSPeter Brune if (snes->lagpre_persist) snes->pre_iter += snes->iter; 484437ec4e1aSPeter Brune 4845648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_test_local_min", NULL, NULL, &flg)); 48469566063dSJacob Faibussowitsch if (flg && !PetscPreLoadingOn) PetscCall(SNESTestLocalMin(snes)); 4847c4421ceaSFande Kong /* Call converged reason views. This may involve user-provided viewers as well */ 48489566063dSJacob Faibussowitsch PetscCall(SNESConvergedReasonViewFromOptions(snes)); 48495968eb51SBarry Smith 48505f80ce2aSJacob Faibussowitsch if (snes->errorifnotconverged) PetscCheck(snes->reason >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_NOT_CONVERGED, "SNESSolve has not converged"); 48519c8e83a9SBarry Smith if (snes->reason < 0) break; 4852efd51863SBarry Smith if (grid < snes->gridsequence) { 4853efd51863SBarry Smith DM fine; 4854efd51863SBarry Smith Vec xnew; 4855efd51863SBarry Smith Mat interp; 4856efd51863SBarry Smith 48579566063dSJacob Faibussowitsch PetscCall(DMRefine(snes->dm, PetscObjectComm((PetscObject)snes), &fine)); 48585f80ce2aSJacob Faibussowitsch PetscCheck(fine, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_INCOMP, "DMRefine() did not perform any refinement, cannot continue grid sequencing"); 48599566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(snes->dm, fine, &interp, NULL)); 48609566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(fine, &xnew)); 48619566063dSJacob Faibussowitsch PetscCall(MatInterpolate(interp, x, xnew)); 48629566063dSJacob Faibussowitsch PetscCall(DMInterpolate(snes->dm, interp, fine)); 48639566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interp)); 4864efd51863SBarry Smith x = xnew; 4865efd51863SBarry Smith 48669566063dSJacob Faibussowitsch PetscCall(SNESReset(snes)); 48679566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes, fine)); 48689566063dSJacob Faibussowitsch PetscCall(SNESResetFromOptions(snes)); 48699566063dSJacob Faibussowitsch PetscCall(DMDestroy(&fine)); 48709566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)))); 4871efd51863SBarry Smith } 4872efd51863SBarry Smith } 48739566063dSJacob Faibussowitsch PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view")); 48749566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(snes->vec_sol, (PetscObject)snes, "-snes_view_solution")); 48759566063dSJacob Faibussowitsch PetscCall(DMMonitor(snes->dm)); 48769566063dSJacob Faibussowitsch PetscCall(SNESMonitorPauseFinal_Internal(snes)); 48773f7e2da0SPeter Brune 48789566063dSJacob Faibussowitsch PetscCall(VecDestroy(&xcreated)); 48799566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsBlock((PetscObject)snes)); 48803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 48819b94acceSBarry Smith } 48829b94acceSBarry Smith 48839b94acceSBarry Smith /* --------- Internal routines for SNES Package --------- */ 48849b94acceSBarry Smith 4885cc4c1da9SBarry Smith /*@ 48864b0e389bSBarry Smith SNESSetType - Sets the method for the nonlinear solver. 48879b94acceSBarry Smith 4888c3339decSBarry Smith Collective 4889fee21e36SBarry Smith 4890c7afd0dbSLois Curfman McInnes Input Parameters: 4891f6dfbefdSBarry Smith + snes - the `SNES` context 4892454a90a3SBarry Smith - type - a known method 4893c7afd0dbSLois Curfman McInnes 4894c7afd0dbSLois Curfman McInnes Options Database Key: 4895454a90a3SBarry Smith . -snes_type <type> - Sets the method; use -help for a list 489604d7464bSBarry Smith of available methods (for instance, newtonls or newtontr) 4897ae12b187SLois Curfman McInnes 4898dc4c0fb0SBarry Smith Level: intermediate 4899dc4c0fb0SBarry Smith 49009b94acceSBarry Smith Notes: 4901e090d566SSatish Balay See "petsc/include/petscsnes.h" for available methods (for instance) 4902f6dfbefdSBarry Smith + `SNESNEWTONLS` - Newton's method with line search 4903c7afd0dbSLois Curfman McInnes (systems of nonlinear equations) 49044a221d59SStefano Zampini - `SNESNEWTONTR` - Newton's method with trust region 4905c7afd0dbSLois Curfman McInnes (systems of nonlinear equations) 49069b94acceSBarry Smith 4907f6dfbefdSBarry Smith Normally, it is best to use the `SNESSetFromOptions()` command and then 4908f6dfbefdSBarry Smith set the `SNES` solver type from the options database rather than by using 4909ae12b187SLois Curfman McInnes this routine. Using the options database provides the user with 4910ae12b187SLois Curfman McInnes maximum flexibility in evaluating the many nonlinear solvers. 4911f6dfbefdSBarry Smith The `SNESSetType()` routine is provided for those situations where it 4912ae12b187SLois Curfman McInnes is necessary to set the nonlinear solver independently of the command 4913ae12b187SLois Curfman McInnes line or options database. This might be the case, for example, when 4914ae12b187SLois Curfman McInnes the choice of solver changes during the execution of the program, 4915ae12b187SLois Curfman McInnes and the user's application is taking responsibility for choosing the 4916b0a32e0cSBarry Smith appropriate method. 491736851e7fSLois Curfman McInnes 4918420bcc1bSBarry Smith Developer Note: 4919f6dfbefdSBarry Smith `SNESRegister()` adds a constructor for a new `SNESType` to `SNESList`, `SNESSetType()` locates 4920f6dfbefdSBarry Smith the constructor in that list and calls it to create the specific object. 49218f6c3df8SBarry Smith 49221cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESType`, `SNESCreate()`, `SNESDestroy()`, `SNESGetType()`, `SNESSetFromOptions()` 49239b94acceSBarry Smith @*/ 4924d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetType(SNES snes, SNESType type) 4925d71ae5a4SJacob Faibussowitsch { 4926ace3abfcSBarry Smith PetscBool match; 49275f80ce2aSJacob Faibussowitsch PetscErrorCode (*r)(SNES); 49283a40ed3dSBarry Smith 49293a40ed3dSBarry Smith PetscFunctionBegin; 49300700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 49314f572ea9SToby Isaac PetscAssertPointer(type, 2); 493282bf6240SBarry Smith 49339566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes, type, &match)); 49343ba16761SJacob Faibussowitsch if (match) PetscFunctionReturn(PETSC_SUCCESS); 493592ff6ae8SBarry Smith 49369566063dSJacob Faibussowitsch PetscCall(PetscFunctionListFind(SNESList, type, &r)); 49376adde796SStefano Zampini PetscCheck(r, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested SNES type %s", type); 493875396ef9SLisandro Dalcin /* Destroy the previous private SNES context */ 4939dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, destroy); 494075396ef9SLisandro Dalcin /* Reinitialize function pointers in SNESOps structure */ 49419e5d0892SLisandro Dalcin snes->ops->setup = NULL; 49429e5d0892SLisandro Dalcin snes->ops->solve = NULL; 49439e5d0892SLisandro Dalcin snes->ops->view = NULL; 49449e5d0892SLisandro Dalcin snes->ops->setfromoptions = NULL; 49459e5d0892SLisandro Dalcin snes->ops->destroy = NULL; 49467fe760d5SStefano Zampini 49477fe760d5SStefano Zampini /* It may happen the user has customized the line search before calling SNESSetType */ 49489566063dSJacob Faibussowitsch if (((PetscObject)snes)->type_name) PetscCall(SNESLineSearchDestroy(&snes->linesearch)); 49497fe760d5SStefano Zampini 495075396ef9SLisandro Dalcin /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */ 495175396ef9SLisandro Dalcin snes->setupcalled = PETSC_FALSE; 4952f5af7f23SKarl Rupp 49539566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)snes, type)); 49549566063dSJacob Faibussowitsch PetscCall((*r)(snes)); 49553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49569b94acceSBarry Smith } 49579b94acceSBarry Smith 4958cc4c1da9SBarry Smith /*@ 4959f6dfbefdSBarry Smith SNESGetType - Gets the `SNES` method type and name (as a string). 49609b94acceSBarry Smith 4961c7afd0dbSLois Curfman McInnes Not Collective 4962c7afd0dbSLois Curfman McInnes 49639b94acceSBarry Smith Input Parameter: 49644b0e389bSBarry Smith . snes - nonlinear solver context 49659b94acceSBarry Smith 49669b94acceSBarry Smith Output Parameter: 4967f6dfbefdSBarry Smith . type - `SNES` method (a character string) 49689b94acceSBarry Smith 496936851e7fSLois Curfman McInnes Level: intermediate 497036851e7fSLois Curfman McInnes 49711cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetType()`, `SNESType`, `SNESSetFromOptions()`, `SNES` 49729b94acceSBarry Smith @*/ 4973d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetType(SNES snes, SNESType *type) 4974d71ae5a4SJacob Faibussowitsch { 49753a40ed3dSBarry Smith PetscFunctionBegin; 49760700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 49774f572ea9SToby Isaac PetscAssertPointer(type, 2); 49787adad957SLisandro Dalcin *type = ((PetscObject)snes)->type_name; 49793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49809b94acceSBarry Smith } 49819b94acceSBarry Smith 49823cd8a7caSMatthew G. Knepley /*@ 4983f6dfbefdSBarry Smith SNESSetSolution - Sets the solution vector for use by the `SNES` routines. 49843cd8a7caSMatthew G. Knepley 4985c3339decSBarry Smith Logically Collective 49863cd8a7caSMatthew G. Knepley 49873cd8a7caSMatthew G. Knepley Input Parameters: 4988f6dfbefdSBarry Smith + snes - the `SNES` context obtained from `SNESCreate()` 49893cd8a7caSMatthew G. Knepley - u - the solution vector 49903cd8a7caSMatthew G. Knepley 49913cd8a7caSMatthew G. Knepley Level: beginner 49923cd8a7caSMatthew G. Knepley 49931cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetSolution()`, `Vec` 49943cd8a7caSMatthew G. Knepley @*/ 4995d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetSolution(SNES snes, Vec u) 4996d71ae5a4SJacob Faibussowitsch { 49973cd8a7caSMatthew G. Knepley DM dm; 49983cd8a7caSMatthew G. Knepley 49993cd8a7caSMatthew G. Knepley PetscFunctionBegin; 50003cd8a7caSMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 50013cd8a7caSMatthew G. Knepley PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 50029566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)u)); 50039566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol)); 50043cd8a7caSMatthew G. Knepley 50053cd8a7caSMatthew G. Knepley snes->vec_sol = u; 50063cd8a7caSMatthew G. Knepley 50079566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 50089566063dSJacob Faibussowitsch PetscCall(DMShellSetGlobalVector(dm, u)); 50093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50103cd8a7caSMatthew G. Knepley } 50113cd8a7caSMatthew G. Knepley 501252baeb72SSatish Balay /*@ 50139b94acceSBarry Smith SNESGetSolution - Returns the vector where the approximate solution is 5014f6dfbefdSBarry Smith stored. This is the fine grid solution when using `SNESSetGridSequence()`. 50159b94acceSBarry Smith 5016420bcc1bSBarry Smith Not Collective, but `x` is parallel if `snes` is parallel 5017c7afd0dbSLois Curfman McInnes 50189b94acceSBarry Smith Input Parameter: 5019f6dfbefdSBarry Smith . snes - the `SNES` context 50209b94acceSBarry Smith 50219b94acceSBarry Smith Output Parameter: 50229b94acceSBarry Smith . x - the solution 50239b94acceSBarry Smith 502470e92668SMatthew Knepley Level: intermediate 502536851e7fSLois Curfman McInnes 50261cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetSolution()`, `SNESSolve()`, `SNES`, `SNESGetSolutionUpdate()`, `SNESGetFunction()` 50279b94acceSBarry Smith @*/ 5028d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolution(SNES snes, Vec *x) 5029d71ae5a4SJacob Faibussowitsch { 50303a40ed3dSBarry Smith PetscFunctionBegin; 50310700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 50324f572ea9SToby Isaac PetscAssertPointer(x, 2); 503385385478SLisandro Dalcin *x = snes->vec_sol; 50343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 503570e92668SMatthew Knepley } 503670e92668SMatthew Knepley 503752baeb72SSatish Balay /*@ 50389b94acceSBarry Smith SNESGetSolutionUpdate - Returns the vector where the solution update is 50399b94acceSBarry Smith stored. 50409b94acceSBarry Smith 5041420bcc1bSBarry Smith Not Collective, but `x` is parallel if `snes` is parallel 5042c7afd0dbSLois Curfman McInnes 50439b94acceSBarry Smith Input Parameter: 5044f6dfbefdSBarry Smith . snes - the `SNES` context 50459b94acceSBarry Smith 50469b94acceSBarry Smith Output Parameter: 50479b94acceSBarry Smith . x - the solution update 50489b94acceSBarry Smith 504936851e7fSLois Curfman McInnes Level: advanced 505036851e7fSLois Curfman McInnes 50511cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()` 50529b94acceSBarry Smith @*/ 5053d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionUpdate(SNES snes, Vec *x) 5054d71ae5a4SJacob Faibussowitsch { 50553a40ed3dSBarry Smith PetscFunctionBegin; 50560700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 50574f572ea9SToby Isaac PetscAssertPointer(x, 2); 505885385478SLisandro Dalcin *x = snes->vec_sol_update; 50593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50609b94acceSBarry Smith } 50619b94acceSBarry Smith 50629b94acceSBarry Smith /*@C 5063f6dfbefdSBarry Smith SNESGetFunction - Returns the function that defines the nonlinear system set with `SNESSetFunction()` 50649b94acceSBarry Smith 5065420bcc1bSBarry Smith Not Collective, but `r` is parallel if `snes` is parallel. Collective if `r` is requested, but has not been created yet. 5066c7afd0dbSLois Curfman McInnes 50679b94acceSBarry Smith Input Parameter: 5068f6dfbefdSBarry Smith . snes - the `SNES` context 50699b94acceSBarry Smith 5070d8d19677SJose E. Roman Output Parameters: 5071dc4c0fb0SBarry Smith + r - the vector that is used to store residuals (or `NULL` if you don't want it) 50728434afd1SBarry Smith . f - the function (or `NULL` if you don't want it); for calling sequence see `SNESFunctionFn` 5073dc4c0fb0SBarry Smith - ctx - the function context (or `NULL` if you don't want it) 50749b94acceSBarry Smith 507536851e7fSLois Curfman McInnes Level: advanced 507636851e7fSLois Curfman McInnes 5077f6dfbefdSBarry Smith Note: 5078dc4c0fb0SBarry Smith The vector `r` DOES NOT, in general, contain the current value of the `SNES` nonlinear function 507904edfde5SBarry Smith 50808434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetSolution()`, `SNESFunctionFn` 50819b94acceSBarry Smith @*/ 50828434afd1SBarry Smith PetscErrorCode SNESGetFunction(SNES snes, Vec *r, SNESFunctionFn **f, void **ctx) 5083d71ae5a4SJacob Faibussowitsch { 50846cab3a1bSJed Brown DM dm; 5085a63bb30eSJed Brown 50863a40ed3dSBarry Smith PetscFunctionBegin; 50870700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5088a63bb30eSJed Brown if (r) { 5089a63bb30eSJed Brown if (!snes->vec_func) { 5090a63bb30eSJed Brown if (snes->vec_rhs) { 50919566063dSJacob Faibussowitsch PetscCall(VecDuplicate(snes->vec_rhs, &snes->vec_func)); 5092a63bb30eSJed Brown } else if (snes->vec_sol) { 50939566063dSJacob Faibussowitsch PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_func)); 5094a63bb30eSJed Brown } else if (snes->dm) { 50959566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(snes->dm, &snes->vec_func)); 5096a63bb30eSJed Brown } 5097a63bb30eSJed Brown } 5098a63bb30eSJed Brown *r = snes->vec_func; 5099a63bb30eSJed Brown } 51009566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 51019566063dSJacob Faibussowitsch PetscCall(DMSNESGetFunction(dm, f, ctx)); 51023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 51039b94acceSBarry Smith } 51049b94acceSBarry Smith 5105c79ef259SPeter Brune /*@C 510637fdd005SBarry Smith SNESGetNGS - Returns the function and context set with `SNESSetNGS()` 5107c79ef259SPeter Brune 5108c79ef259SPeter Brune Input Parameter: 5109f6dfbefdSBarry Smith . snes - the `SNES` context 5110c79ef259SPeter Brune 5111d8d19677SJose E. Roman Output Parameters: 51128434afd1SBarry Smith + f - the function (or `NULL`) see `SNESNGSFn` for calling sequence 5113dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`) 5114c79ef259SPeter Brune 5115c79ef259SPeter Brune Level: advanced 5116c79ef259SPeter Brune 51178434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetNGS()`, `SNESGetFunction()`, `SNESNGSFn` 5118c79ef259SPeter Brune @*/ 51198434afd1SBarry Smith PetscErrorCode SNESGetNGS(SNES snes, SNESNGSFn **f, void **ctx) 5120d71ae5a4SJacob Faibussowitsch { 51216cab3a1bSJed Brown DM dm; 51226cab3a1bSJed Brown 5123646217ecSPeter Brune PetscFunctionBegin; 5124646217ecSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 51259566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 51269566063dSJacob Faibussowitsch PetscCall(DMSNESGetNGS(dm, f, ctx)); 51273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5128646217ecSPeter Brune } 5129646217ecSPeter Brune 5130cc4c1da9SBarry Smith /*@ 51313c7409f5SSatish Balay SNESSetOptionsPrefix - Sets the prefix used for searching for all 5132f6dfbefdSBarry Smith `SNES` options in the database. 51333c7409f5SSatish Balay 5134c3339decSBarry Smith Logically Collective 5135fee21e36SBarry Smith 5136d8d19677SJose E. Roman Input Parameters: 5137f6dfbefdSBarry Smith + snes - the `SNES` context 5138c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names 5139c7afd0dbSLois Curfman McInnes 5140dc4c0fb0SBarry Smith Level: advanced 5141dc4c0fb0SBarry Smith 5142f6dfbefdSBarry Smith Note: 5143a83b1b31SSatish Balay A hyphen (-) must NOT be given at the beginning of the prefix name. 5144c7afd0dbSLois Curfman McInnes The first character of all runtime options is AUTOMATICALLY the hyphen. 5145d850072dSLois Curfman McInnes 51461cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESAppendOptionsPrefix()` 51473c7409f5SSatish Balay @*/ 5148d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetOptionsPrefix(SNES snes, const char prefix[]) 5149d71ae5a4SJacob Faibussowitsch { 51503a40ed3dSBarry Smith PetscFunctionBegin; 51510700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 51529566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes, prefix)); 51539566063dSJacob Faibussowitsch if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 515435f5d045SPeter Brune if (snes->linesearch) { 51559566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 51569566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch, prefix)); 515735f5d045SPeter Brune } 51589566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(snes->ksp, prefix)); 51593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 51603c7409f5SSatish Balay } 51613c7409f5SSatish Balay 5162cc4c1da9SBarry Smith /*@ 5163f525115eSLois Curfman McInnes SNESAppendOptionsPrefix - Appends to the prefix used for searching for all 5164f6dfbefdSBarry Smith `SNES` options in the database. 51653c7409f5SSatish Balay 5166c3339decSBarry Smith Logically Collective 5167fee21e36SBarry Smith 5168c7afd0dbSLois Curfman McInnes Input Parameters: 5169f6dfbefdSBarry Smith + snes - the `SNES` context 5170c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names 5171c7afd0dbSLois Curfman McInnes 5172dc4c0fb0SBarry Smith Level: advanced 5173dc4c0fb0SBarry Smith 5174f6dfbefdSBarry Smith Note: 5175a83b1b31SSatish Balay A hyphen (-) must NOT be given at the beginning of the prefix name. 5176c7afd0dbSLois Curfman McInnes The first character of all runtime options is AUTOMATICALLY the hyphen. 5177d850072dSLois Curfman McInnes 51781cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetOptionsPrefix()`, `SNESSetOptionsPrefix()` 51793c7409f5SSatish Balay @*/ 5180d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESAppendOptionsPrefix(SNES snes, const char prefix[]) 5181d71ae5a4SJacob Faibussowitsch { 51823a40ed3dSBarry Smith PetscFunctionBegin; 51830700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 51849566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes, prefix)); 51859566063dSJacob Faibussowitsch if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 518635f5d045SPeter Brune if (snes->linesearch) { 51879566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 51889566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch, prefix)); 518935f5d045SPeter Brune } 51909566063dSJacob Faibussowitsch PetscCall(KSPAppendOptionsPrefix(snes->ksp, prefix)); 51913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 51923c7409f5SSatish Balay } 51933c7409f5SSatish Balay 5194cc4c1da9SBarry Smith /*@ 5195f6dfbefdSBarry Smith SNESGetOptionsPrefix - Gets the prefix used for searching for all 5196f6dfbefdSBarry Smith `SNES` options in the database. 51973c7409f5SSatish Balay 5198c7afd0dbSLois Curfman McInnes Not Collective 5199c7afd0dbSLois Curfman McInnes 52003c7409f5SSatish Balay Input Parameter: 5201f6dfbefdSBarry Smith . snes - the `SNES` context 52023c7409f5SSatish Balay 52033c7409f5SSatish Balay Output Parameter: 52043c7409f5SSatish Balay . prefix - pointer to the prefix string used 52053c7409f5SSatish Balay 520636851e7fSLois Curfman McInnes Level: advanced 520736851e7fSLois Curfman McInnes 5208420bcc1bSBarry Smith Fortran Note: 5209dc4c0fb0SBarry Smith The user should pass in a string 'prefix' of 5210dc4c0fb0SBarry Smith sufficient length to hold the prefix. 5211dc4c0fb0SBarry Smith 52121cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetOptionsPrefix()`, `SNESAppendOptionsPrefix()` 52133c7409f5SSatish Balay @*/ 5214d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetOptionsPrefix(SNES snes, const char *prefix[]) 5215d71ae5a4SJacob Faibussowitsch { 52163a40ed3dSBarry Smith PetscFunctionBegin; 52170700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 52189566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)snes, prefix)); 52193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 52203c7409f5SSatish Balay } 52213c7409f5SSatish Balay 52223cea93caSBarry Smith /*@C 52231c84c290SBarry Smith SNESRegister - Adds a method to the nonlinear solver package. 52241c84c290SBarry Smith 522520f4b53cSBarry Smith Not Collective 52261c84c290SBarry Smith 52271c84c290SBarry Smith Input Parameters: 522820f4b53cSBarry Smith + sname - name of a new user-defined solver 522920f4b53cSBarry Smith - function - routine to create method context 52301c84c290SBarry Smith 5231dc4c0fb0SBarry Smith Level: advanced 5232dc4c0fb0SBarry Smith 5233f6dfbefdSBarry Smith Note: 5234f6dfbefdSBarry Smith `SNESRegister()` may be called multiple times to add several user-defined solvers. 52351c84c290SBarry Smith 5236e4094ef1SJacob Faibussowitsch Example Usage: 52371c84c290SBarry Smith .vb 5238bdf89e91SBarry Smith SNESRegister("my_solver", MySolverCreate); 52391c84c290SBarry Smith .ve 52401c84c290SBarry Smith 52411c84c290SBarry Smith Then, your solver can be chosen with the procedural interface via 52421c84c290SBarry Smith $ SNESSetType(snes, "my_solver") 52431c84c290SBarry Smith or at runtime via the option 52441c84c290SBarry Smith $ -snes_type my_solver 52451c84c290SBarry Smith 52461cc06b55SBarry Smith .seealso: [](ch_snes), `SNESRegisterAll()`, `SNESRegisterDestroy()` 52473cea93caSBarry Smith @*/ 5248d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESRegister(const char sname[], PetscErrorCode (*function)(SNES)) 5249d71ae5a4SJacob Faibussowitsch { 5250b2002411SLois Curfman McInnes PetscFunctionBegin; 52519566063dSJacob Faibussowitsch PetscCall(SNESInitializePackage()); 52529566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&SNESList, sname, function)); 52533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5254b2002411SLois Curfman McInnes } 5255da9b6338SBarry Smith 5256d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestLocalMin(SNES snes) 5257d71ae5a4SJacob Faibussowitsch { 525877431f27SBarry Smith PetscInt N, i, j; 5259da9b6338SBarry Smith Vec u, uh, fh; 5260da9b6338SBarry Smith PetscScalar value; 5261da9b6338SBarry Smith PetscReal norm; 5262da9b6338SBarry Smith 5263da9b6338SBarry Smith PetscFunctionBegin; 52649566063dSJacob Faibussowitsch PetscCall(SNESGetSolution(snes, &u)); 52659566063dSJacob Faibussowitsch PetscCall(VecDuplicate(u, &uh)); 52669566063dSJacob Faibussowitsch PetscCall(VecDuplicate(u, &fh)); 5267da9b6338SBarry Smith 5268da9b6338SBarry Smith /* currently only works for sequential */ 52699566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Testing FormFunction() for local min\n")); 52709566063dSJacob Faibussowitsch PetscCall(VecGetSize(u, &N)); 5271da9b6338SBarry Smith for (i = 0; i < N; i++) { 52729566063dSJacob Faibussowitsch PetscCall(VecCopy(u, uh)); 527363a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "i = %" PetscInt_FMT "\n", i)); 5274da9b6338SBarry Smith for (j = -10; j < 11; j++) { 52758b49ba18SBarry Smith value = PetscSign(j) * PetscExpReal(PetscAbs(j) - 10.0); 52769566063dSJacob Faibussowitsch PetscCall(VecSetValue(uh, i, value, ADD_VALUES)); 52779566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, uh, fh)); 52789566063dSJacob Faibussowitsch PetscCall(VecNorm(fh, NORM_2, &norm)); 527963a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), " j norm %" PetscInt_FMT " %18.16e\n", j, (double)norm)); 5280da9b6338SBarry Smith value = -value; 52819566063dSJacob Faibussowitsch PetscCall(VecSetValue(uh, i, value, ADD_VALUES)); 5282da9b6338SBarry Smith } 5283da9b6338SBarry Smith } 52849566063dSJacob Faibussowitsch PetscCall(VecDestroy(&uh)); 52859566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fh)); 52863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5287da9b6338SBarry Smith } 528871f87433Sdalcinl 528971f87433Sdalcinl /*@ 5290f6dfbefdSBarry Smith SNESKSPSetUseEW - Sets `SNES` to the use Eisenstat-Walker method for 529171f87433Sdalcinl computing relative tolerance for linear solvers within an inexact 529271f87433Sdalcinl Newton method. 529371f87433Sdalcinl 5294c3339decSBarry Smith Logically Collective 529571f87433Sdalcinl 529671f87433Sdalcinl Input Parameters: 5297f6dfbefdSBarry Smith + snes - `SNES` context 5298f6dfbefdSBarry Smith - flag - `PETSC_TRUE` or `PETSC_FALSE` 529971f87433Sdalcinl 5300f6dfbefdSBarry Smith Options Database Keys: 530164ba62caSBarry Smith + -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence 530264ba62caSBarry Smith . -snes_ksp_ew_version ver - version of Eisenstat-Walker method 530364ba62caSBarry Smith . -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0 530464ba62caSBarry Smith . -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax 530564ba62caSBarry Smith . -snes_ksp_ew_gamma <gamma> - Sets gamma 530664ba62caSBarry Smith . -snes_ksp_ew_alpha <alpha> - Sets alpha 530764ba62caSBarry Smith . -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2 530864ba62caSBarry Smith - -snes_ksp_ew_threshold <threshold> - Sets threshold 530964ba62caSBarry Smith 5310dc4c0fb0SBarry Smith Level: advanced 5311dc4c0fb0SBarry Smith 5312f6dfbefdSBarry Smith Note: 5313f6dfbefdSBarry Smith The default is to use a constant relative tolerance for 531471f87433Sdalcinl the inner linear solvers. Alternatively, one can use the 53151d27aa22SBarry Smith Eisenstat-Walker method {cite}`ew96`, where the relative convergence tolerance 531671f87433Sdalcinl is reset at each Newton iteration according progress of the nonlinear 531771f87433Sdalcinl solver. 531871f87433Sdalcinl 53191cc06b55SBarry Smith .seealso: [](ch_snes), `KSP`, `SNES`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()` 532071f87433Sdalcinl @*/ 5321d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetUseEW(SNES snes, PetscBool flag) 5322d71ae5a4SJacob Faibussowitsch { 532371f87433Sdalcinl PetscFunctionBegin; 53240700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5325acfcf0e5SJed Brown PetscValidLogicalCollectiveBool(snes, flag, 2); 532671f87433Sdalcinl snes->ksp_ewconv = flag; 53273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 532871f87433Sdalcinl } 532971f87433Sdalcinl 533071f87433Sdalcinl /*@ 5331f6dfbefdSBarry Smith SNESKSPGetUseEW - Gets if `SNES` is using Eisenstat-Walker method 533271f87433Sdalcinl for computing relative tolerance for linear solvers within an 533371f87433Sdalcinl inexact Newton method. 533471f87433Sdalcinl 533571f87433Sdalcinl Not Collective 533671f87433Sdalcinl 533771f87433Sdalcinl Input Parameter: 5338f6dfbefdSBarry Smith . snes - `SNES` context 533971f87433Sdalcinl 534071f87433Sdalcinl Output Parameter: 5341f6dfbefdSBarry Smith . flag - `PETSC_TRUE` or `PETSC_FALSE` 534271f87433Sdalcinl 534371f87433Sdalcinl Level: advanced 534471f87433Sdalcinl 53451cc06b55SBarry Smith .seealso: [](ch_snes), `SNESKSPSetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()` 534671f87433Sdalcinl @*/ 5347d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag) 5348d71ae5a4SJacob Faibussowitsch { 534971f87433Sdalcinl PetscFunctionBegin; 53500700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 53514f572ea9SToby Isaac PetscAssertPointer(flag, 2); 535271f87433Sdalcinl *flag = snes->ksp_ewconv; 53533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 535471f87433Sdalcinl } 535571f87433Sdalcinl 535671f87433Sdalcinl /*@ 5357fa9f3622SBarry Smith SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker 535871f87433Sdalcinl convergence criteria for the linear solvers within an inexact 535971f87433Sdalcinl Newton method. 536071f87433Sdalcinl 5361c3339decSBarry Smith Logically Collective 536271f87433Sdalcinl 536371f87433Sdalcinl Input Parameters: 5364f6dfbefdSBarry Smith + snes - `SNES` context 53650f0abf79SStefano Zampini . version - version 1, 2 (default is 2), 3 or 4 536671f87433Sdalcinl . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 536771f87433Sdalcinl . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 536871f87433Sdalcinl . gamma - multiplicative factor for version 2 rtol computation 536971f87433Sdalcinl (0 <= gamma2 <= 1) 537071f87433Sdalcinl . alpha - power for version 2 rtol computation (1 < alpha <= 2) 537171f87433Sdalcinl . alpha2 - power for safeguard 537271f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1) 537371f87433Sdalcinl 5374dc4c0fb0SBarry Smith Level: advanced 5375dc4c0fb0SBarry Smith 5376f6dfbefdSBarry Smith Notes: 537771f87433Sdalcinl Version 3 was contributed by Luis Chacon, June 2006. 537871f87433Sdalcinl 537977e5a1f9SBarry Smith Use `PETSC_CURRENT` to retain the default for any of the parameters. 538071f87433Sdalcinl 53811cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()` 538271f87433Sdalcinl @*/ 5383d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetParametersEW(SNES snes, PetscInt version, PetscReal rtol_0, PetscReal rtol_max, PetscReal gamma, PetscReal alpha, PetscReal alpha2, PetscReal threshold) 5384d71ae5a4SJacob Faibussowitsch { 5385fa9f3622SBarry Smith SNESKSPEW *kctx; 53865fd66863SKarl Rupp 538771f87433Sdalcinl PetscFunctionBegin; 53880700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5389fa9f3622SBarry Smith kctx = (SNESKSPEW *)snes->kspconvctx; 53905f80ce2aSJacob Faibussowitsch PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing"); 5391c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, version, 2); 5392c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, rtol_0, 3); 5393c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, rtol_max, 4); 5394c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, gamma, 5); 5395c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, alpha, 6); 5396c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, alpha2, 7); 5397c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, threshold, 8); 539871f87433Sdalcinl 539977e5a1f9SBarry Smith if (version != PETSC_CURRENT) kctx->version = version; 540077e5a1f9SBarry Smith if (rtol_0 != (PetscReal)PETSC_CURRENT) kctx->rtol_0 = rtol_0; 540177e5a1f9SBarry Smith if (rtol_max != (PetscReal)PETSC_CURRENT) kctx->rtol_max = rtol_max; 540277e5a1f9SBarry Smith if (gamma != (PetscReal)PETSC_CURRENT) kctx->gamma = gamma; 540377e5a1f9SBarry Smith if (alpha != (PetscReal)PETSC_CURRENT) kctx->alpha = alpha; 540477e5a1f9SBarry Smith if (alpha2 != (PetscReal)PETSC_CURRENT) kctx->alpha2 = alpha2; 540577e5a1f9SBarry Smith if (threshold != (PetscReal)PETSC_CURRENT) kctx->threshold = threshold; 540671f87433Sdalcinl 54070f0abf79SStefano 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); 54080b121fc5SBarry 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); 54090b121fc5SBarry 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); 54100b121fc5SBarry 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); 54110b121fc5SBarry 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); 54120b121fc5SBarry 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); 54133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 541471f87433Sdalcinl } 541571f87433Sdalcinl 541671f87433Sdalcinl /*@ 5417fa9f3622SBarry Smith SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker 541871f87433Sdalcinl convergence criteria for the linear solvers within an inexact 541971f87433Sdalcinl Newton method. 542071f87433Sdalcinl 542171f87433Sdalcinl Not Collective 542271f87433Sdalcinl 542397bb3fdcSJose E. Roman Input Parameter: 5424f6dfbefdSBarry Smith . snes - `SNES` context 542571f87433Sdalcinl 542671f87433Sdalcinl Output Parameters: 54270f0abf79SStefano Zampini + version - version 1, 2 (default is 2), 3 or 4 542871f87433Sdalcinl . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 542971f87433Sdalcinl . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 5430bf388a1fSBarry Smith . gamma - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1) 543171f87433Sdalcinl . alpha - power for version 2 rtol computation (1 < alpha <= 2) 543271f87433Sdalcinl . alpha2 - power for safeguard 543371f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1) 543471f87433Sdalcinl 543571f87433Sdalcinl Level: advanced 543671f87433Sdalcinl 54371cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPSetParametersEW()` 543871f87433Sdalcinl @*/ 5439d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetParametersEW(SNES snes, PetscInt *version, PetscReal *rtol_0, PetscReal *rtol_max, PetscReal *gamma, PetscReal *alpha, PetscReal *alpha2, PetscReal *threshold) 5440d71ae5a4SJacob Faibussowitsch { 5441fa9f3622SBarry Smith SNESKSPEW *kctx; 54425fd66863SKarl Rupp 544371f87433Sdalcinl PetscFunctionBegin; 54440700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5445fa9f3622SBarry Smith kctx = (SNESKSPEW *)snes->kspconvctx; 54465f80ce2aSJacob Faibussowitsch PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing"); 544771f87433Sdalcinl if (version) *version = kctx->version; 544871f87433Sdalcinl if (rtol_0) *rtol_0 = kctx->rtol_0; 544971f87433Sdalcinl if (rtol_max) *rtol_max = kctx->rtol_max; 545071f87433Sdalcinl if (gamma) *gamma = kctx->gamma; 545171f87433Sdalcinl if (alpha) *alpha = kctx->alpha; 545271f87433Sdalcinl if (alpha2) *alpha2 = kctx->alpha2; 545371f87433Sdalcinl if (threshold) *threshold = kctx->threshold; 54543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 545571f87433Sdalcinl } 545671f87433Sdalcinl 54575c0db29aSPierre Jolivet PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx) 5458d71ae5a4SJacob Faibussowitsch { 54595c0db29aSPierre Jolivet SNES snes = (SNES)ctx; 5460fa9f3622SBarry Smith SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx; 546177e5a1f9SBarry Smith PetscReal rtol = PETSC_CURRENT, stol; 546271f87433Sdalcinl 546371f87433Sdalcinl PetscFunctionBegin; 54643ba16761SJacob Faibussowitsch if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS); 546530058271SDmitry Karpeev if (!snes->iter) { 546630058271SDmitry Karpeev rtol = kctx->rtol_0; /* first time in, so use the original user rtol */ 54679566063dSJacob Faibussowitsch PetscCall(VecNorm(snes->vec_func, NORM_2, &kctx->norm_first)); 54680f0abf79SStefano Zampini } else { 54690fdf79fbSJacob 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); 547071f87433Sdalcinl if (kctx->version == 1) { 54710f0abf79SStefano Zampini rtol = PetscAbsReal(snes->norm - kctx->lresid_last) / kctx->norm_last; 547285ec1a3cSBarry Smith stol = PetscPowReal(kctx->rtol_last, kctx->alpha2); 547371f87433Sdalcinl if (stol > kctx->threshold) rtol = PetscMax(rtol, stol); 547471f87433Sdalcinl } else if (kctx->version == 2) { 547585ec1a3cSBarry Smith rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha); 547685ec1a3cSBarry Smith stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha); 547771f87433Sdalcinl if (stol > kctx->threshold) rtol = PetscMax(rtol, stol); 547871f87433Sdalcinl } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */ 547985ec1a3cSBarry Smith rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha); 548071f87433Sdalcinl /* safeguard: avoid sharp decrease of rtol */ 548185ec1a3cSBarry Smith stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha); 548271f87433Sdalcinl stol = PetscMax(rtol, stol); 548371f87433Sdalcinl rtol = PetscMin(kctx->rtol_0, stol); 548471f87433Sdalcinl /* safeguard: avoid oversolving */ 548530058271SDmitry Karpeev stol = kctx->gamma * (kctx->norm_first * snes->rtol) / snes->norm; 548671f87433Sdalcinl stol = PetscMax(rtol, stol); 548771f87433Sdalcinl rtol = PetscMin(kctx->rtol_0, stol); 54880fdf79fbSJacob Faibussowitsch } else /* if (kctx->version == 4) */ { 54890fdf79fbSJacob Faibussowitsch /* H.-B. An et al. Journal of Computational and Applied Mathematics 200 (2007) 47-60 */ 54900f0abf79SStefano Zampini PetscReal ared = PetscAbsReal(kctx->norm_last - snes->norm); 54910f0abf79SStefano Zampini PetscReal pred = PetscAbsReal(kctx->norm_last - kctx->lresid_last); 54920f0abf79SStefano Zampini PetscReal rk = ared / pred; 54930f0abf79SStefano Zampini if (rk < kctx->v4_p1) rtol = 1. - 2. * kctx->v4_p1; 54940f0abf79SStefano Zampini else if (rk < kctx->v4_p2) rtol = kctx->rtol_last; 54950f0abf79SStefano Zampini else if (rk < kctx->v4_p3) rtol = kctx->v4_m1 * kctx->rtol_last; 54960f0abf79SStefano Zampini else rtol = kctx->v4_m2 * kctx->rtol_last; 54970f0abf79SStefano Zampini 5498a4598233SStefano 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; 54990f0abf79SStefano Zampini kctx->rtol_last_2 = kctx->rtol_last; 55000f0abf79SStefano Zampini kctx->rk_last_2 = kctx->rk_last; 55010f0abf79SStefano Zampini kctx->rk_last = rk; 55020fdf79fbSJacob Faibussowitsch } 55030f0abf79SStefano Zampini } 55040f0abf79SStefano Zampini /* safeguard: avoid rtol greater than rtol_max */ 550571f87433Sdalcinl rtol = PetscMin(rtol, kctx->rtol_max); 550677e5a1f9SBarry Smith PetscCall(KSPSetTolerances(ksp, rtol, PETSC_CURRENT, PETSC_CURRENT, PETSC_CURRENT)); 550763a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "iter %" PetscInt_FMT ", Eisenstat-Walker (version %" PetscInt_FMT ") KSP rtol=%g\n", snes->iter, kctx->version, (double)rtol)); 55083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 550971f87433Sdalcinl } 551071f87433Sdalcinl 55115c0db29aSPierre Jolivet PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx) 5512d71ae5a4SJacob Faibussowitsch { 55135c0db29aSPierre Jolivet SNES snes = (SNES)ctx; 5514fa9f3622SBarry Smith SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx; 551571f87433Sdalcinl PCSide pcside; 551671f87433Sdalcinl Vec lres; 551771f87433Sdalcinl 551871f87433Sdalcinl PetscFunctionBegin; 55193ba16761SJacob Faibussowitsch if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS); 55209566063dSJacob Faibussowitsch PetscCall(KSPGetTolerances(ksp, &kctx->rtol_last, NULL, NULL, NULL)); 552171dbe336SPeter Brune kctx->norm_last = snes->norm; 55220f0abf79SStefano Zampini if (kctx->version == 1 || kctx->version == 4) { 55234f00ce20SMatthew G. Knepley PC pc; 55240f0abf79SStefano Zampini PetscBool getRes; 55254f00ce20SMatthew G. Knepley 55269566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksp, &pc)); 55270f0abf79SStefano Zampini PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &getRes)); 55280f0abf79SStefano Zampini if (!getRes) { 55290f0abf79SStefano Zampini KSPNormType normtype; 55300f0abf79SStefano Zampini 55310f0abf79SStefano Zampini PetscCall(KSPGetNormType(ksp, &normtype)); 55320f0abf79SStefano Zampini getRes = (PetscBool)(normtype == KSP_NORM_UNPRECONDITIONED); 55330f0abf79SStefano Zampini } 55349566063dSJacob Faibussowitsch PetscCall(KSPGetPCSide(ksp, &pcside)); 55350f0abf79SStefano Zampini if (pcside == PC_RIGHT || getRes) { /* KSP residual is true linear residual */ 55369566063dSJacob Faibussowitsch PetscCall(KSPGetResidualNorm(ksp, &kctx->lresid_last)); 553771f87433Sdalcinl } else { 553871f87433Sdalcinl /* KSP residual is preconditioned residual */ 553971f87433Sdalcinl /* compute true linear residual norm */ 55400f0abf79SStefano Zampini Mat J; 55410f0abf79SStefano Zampini PetscCall(KSPGetOperators(ksp, &J, NULL)); 55429566063dSJacob Faibussowitsch PetscCall(VecDuplicate(b, &lres)); 55430f0abf79SStefano Zampini PetscCall(MatMult(J, x, lres)); 55449566063dSJacob Faibussowitsch PetscCall(VecAYPX(lres, -1.0, b)); 55459566063dSJacob Faibussowitsch PetscCall(VecNorm(lres, NORM_2, &kctx->lresid_last)); 55469566063dSJacob Faibussowitsch PetscCall(VecDestroy(&lres)); 554771f87433Sdalcinl } 554871f87433Sdalcinl } 55493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 555071f87433Sdalcinl } 555171f87433Sdalcinl 5552d4211eb9SBarry Smith /*@ 5553f6dfbefdSBarry Smith SNESGetKSP - Returns the `KSP` context for a `SNES` solver. 5554d4211eb9SBarry Smith 5555420bcc1bSBarry Smith Not Collective, but if `snes` is parallel, then `ksp` is parallel 5556d4211eb9SBarry Smith 5557d4211eb9SBarry Smith Input Parameter: 5558f6dfbefdSBarry Smith . snes - the `SNES` context 5559d4211eb9SBarry Smith 5560d4211eb9SBarry Smith Output Parameter: 5561f6dfbefdSBarry Smith . ksp - the `KSP` context 5562d4211eb9SBarry Smith 5563dc4c0fb0SBarry Smith Level: beginner 5564dc4c0fb0SBarry Smith 5565d4211eb9SBarry Smith Notes: 5566f6dfbefdSBarry Smith The user can then directly manipulate the `KSP` context to set various 5567d4211eb9SBarry Smith options, etc. Likewise, the user can then extract and manipulate the 5568f6dfbefdSBarry Smith `PC` contexts as well. 5569f6dfbefdSBarry Smith 5570f6dfbefdSBarry Smith Some `SNESType`s do not use a `KSP` but a `KSP` is still returned by this function 5571d4211eb9SBarry Smith 55721cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSP`, `PC`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()` 5573d4211eb9SBarry Smith @*/ 5574d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetKSP(SNES snes, KSP *ksp) 5575d71ae5a4SJacob Faibussowitsch { 557671f87433Sdalcinl PetscFunctionBegin; 5577d4211eb9SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 55784f572ea9SToby Isaac PetscAssertPointer(ksp, 2); 5579d4211eb9SBarry Smith 5580d4211eb9SBarry Smith if (!snes->ksp) { 55819566063dSJacob Faibussowitsch PetscCall(KSPCreate(PetscObjectComm((PetscObject)snes), &snes->ksp)); 55829566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->ksp, (PetscObject)snes, 1)); 5583d4211eb9SBarry Smith 55845c0db29aSPierre Jolivet PetscCall(KSPSetPreSolve(snes->ksp, KSPPreSolve_SNESEW, snes)); 55855c0db29aSPierre Jolivet PetscCall(KSPSetPostSolve(snes->ksp, KSPPostSolve_SNESEW, snes)); 5586a5c2985bSBarry Smith 55879566063dSJacob Faibussowitsch PetscCall(KSPMonitorSetFromOptions(snes->ksp, "-snes_monitor_ksp", "snes_preconditioned_residual", snes)); 55889566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptions((PetscObject)snes->ksp, ((PetscObject)snes)->options)); 5589d4211eb9SBarry Smith } 5590d4211eb9SBarry Smith *ksp = snes->ksp; 55913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 559271f87433Sdalcinl } 55936c699258SBarry Smith 5594af0996ceSBarry Smith #include <petsc/private/dmimpl.h> 55956c699258SBarry Smith /*@ 5596f6dfbefdSBarry Smith SNESSetDM - Sets the `DM` that may be used by some nonlinear solvers or their underlying preconditioners 55976c699258SBarry Smith 5598c3339decSBarry Smith Logically Collective 55996c699258SBarry Smith 56006c699258SBarry Smith Input Parameters: 56012a808120SBarry Smith + snes - the nonlinear solver context 5602420bcc1bSBarry Smith - dm - the `DM`, cannot be `NULL` 5603dc4c0fb0SBarry Smith 5604dc4c0fb0SBarry Smith Level: intermediate 56056c699258SBarry Smith 5606f6dfbefdSBarry Smith Note: 5607f6dfbefdSBarry Smith A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`, 5608f6dfbefdSBarry Smith even when not using interfaces like `DMSNESSetFunction()`. Use `DMClone()` to get a distinct `DM` when solving different 5609e03a659cSJed Brown problems using the same function space. 5610e03a659cSJed Brown 5611420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()` 56126c699258SBarry Smith @*/ 5613d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDM(SNES snes, DM dm) 5614d71ae5a4SJacob Faibussowitsch { 5615345fed2cSBarry Smith KSP ksp; 5616942e3340SBarry Smith DMSNES sdm; 56176c699258SBarry Smith 56186c699258SBarry Smith PetscFunctionBegin; 56190700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 56202a808120SBarry Smith PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 56219566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 5622942e3340SBarry Smith if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */ 562351f4b3c7SToby Isaac if (snes->dm->dmsnes && !dm->dmsnes) { 56249566063dSJacob Faibussowitsch PetscCall(DMCopyDMSNES(snes->dm, dm)); 56259566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(snes->dm, &sdm)); 5626f5af7f23SKarl Rupp if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */ 56276cab3a1bSJed Brown } 56289566063dSJacob Faibussowitsch PetscCall(DMCoarsenHookRemove(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes)); 56299566063dSJacob Faibussowitsch PetscCall(DMDestroy(&snes->dm)); 56306cab3a1bSJed Brown } 56316c699258SBarry Smith snes->dm = dm; 5632116d1032SJed Brown snes->dmAuto = PETSC_FALSE; 5633f5af7f23SKarl Rupp 56349566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 56359566063dSJacob Faibussowitsch PetscCall(KSPSetDM(ksp, dm)); 56369566063dSJacob Faibussowitsch PetscCall(KSPSetDMActive(ksp, PETSC_FALSE)); 5637efd4aadfSBarry Smith if (snes->npc) { 56389566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes->npc, snes->dm)); 56399566063dSJacob Faibussowitsch PetscCall(SNESSetNPCSide(snes, snes->npcside)); 56402c155ee1SBarry Smith } 56413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 56426c699258SBarry Smith } 56436c699258SBarry Smith 56446c699258SBarry Smith /*@ 5645420bcc1bSBarry Smith SNESGetDM - Gets the `DM` that may be used by some solvers/preconditioners 56466c699258SBarry Smith 5647f6dfbefdSBarry Smith Not Collective but dm obtained is parallel on snes 56486c699258SBarry Smith 56496c699258SBarry Smith Input Parameter: 5650420bcc1bSBarry Smith . snes - the `SNES` context 56516c699258SBarry Smith 56526c699258SBarry Smith Output Parameter: 5653420bcc1bSBarry Smith . dm - the `DM` 56546c699258SBarry Smith 56556c699258SBarry Smith Level: intermediate 56566c699258SBarry Smith 5657420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESSetDM()`, `KSPSetDM()`, `KSPGetDM()` 56586c699258SBarry Smith @*/ 5659d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDM(SNES snes, DM *dm) 5660d71ae5a4SJacob Faibussowitsch { 56616c699258SBarry Smith PetscFunctionBegin; 56620700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 56636cab3a1bSJed Brown if (!snes->dm) { 56649566063dSJacob Faibussowitsch PetscCall(DMShellCreate(PetscObjectComm((PetscObject)snes), &snes->dm)); 5665116d1032SJed Brown snes->dmAuto = PETSC_TRUE; 56666cab3a1bSJed Brown } 56676c699258SBarry Smith *dm = snes->dm; 56683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 56696c699258SBarry Smith } 56700807856dSBarry Smith 567131823bd8SMatthew G Knepley /*@ 5672be95d8f1SBarry Smith SNESSetNPC - Sets the nonlinear preconditioner to be used. 567331823bd8SMatthew G Knepley 5674c3339decSBarry Smith Collective 567531823bd8SMatthew G Knepley 567631823bd8SMatthew G Knepley Input Parameters: 5677f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 5678420bcc1bSBarry Smith - npc - the nonlinear preconditioner object 567931823bd8SMatthew G Knepley 5680dc4c0fb0SBarry Smith Level: developer 5681dc4c0fb0SBarry Smith 568231823bd8SMatthew G Knepley Notes: 5683f6dfbefdSBarry Smith Use `SNESGetNPC()` to retrieve the preconditioner context (for example, 568431823bd8SMatthew G Knepley to configure it using the API). 568531823bd8SMatthew G Knepley 5686f6dfbefdSBarry Smith Only some `SNESType` can use a nonlinear preconditioner 5687f6dfbefdSBarry Smith 5688420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNGS`, `SNESFAS`, `SNESGetNPC()`, `SNESHasNPC()` 568931823bd8SMatthew G Knepley @*/ 5690d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPC(SNES snes, SNES npc) 5691d71ae5a4SJacob Faibussowitsch { 569231823bd8SMatthew G Knepley PetscFunctionBegin; 569331823bd8SMatthew G Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5694f6dfbefdSBarry Smith PetscValidHeaderSpecific(npc, SNES_CLASSID, 2); 5695f6dfbefdSBarry Smith PetscCheckSameComm(snes, 1, npc, 2); 5696f6dfbefdSBarry Smith PetscCall(PetscObjectReference((PetscObject)npc)); 56979566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&snes->npc)); 5698f6dfbefdSBarry Smith snes->npc = npc; 56993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 570031823bd8SMatthew G Knepley } 570131823bd8SMatthew G Knepley 570231823bd8SMatthew G Knepley /*@ 5703f6dfbefdSBarry Smith SNESGetNPC - Gets a nonlinear preconditioning solver SNES` to be used to precondition the original nonlinear solver. 570431823bd8SMatthew G Knepley 5705f6dfbefdSBarry Smith Not Collective; but any changes to the obtained the npc object must be applied collectively 570631823bd8SMatthew G Knepley 570731823bd8SMatthew G Knepley Input Parameter: 5708f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 570931823bd8SMatthew G Knepley 571031823bd8SMatthew G Knepley Output Parameter: 5711e4094ef1SJacob Faibussowitsch . pc - preconditioner context 571231823bd8SMatthew G Knepley 5713f6dfbefdSBarry Smith Options Database Key: 5714f6dfbefdSBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner 5715b5badacbSBarry Smith 5716dc4c0fb0SBarry Smith Level: developer 5717dc4c0fb0SBarry Smith 571895452b02SPatrick Sanan Notes: 5719f6dfbefdSBarry Smith If a `SNES` was previously set with `SNESSetNPC()` then that value is returned, otherwise a new `SNES` object is created. 5720be95d8f1SBarry Smith 5721f6dfbefdSBarry Smith The (preconditioner) `SNES` returned automatically inherits the same nonlinear function and Jacobian supplied to the original 5722f6dfbefdSBarry Smith `SNES` 5723951fe5abSBarry Smith 57241cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESHasNPC()`, `SNES`, `SNESCreate()` 572531823bd8SMatthew G Knepley @*/ 5726d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPC(SNES snes, SNES *pc) 5727d71ae5a4SJacob Faibussowitsch { 5728a64e098fSPeter Brune const char *optionsprefix; 572931823bd8SMatthew G Knepley 573031823bd8SMatthew G Knepley PetscFunctionBegin; 573131823bd8SMatthew G Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 57324f572ea9SToby Isaac PetscAssertPointer(pc, 2); 5733efd4aadfSBarry Smith if (!snes->npc) { 5734ec785e5bSStefano Zampini void *ctx; 5735ec785e5bSStefano Zampini 57369566063dSJacob Faibussowitsch PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &snes->npc)); 57379566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->npc, (PetscObject)snes, 1)); 57389566063dSJacob Faibussowitsch PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 57399566063dSJacob Faibussowitsch PetscCall(SNESSetOptionsPrefix(snes->npc, optionsprefix)); 57409566063dSJacob Faibussowitsch PetscCall(SNESAppendOptionsPrefix(snes->npc, "npc_")); 5741fb87a551SStefano Zampini if (snes->ops->usercompute) { 574249abdd8aSBarry Smith PetscCall(SNESSetComputeApplicationContext(snes, snes->ops->usercompute, snes->ops->ctxdestroy)); 5743fb87a551SStefano Zampini } else { 5744ec785e5bSStefano Zampini PetscCall(SNESGetApplicationContext(snes, &ctx)); 5745ec785e5bSStefano Zampini PetscCall(SNESSetApplicationContext(snes->npc, ctx)); 5746fb87a551SStefano Zampini } 57479566063dSJacob Faibussowitsch PetscCall(SNESSetCountersReset(snes->npc, PETSC_FALSE)); 574831823bd8SMatthew G Knepley } 5749efd4aadfSBarry Smith *pc = snes->npc; 57503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 575131823bd8SMatthew G Knepley } 575231823bd8SMatthew G Knepley 57533ad1a0b9SPatrick Farrell /*@ 57543ad1a0b9SPatrick Farrell SNESHasNPC - Returns whether a nonlinear preconditioner exists 57553ad1a0b9SPatrick Farrell 57563ad1a0b9SPatrick Farrell Not Collective 57573ad1a0b9SPatrick Farrell 57583ad1a0b9SPatrick Farrell Input Parameter: 5759f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 57603ad1a0b9SPatrick Farrell 57613ad1a0b9SPatrick Farrell Output Parameter: 5762420bcc1bSBarry Smith . has_npc - whether the `SNES` has a nonlinear preconditioner or not 57633ad1a0b9SPatrick Farrell 57643ad1a0b9SPatrick Farrell Level: developer 57653ad1a0b9SPatrick Farrell 57661cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESGetNPC()` 57673ad1a0b9SPatrick Farrell @*/ 5768d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc) 5769d71ae5a4SJacob Faibussowitsch { 57703ad1a0b9SPatrick Farrell PetscFunctionBegin; 57713ad1a0b9SPatrick Farrell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5772*835f2295SStefano Zampini PetscAssertPointer(has_npc, 2); 5773*835f2295SStefano Zampini *has_npc = snes->npc ? PETSC_TRUE : PETSC_FALSE; 57743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 57753ad1a0b9SPatrick Farrell } 57763ad1a0b9SPatrick Farrell 5777c40d0f55SPeter Brune /*@ 5778420bcc1bSBarry Smith SNESSetNPCSide - Sets the nonlinear preconditioning side. 5779c40d0f55SPeter Brune 5780c3339decSBarry Smith Logically Collective 5781c40d0f55SPeter Brune 5782c40d0f55SPeter Brune Input Parameter: 5783f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 5784c40d0f55SPeter Brune 5785c40d0f55SPeter Brune Output Parameter: 5786c40d0f55SPeter Brune . side - the preconditioning side, where side is one of 5787c40d0f55SPeter Brune .vb 57882d547940SBarry Smith PC_LEFT - left preconditioning 57892d547940SBarry Smith PC_RIGHT - right preconditioning (default for most nonlinear solvers) 5790c40d0f55SPeter Brune .ve 5791c40d0f55SPeter Brune 5792f6dfbefdSBarry Smith Options Database Key: 579367b8a455SSatish Balay . -snes_npc_side <right,left> - nonlinear preconditioner side 5794c40d0f55SPeter Brune 5795dc4c0fb0SBarry Smith Level: intermediate 5796dc4c0fb0SBarry Smith 5797f6dfbefdSBarry Smith Note: 5798f6dfbefdSBarry Smith `SNESNRICHARDSON` and `SNESNCG` only support left preconditioning. 57992d547940SBarry Smith 5800420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNRICHARDSON`, `SNESNCG`, `SNESType`, `SNESGetNPCSide()`, `KSPSetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide` 5801c40d0f55SPeter Brune @*/ 5802d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPCSide(SNES snes, PCSide side) 5803d71ae5a4SJacob Faibussowitsch { 5804c40d0f55SPeter Brune PetscFunctionBegin; 5805c40d0f55SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5806c40d0f55SPeter Brune PetscValidLogicalCollectiveEnum(snes, side, 2); 5807b552625fSStefano Zampini if (side == PC_SIDE_DEFAULT) side = PC_RIGHT; 580854c59aa7SJacob Faibussowitsch PetscCheck((side == PC_LEFT) || (side == PC_RIGHT), PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Only PC_LEFT and PC_RIGHT are supported"); 5809efd4aadfSBarry Smith snes->npcside = side; 58103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5811c40d0f55SPeter Brune } 5812c40d0f55SPeter Brune 5813c40d0f55SPeter Brune /*@ 5814be95d8f1SBarry Smith SNESGetNPCSide - Gets the preconditioning side. 5815c40d0f55SPeter Brune 5816c40d0f55SPeter Brune Not Collective 5817c40d0f55SPeter Brune 5818c40d0f55SPeter Brune Input Parameter: 5819f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 5820c40d0f55SPeter Brune 5821c40d0f55SPeter Brune Output Parameter: 5822c40d0f55SPeter Brune . side - the preconditioning side, where side is one of 5823c40d0f55SPeter Brune .vb 5824f6dfbefdSBarry Smith `PC_LEFT` - left preconditioning 5825f6dfbefdSBarry Smith `PC_RIGHT` - right preconditioning (default for most nonlinear solvers) 5826c40d0f55SPeter Brune .ve 5827c40d0f55SPeter Brune 5828c40d0f55SPeter Brune Level: intermediate 5829c40d0f55SPeter Brune 5830420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNPCSide()`, `KSPGetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide` 5831c40d0f55SPeter Brune @*/ 5832d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPCSide(SNES snes, PCSide *side) 5833d71ae5a4SJacob Faibussowitsch { 5834c40d0f55SPeter Brune PetscFunctionBegin; 5835c40d0f55SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 58364f572ea9SToby Isaac PetscAssertPointer(side, 2); 5837efd4aadfSBarry Smith *side = snes->npcside; 58383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5839c40d0f55SPeter Brune } 5840c40d0f55SPeter Brune 58419e764e56SPeter Brune /*@ 5842420bcc1bSBarry Smith SNESSetLineSearch - Sets the linesearch to be used for `SNES` 58439e764e56SPeter Brune 5844c3339decSBarry Smith Collective 58459e764e56SPeter Brune 58469e764e56SPeter Brune Input Parameters: 5847f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 58489e764e56SPeter Brune - linesearch - the linesearch object 58499e764e56SPeter Brune 5850dc4c0fb0SBarry Smith Level: developer 5851dc4c0fb0SBarry Smith 5852f6dfbefdSBarry Smith Note: 5853420bcc1bSBarry Smith This is almost never used, rather one uses `SNESGetLineSearch()` to retrieve the line search and set options on it 58549e764e56SPeter Brune to configure it using the API). 58559e764e56SPeter Brune 5856420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()` 58579e764e56SPeter Brune @*/ 5858d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch) 5859d71ae5a4SJacob Faibussowitsch { 58609e764e56SPeter Brune PetscFunctionBegin; 58619e764e56SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5862f1c6b773SPeter Brune PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 2); 58639e764e56SPeter Brune PetscCheckSameComm(snes, 1, linesearch, 2); 58649566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)linesearch)); 58659566063dSJacob Faibussowitsch PetscCall(SNESLineSearchDestroy(&snes->linesearch)); 5866f5af7f23SKarl Rupp 58679e764e56SPeter Brune snes->linesearch = linesearch; 58683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 58699e764e56SPeter Brune } 58709e764e56SPeter Brune 5871a34ceb2aSJed Brown /*@ 5872420bcc1bSBarry Smith SNESGetLineSearch - Returns the line search context possibly set with `SNESSetLineSearch()` 5873f6dfbefdSBarry Smith or creates a default line search instance associated with the `SNES` and returns it. 58749e764e56SPeter Brune 58759e764e56SPeter Brune Not Collective 58769e764e56SPeter Brune 58779e764e56SPeter Brune Input Parameter: 5878f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 58799e764e56SPeter Brune 58809e764e56SPeter Brune Output Parameter: 58819e764e56SPeter Brune . linesearch - linesearch context 58829e764e56SPeter Brune 5883162e0bf5SPeter Brune Level: beginner 58849e764e56SPeter Brune 58851cc06b55SBarry Smith .seealso: [](ch_snes), `SNESLineSearch`, `SNESSetLineSearch()`, `SNESLineSearchCreate()` 58869e764e56SPeter Brune @*/ 5887d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch) 5888d71ae5a4SJacob Faibussowitsch { 58899e764e56SPeter Brune const char *optionsprefix; 58909e764e56SPeter Brune 58919e764e56SPeter Brune PetscFunctionBegin; 58929e764e56SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 58934f572ea9SToby Isaac PetscAssertPointer(linesearch, 2); 58949e764e56SPeter Brune if (!snes->linesearch) { 58959566063dSJacob Faibussowitsch PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 58969566063dSJacob Faibussowitsch PetscCall(SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch)); 58979566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetSNES(snes->linesearch, snes)); 58989566063dSJacob Faibussowitsch PetscCall(SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix)); 58999566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->linesearch, (PetscObject)snes, 1)); 59009e764e56SPeter Brune } 59019e764e56SPeter Brune *linesearch = snes->linesearch; 59023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 59039e764e56SPeter Brune } 5904