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 6187addb90fSBarry Smith matrix-free version but still employs the user-provided matrix used for computing the preconditioner. */ 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 808ce78bad3SBarry Smith PETSC_EXTERN PetscErrorCode PetscMonitorPauseFinal_Internal(PetscInt, void *); 809ce78bad3SBarry Smith 810d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESMonitorPauseFinal_Internal(SNES snes) 811d71ae5a4SJacob Faibussowitsch { 8125e7c47f3SMatthew G. Knepley PetscFunctionBegin; 8133ba16761SJacob Faibussowitsch if (!snes->pauseFinal) PetscFunctionReturn(PETSC_SUCCESS); 814ce78bad3SBarry Smith PetscCall(PetscMonitorPauseFinal_Internal(snes->numbermonitors, snes->monitorcontext)); 8153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8165e7c47f3SMatthew G. Knepley } 8175e7c47f3SMatthew G. Knepley 818fde5950dSBarry Smith /*@C 819fde5950dSBarry Smith SNESMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user 820fde5950dSBarry Smith 821c3339decSBarry Smith Collective 822fde5950dSBarry Smith 823fde5950dSBarry Smith Input Parameters: 824dc4c0fb0SBarry Smith + snes - `SNES` object you wish to monitor 825fde5950dSBarry Smith . name - the monitor type one is seeking 826fde5950dSBarry Smith . help - message indicating what monitoring is done 827fde5950dSBarry Smith . manual - manual page for the monitor 82849abdd8aSBarry Smith . monitor - the monitor function, this must use a `PetscViewerFormat` as its context 829f6dfbefdSBarry 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 830fde5950dSBarry Smith 831420bcc1bSBarry Smith Calling sequence of `monitor`: 832420bcc1bSBarry Smith + snes - the nonlinear solver context 833420bcc1bSBarry Smith . it - the current iteration 834420bcc1bSBarry Smith . r - the current function norm 835420bcc1bSBarry Smith - vf - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use 836420bcc1bSBarry Smith 837420bcc1bSBarry Smith Calling sequence of `monitorsetup`: 838420bcc1bSBarry Smith + snes - the nonlinear solver context 839420bcc1bSBarry Smith - vf - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use 840420bcc1bSBarry Smith 841f6dfbefdSBarry Smith Options Database Key: 842f6dfbefdSBarry Smith . -name - trigger the use of this monitor in `SNESSetFromOptions()` 843f6dfbefdSBarry Smith 844f6dfbefdSBarry Smith Level: advanced 845fde5950dSBarry Smith 846648c30bcSBarry Smith .seealso: [](ch_snes), `PetscOptionsCreateViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, 847db781477SPatrick Sanan `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()` 848e4094ef1SJacob Faibussowitsch `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, 849db781477SPatrick Sanan `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`, 850c2e3fba1SPatrick Sanan `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`, 851db781477SPatrick Sanan `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`, 852db781477SPatrick Sanan `PetscOptionsFList()`, `PetscOptionsEList()` 853fde5950dSBarry Smith @*/ 854420bcc1bSBarry 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)) 855d71ae5a4SJacob Faibussowitsch { 856fde5950dSBarry Smith PetscViewer viewer; 857fde5950dSBarry Smith PetscViewerFormat format; 858fde5950dSBarry Smith PetscBool flg; 859fde5950dSBarry Smith 860fde5950dSBarry Smith PetscFunctionBegin; 861648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, name, &viewer, &format, &flg)); 862fde5950dSBarry Smith if (flg) { 863d43b4f6eSBarry Smith PetscViewerAndFormat *vf; 8649566063dSJacob Faibussowitsch PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf)); 865648c30bcSBarry Smith PetscCall(PetscViewerDestroy(&viewer)); 8661baa6e33SBarry Smith if (monitorsetup) PetscCall((*monitorsetup)(snes, vf)); 86749abdd8aSBarry Smith PetscCall(SNESMonitorSet(snes, (PetscErrorCode (*)(SNES, PetscInt, PetscReal, void *))monitor, vf, (PetscCtxDestroyFn *)PetscViewerAndFormatDestroy)); 868fde5950dSBarry Smith } 8693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 870fde5950dSBarry Smith } 871fde5950dSBarry Smith 872a4598233SStefano Zampini PetscErrorCode SNESEWSetFromOptions_Private(SNESKSPEW *kctx, PetscBool print_api, MPI_Comm comm, const char *prefix) 873d71ae5a4SJacob Faibussowitsch { 874a4598233SStefano Zampini const char *api = print_api ? "SNESKSPSetParametersEW" : NULL; 875a4598233SStefano Zampini 8760f0abf79SStefano Zampini PetscFunctionBegin; 8770f0abf79SStefano Zampini PetscOptionsBegin(comm, prefix, "Eisenstat and Walker type forcing options", "KSP"); 878a4598233SStefano Zampini PetscCall(PetscOptionsInt("-ksp_ew_version", "Version 1, 2 or 3", api, kctx->version, &kctx->version, NULL)); 879a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_rtol0", "0 <= rtol0 < 1", api, kctx->rtol_0, &kctx->rtol_0, NULL)); 880a4598233SStefano Zampini kctx->rtol_max = PetscMax(kctx->rtol_0, kctx->rtol_max); 881a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_rtolmax", "0 <= rtolmax < 1", api, kctx->rtol_max, &kctx->rtol_max, NULL)); 882a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_gamma", "0 <= gamma <= 1", api, kctx->gamma, &kctx->gamma, NULL)); 883a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_alpha", "1 < alpha <= 2", api, kctx->alpha, &kctx->alpha, NULL)); 8840f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_alpha2", "alpha2", NULL, kctx->alpha2, &kctx->alpha2, NULL)); 885a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_threshold", "0 < threshold < 1", api, kctx->threshold, &kctx->threshold, NULL)); 8860f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_p1", "p1", NULL, kctx->v4_p1, &kctx->v4_p1, NULL)); 8870f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_p2", "p2", NULL, kctx->v4_p2, &kctx->v4_p2, NULL)); 8880f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_p3", "p3", NULL, kctx->v4_p3, &kctx->v4_p3, NULL)); 8890f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_m1", "Scaling when rk-1 in [p2,p3)", NULL, kctx->v4_m1, &kctx->v4_m1, NULL)); 8900f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_m2", "Scaling when rk-1 in [p3,+infty)", NULL, kctx->v4_m2, &kctx->v4_m2, NULL)); 8910f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_m3", "Threshold for successive rtol (0.1 in Eq.7)", NULL, kctx->v4_m3, &kctx->v4_m3, NULL)); 8920f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_m4", "Adaptation scaling (0.5 in Eq.7)", NULL, kctx->v4_m4, &kctx->v4_m4, NULL)); 8930f0abf79SStefano Zampini PetscOptionsEnd(); 8943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8950f0abf79SStefano Zampini } 8960f0abf79SStefano Zampini 8979b94acceSBarry Smith /*@ 898f6dfbefdSBarry Smith SNESSetFromOptions - Sets various `SNES` and `KSP` parameters from user options. 8999b94acceSBarry Smith 900c3339decSBarry Smith Collective 901c7afd0dbSLois Curfman McInnes 9029b94acceSBarry Smith Input Parameter: 903f6dfbefdSBarry Smith . snes - the `SNES` context 9049b94acceSBarry Smith 90536851e7fSLois Curfman McInnes Options Database Keys: 906f6dfbefdSBarry Smith + -snes_type <type> - newtonls, newtontr, ngmres, ncg, nrichardson, qn, vi, fas, `SNESType` for complete list 907b39c3a46SLois Curfman McInnes . -snes_rtol <rtol> - relative decrease in tolerance norm from initial 90877e5a1f9SBarry Smith . -snes_atol <abstol> - absolute tolerance of residual norm 90977e5a1f9SBarry Smith . -snes_stol <stol> - convergence tolerance in terms of the norm of the change in the solution between steps 910e4d06f11SPatrick Farrell . -snes_divergence_tolerance <divtol> - if the residual goes above divtol*rnorm0, exit with divergence 911b39c3a46SLois Curfman McInnes . -snes_max_it <max_it> - maximum number of iterations 912b39c3a46SLois Curfman McInnes . -snes_max_funcs <max_funcs> - maximum number of function evaluations 91377e5a1f9SBarry Smith . -snes_force_iteration <force> - force `SNESSolve()` to take at least one iteration 9144839bfe8SBarry Smith . -snes_max_fail <max_fail> - maximum number of line search failures allowed before stopping, default is none 915ddf469c8SBarry Smith . -snes_max_linear_solve_fail - number of linear solver failures before SNESSolve() stops 916a8054027SBarry Smith . -snes_lag_preconditioner <lag> - how often preconditioner is rebuilt (use -1 to never rebuild) 9173d5a8a6aSBarry Smith . -snes_lag_preconditioner_persists <true,false> - retains the -snes_lag_preconditioner information across multiple SNESSolve() 918e35cf81dSBarry Smith . -snes_lag_jacobian <lag> - how often Jacobian is rebuilt (use -1 to never rebuild) 9193d5a8a6aSBarry Smith . -snes_lag_jacobian_persists <true,false> - retains the -snes_lag_jacobian information across multiple SNESSolve() 920ceaaa498SBarry 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. 921fde5950dSBarry Smith . -snes_monitor [ascii][:filename][:viewer format] - prints residual norm at each iteration. if no filename given prints to stdout 922fde5950dSBarry Smith . -snes_monitor_solution [ascii binary draw][:filename][:viewer format] - plots solution at each iteration 923fde5950dSBarry Smith . -snes_monitor_residual [ascii binary draw][:filename][:viewer format] - plots residual (not its norm) at each iteration 924fde5950dSBarry Smith . -snes_monitor_solution_update [ascii binary draw][:filename][:viewer format] - plots update to solution at each iteration 9254619e776SBarry Smith . -snes_monitor_lg_residualnorm - plots residual norm at each iteration 926459f5d12SBarry Smith . -snes_monitor_lg_range - plots residual norm at each iteration 9275e7c47f3SMatthew G. Knepley . -snes_monitor_pause_final - Pauses all monitor drawing after the solver ends 928e24b481bSBarry Smith . -snes_fd - use finite differences to compute Jacobian; very slow, only for testing 929e2e60de9SPeter Brune . -snes_fd_color - use finite differences with coloring to compute Jacobian 930ceaaa498SBarry Smith . -snes_mf_ksp_monitor - if using matrix-free multiply then print h at each `KSP` iteration 931b5badacbSBarry Smith . -snes_converged_reason - print the reason for convergence/divergence after each solve 932ceaaa498SBarry Smith . -npc_snes_type <type> - the `SNES` type to use as a nonlinear preconditioner 933e62ac41dSBarry 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. 934e62ac41dSBarry 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. 93582738288SBarry Smith 936f6dfbefdSBarry Smith Options Database Keys for Eisenstat-Walker method: 937fa9f3622SBarry Smith + -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence 9384b27c08aSLois Curfman McInnes . -snes_ksp_ew_version ver - version of Eisenstat-Walker method 93936851e7fSLois Curfman McInnes . -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0 94036851e7fSLois Curfman McInnes . -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax 94136851e7fSLois Curfman McInnes . -snes_ksp_ew_gamma <gamma> - Sets gamma 94236851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha <alpha> - Sets alpha 94336851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2 94436851e7fSLois Curfman McInnes - -snes_ksp_ew_threshold <threshold> - Sets threshold 94582738288SBarry Smith 946dc4c0fb0SBarry Smith Level: beginner 947dc4c0fb0SBarry Smith 94811ca99fdSLois Curfman McInnes Notes: 949ec5066bdSBarry Smith To see all options, run your program with the -help option or consult the users manual 950ec5066bdSBarry Smith 951420bcc1bSBarry Smith `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`, 952420bcc1bSBarry Smith and computing explicitly with 953f6dfbefdSBarry Smith finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object. 95483e2fdc7SBarry Smith 955420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESType`, `SNESSetOptionsPrefix()`, `SNESResetFromOptions()`, `SNES`, `SNESCreate()`, `MatCreateSNESMF()`, `MatFDColoring` 9569b94acceSBarry Smith @*/ 957d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFromOptions(SNES snes) 958d71ae5a4SJacob Faibussowitsch { 9598afaa268SBarry Smith PetscBool flg, pcset, persist, set; 96077e5a1f9SBarry Smith PetscInt i, indx, lag, grids, max_its, max_funcs; 96104d7464bSBarry Smith const char *deft = SNESNEWTONLS; 962649ef022SMatthew Knepley const char *convtests[] = {"default", "skip", "correct_pressure"}; 96385385478SLisandro Dalcin SNESKSPEW *kctx = NULL; 9640f0abf79SStefano Zampini char type[256], monfilename[PETSC_MAX_PATH_LEN], ewprefix[256]; 965c40d0f55SPeter Brune PCSide pcside; 966a64e098fSPeter Brune const char *optionsprefix; 96777e5a1f9SBarry Smith PetscReal rtol, abstol, stol; 9689b94acceSBarry Smith 9693a40ed3dSBarry Smith PetscFunctionBegin; 9700700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 9719566063dSJacob Faibussowitsch PetscCall(SNESRegisterAll()); 972d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)snes); 973639ff905SBarry Smith if (((PetscObject)snes)->type_name) deft = ((PetscObject)snes)->type_name; 9749566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-snes_type", "Nonlinear solver method", "SNESSetType", SNESList, deft, type, 256, &flg)); 975d64ed03dSBarry Smith if (flg) { 9769566063dSJacob Faibussowitsch PetscCall(SNESSetType(snes, type)); 9777adad957SLisandro Dalcin } else if (!((PetscObject)snes)->type_name) { 9789566063dSJacob Faibussowitsch PetscCall(SNESSetType(snes, deft)); 979d64ed03dSBarry Smith } 980186905e3SBarry Smith 98177e5a1f9SBarry Smith abstol = snes->abstol; 98277e5a1f9SBarry Smith rtol = snes->rtol; 98377e5a1f9SBarry Smith stol = snes->stol; 98477e5a1f9SBarry Smith max_its = snes->max_its; 98577e5a1f9SBarry Smith max_funcs = snes->max_funcs; 98677e5a1f9SBarry Smith PetscCall(PetscOptionsReal("-snes_rtol", "Stop if decrease in function norm less than", "SNESSetTolerances", snes->rtol, &rtol, NULL)); 98777e5a1f9SBarry Smith PetscCall(PetscOptionsReal("-snes_atol", "Stop if function norm less than", "SNESSetTolerances", snes->abstol, &abstol, NULL)); 98877e5a1f9SBarry Smith PetscCall(PetscOptionsReal("-snes_stol", "Stop if step length less than", "SNESSetTolerances", snes->stol, &stol, NULL)); 98977e5a1f9SBarry Smith PetscCall(PetscOptionsInt("-snes_max_it", "Maximum iterations", "SNESSetTolerances", snes->max_its, &max_its, NULL)); 99077e5a1f9SBarry Smith PetscCall(PetscOptionsInt("-snes_max_funcs", "Maximum function evaluations", "SNESSetTolerances", snes->max_funcs, &max_funcs, NULL)); 99177e5a1f9SBarry Smith PetscCall(SNESSetTolerances(snes, abstol, rtol, stol, max_its, max_funcs)); 99277e5a1f9SBarry Smith 99377e5a1f9SBarry Smith PetscCall(PetscOptionsReal("-snes_divergence_tolerance", "Stop if residual norm increases by this factor", "SNESSetDivergenceTolerance", snes->divtol, &snes->divtol, &flg)); 99477e5a1f9SBarry Smith if (flg) PetscCall(SNESSetDivergenceTolerance(snes, snes->divtol)); 99577e5a1f9SBarry Smith 99677e5a1f9SBarry Smith PetscCall(PetscOptionsInt("-snes_max_fail", "Maximum nonlinear step failures", "SNESSetMaxNonlinearStepFailures", snes->maxFailures, &snes->maxFailures, &flg)); 99777e5a1f9SBarry Smith if (flg) PetscCall(SNESSetMaxNonlinearStepFailures(snes, snes->maxFailures)); 99877e5a1f9SBarry Smith 99977e5a1f9SBarry Smith PetscCall(PetscOptionsInt("-snes_max_linear_solve_fail", "Maximum failures in linear solves allowed", "SNESSetMaxLinearSolveFailures", snes->maxLinearSolveFailures, &snes->maxLinearSolveFailures, &flg)); 100077e5a1f9SBarry Smith if (flg) PetscCall(SNESSetMaxLinearSolveFailures(snes, snes->maxLinearSolveFailures)); 100177e5a1f9SBarry Smith 10029566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_error_if_not_converged", "Generate error if solver does not converge", "SNESSetErrorIfNotConverged", snes->errorifnotconverged, &snes->errorifnotconverged, NULL)); 10039566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_force_iteration", "Force SNESSolve() to take at least one iteration", "SNESSetForceIteration", snes->forceiteration, &snes->forceiteration, NULL)); 10049566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_check_jacobian_domain_error", "Check Jacobian domain error after Jacobian evaluation", "SNESCheckJacobianDomainError", snes->checkjacdomainerror, &snes->checkjacdomainerror, NULL)); 100585385478SLisandro Dalcin 10069566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_lag_preconditioner", "How often to rebuild preconditioner", "SNESSetLagPreconditioner", snes->lagpreconditioner, &lag, &flg)); 1007a8054027SBarry Smith if (flg) { 10085f80ce2aSJacob Faibussowitsch PetscCheck(lag != -1, PetscObjectComm((PetscObject)snes), PETSC_ERR_USER, "Cannot set the lag to -1 from the command line since the preconditioner must be built as least once, perhaps you mean -2"); 10099566063dSJacob Faibussowitsch PetscCall(SNESSetLagPreconditioner(snes, lag)); 1010a8054027SBarry Smith } 10119566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_lag_preconditioner_persists", "Preconditioner lagging through multiple SNES solves", "SNESSetLagPreconditionerPersists", snes->lagjac_persist, &persist, &flg)); 10121baa6e33SBarry Smith if (flg) PetscCall(SNESSetLagPreconditionerPersists(snes, persist)); 10139566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_lag_jacobian", "How often to rebuild Jacobian", "SNESSetLagJacobian", snes->lagjacobian, &lag, &flg)); 1014e35cf81dSBarry Smith if (flg) { 10155f80ce2aSJacob 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"); 10169566063dSJacob Faibussowitsch PetscCall(SNESSetLagJacobian(snes, lag)); 1017e35cf81dSBarry Smith } 10189566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_lag_jacobian_persists", "Jacobian lagging through multiple SNES solves", "SNESSetLagJacobianPersists", snes->lagjac_persist, &persist, &flg)); 10191baa6e33SBarry Smith if (flg) PetscCall(SNESSetLagJacobianPersists(snes, persist)); 102037ec4e1aSPeter Brune 10219566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_grid_sequence", "Use grid sequencing to generate initial guess", "SNESSetGridSequence", snes->gridsequence, &grids, &flg)); 10221baa6e33SBarry Smith if (flg) PetscCall(SNESSetGridSequence(snes, grids)); 1023a8054027SBarry Smith 1024400f6f02SBarry Smith PetscCall(PetscOptionsEList("-snes_convergence_test", "Convergence test", "SNESSetConvergenceTest", convtests, PETSC_STATIC_ARRAY_LENGTH(convtests), "default", &indx, &flg)); 102585385478SLisandro Dalcin if (flg) { 102685385478SLisandro Dalcin switch (indx) { 1027d71ae5a4SJacob Faibussowitsch case 0: 1028d71ae5a4SJacob Faibussowitsch PetscCall(SNESSetConvergenceTest(snes, SNESConvergedDefault, NULL, NULL)); 1029d71ae5a4SJacob Faibussowitsch break; 1030d71ae5a4SJacob Faibussowitsch case 1: 1031d71ae5a4SJacob Faibussowitsch PetscCall(SNESSetConvergenceTest(snes, SNESConvergedSkip, NULL, NULL)); 1032d71ae5a4SJacob Faibussowitsch break; 1033d71ae5a4SJacob Faibussowitsch case 2: 1034d71ae5a4SJacob Faibussowitsch PetscCall(SNESSetConvergenceTest(snes, SNESConvergedCorrectPressure, NULL, NULL)); 1035d71ae5a4SJacob Faibussowitsch break; 103685385478SLisandro Dalcin } 103785385478SLisandro Dalcin } 103885385478SLisandro Dalcin 10399566063dSJacob Faibussowitsch PetscCall(PetscOptionsEList("-snes_norm_schedule", "SNES Norm schedule", "SNESSetNormSchedule", SNESNormSchedules, 5, "function", &indx, &flg)); 10409566063dSJacob Faibussowitsch if (flg) PetscCall(SNESSetNormSchedule(snes, (SNESNormSchedule)indx)); 1041fdacfa88SPeter Brune 10429566063dSJacob Faibussowitsch PetscCall(PetscOptionsEList("-snes_function_type", "SNES Norm schedule", "SNESSetFunctionType", SNESFunctionTypes, 2, "unpreconditioned", &indx, &flg)); 10439566063dSJacob Faibussowitsch if (flg) PetscCall(SNESSetFunctionType(snes, (SNESFunctionType)indx)); 1044186905e3SBarry Smith 104585385478SLisandro Dalcin kctx = (SNESKSPEW *)snes->kspconvctx; 104685385478SLisandro Dalcin 10479566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_ksp_ew", "Use Eisentat-Walker linear system convergence test", "SNESKSPSetUseEW", snes->ksp_ewconv, &snes->ksp_ewconv, NULL)); 1048186905e3SBarry Smith 10490f0abf79SStefano Zampini PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 10500f0abf79SStefano Zampini PetscCall(PetscSNPrintf(ewprefix, sizeof(ewprefix), "%s%s", optionsprefix ? optionsprefix : "", "snes_")); 1051a4598233SStefano Zampini PetscCall(SNESEWSetFromOptions_Private(kctx, PETSC_TRUE, PetscObjectComm((PetscObject)snes), ewprefix)); 1052186905e3SBarry Smith 105390d69ab7SBarry Smith flg = PETSC_FALSE; 10549566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_monitor_cancel", "Remove all monitors", "SNESMonitorCancel", flg, &flg, &set)); 10559566063dSJacob Faibussowitsch if (set && flg) PetscCall(SNESMonitorCancel(snes)); 1056eabae89aSBarry Smith 10579566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor", "Monitor norm of function", "SNESMonitorDefault", SNESMonitorDefault, SNESMonitorDefaultSetUp)); 10589566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_short", "Monitor norm of function with fewer digits", "SNESMonitorDefaultShort", SNESMonitorDefaultShort, NULL)); 10599566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_range", "Monitor range of elements of function", "SNESMonitorRange", SNESMonitorRange, NULL)); 1060eabae89aSBarry Smith 10619566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_ratio", "Monitor ratios of the norm of function for consecutive steps", "SNESMonitorRatio", SNESMonitorRatio, SNESMonitorRatioSetUp)); 10629566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_field", "Monitor norm of function (split into fields)", "SNESMonitorDefaultField", SNESMonitorDefaultField, NULL)); 10639566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution", "View solution at each iteration", "SNESMonitorSolution", SNESMonitorSolution, NULL)); 10649566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution_update", "View correction at each iteration", "SNESMonitorSolutionUpdate", SNESMonitorSolutionUpdate, NULL)); 10659566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_residual", "View residual at each iteration", "SNESMonitorResidual", SNESMonitorResidual, NULL)); 10669566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_jacupdate_spectrum", "Print the change in the spectrum of the Jacobian", "SNESMonitorJacUpdateSpectrum", SNESMonitorJacUpdateSpectrum, NULL)); 10679566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_fields", "Monitor norm of function per field", "SNESMonitorSet", SNESMonitorFields, NULL)); 10689566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_monitor_pause_final", "Pauses all draw monitors at the final iterate", "SNESMonitorPauseFinal_Internal", PETSC_FALSE, &snes->pauseFinal, NULL)); 10692db13446SMatthew G. Knepley 10709566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-snes_monitor_python", "Use Python function", "SNESMonitorSet", NULL, monfilename, sizeof(monfilename), &flg)); 10719566063dSJacob Faibussowitsch if (flg) PetscCall(PetscPythonMonitorSet((PetscObject)snes, monfilename)); 10725180491cSLisandro Dalcin 107390d69ab7SBarry Smith flg = PETSC_FALSE; 10749566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_monitor_lg_range", "Plot function range at each iteration", "SNESMonitorLGRange", flg, &flg, NULL)); 1075459f5d12SBarry Smith if (flg) { 1076459f5d12SBarry Smith PetscViewer ctx; 1077e24b481bSBarry Smith 10789566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &ctx)); 107949abdd8aSBarry Smith PetscCall(SNESMonitorSet(snes, SNESMonitorLGRange, ctx, (PetscCtxDestroyFn *)PetscViewerDestroy)); 1080459f5d12SBarry Smith } 10812e7541e6SPeter Brune 1082648c30bcSBarry Smith PetscCall(PetscViewerDestroy(&snes->convergedreasonviewer)); 1083648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_converged_reason", &snes->convergedreasonviewer, &snes->convergedreasonformat, NULL)); 108490d69ab7SBarry Smith flg = PETSC_FALSE; 10859566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_converged_reason_view_cancel", "Remove all converged reason viewers", "SNESConvergedReasonViewCancel", flg, &flg, &set)); 10869566063dSJacob Faibussowitsch if (set && flg) PetscCall(SNESConvergedReasonViewCancel(snes)); 1087c4421ceaSFande Kong 1088c4421ceaSFande Kong flg = PETSC_FALSE; 10899566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_fd", "Use finite differences (slow) to compute Jacobian", "SNESComputeJacobianDefault", flg, &flg, NULL)); 10904b27c08aSLois Curfman McInnes if (flg) { 10916cab3a1bSJed Brown void *functx; 1092b1f624c7SBarry Smith DM dm; 10939566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 1094800f99ffSJeremy L Thompson PetscCall(DMSNESUnsetJacobianContext_Internal(dm)); 10959566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, NULL, &functx)); 10969566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefault, functx)); 10979566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Setting default finite difference Jacobian matrix\n")); 10989b94acceSBarry Smith } 1099639f9d9dSBarry Smith 110044848bc4SPeter Brune flg = PETSC_FALSE; 11019566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_fd_function", "Use finite differences (slow) to compute function from user objective", "SNESObjectiveComputeFunctionDefaultFD", flg, &flg, NULL)); 11021baa6e33SBarry Smith if (flg) PetscCall(SNESSetFunction(snes, NULL, SNESObjectiveComputeFunctionDefaultFD, NULL)); 110397584545SPeter Brune 110497584545SPeter Brune flg = PETSC_FALSE; 11059566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_fd_color", "Use finite differences with coloring to compute Jacobian", "SNESComputeJacobianDefaultColor", flg, &flg, NULL)); 110644848bc4SPeter Brune if (flg) { 1107c52e227fSPeter Brune DM dm; 11089566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 1109800f99ffSJeremy L Thompson PetscCall(DMSNESUnsetJacobianContext_Internal(dm)); 11109566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefaultColor, NULL)); 11119566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Setting default finite difference coloring Jacobian matrix\n")); 111244848bc4SPeter Brune } 111344848bc4SPeter Brune 1114aa3661deSLisandro Dalcin flg = PETSC_FALSE; 11157addb90fSBarry Smith PetscCall(PetscOptionsBool("-snes_mf_operator", "Use a Matrix-Free Jacobian with user-provided matrix for computing the preconditioner", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf_operator, &flg)); 1116d8f46077SPeter Brune if (flg && snes->mf_operator) { 1117a8248277SBarry Smith snes->mf_operator = PETSC_TRUE; 1118d8f46077SPeter Brune snes->mf = PETSC_TRUE; 1119a8248277SBarry Smith } 1120aa3661deSLisandro Dalcin flg = PETSC_FALSE; 11217addb90fSBarry Smith PetscCall(PetscOptionsBool("-snes_mf", "Use a Matrix-Free Jacobian with no matrix for computing the preconditioner", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf, &flg)); 1122d8f46077SPeter Brune if (!flg && snes->mf_operator) snes->mf = PETSC_TRUE; 11239566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_mf_version", "Matrix-Free routines version 1 or 2", "None", snes->mf_version, &snes->mf_version, NULL)); 1124d28543b3SPeter Brune 1125c40d0f55SPeter Brune flg = PETSC_FALSE; 11269566063dSJacob Faibussowitsch PetscCall(SNESGetNPCSide(snes, &pcside)); 11279566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-snes_npc_side", "SNES nonlinear preconditioner side", "SNESSetNPCSide", PCSides, (PetscEnum)pcside, (PetscEnum *)&pcside, &flg)); 11289566063dSJacob Faibussowitsch if (flg) PetscCall(SNESSetNPCSide(snes, pcside)); 1129c40d0f55SPeter Brune 1130e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS) 11318a70d858SHong Zhang /* 11328a70d858SHong Zhang Publish convergence information using SAWs 11338a70d858SHong Zhang */ 11348a70d858SHong Zhang flg = PETSC_FALSE; 11359566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_monitor_saws", "Publish SNES progress using SAWs", "SNESMonitorSet", flg, &flg, NULL)); 11368a70d858SHong Zhang if (flg) { 11378a70d858SHong Zhang void *ctx; 11389566063dSJacob Faibussowitsch PetscCall(SNESMonitorSAWsCreate(snes, &ctx)); 11399566063dSJacob Faibussowitsch PetscCall(SNESMonitorSet(snes, SNESMonitorSAWs, ctx, SNESMonitorSAWsDestroy)); 11408a70d858SHong Zhang } 11418a70d858SHong Zhang #endif 11428a70d858SHong Zhang #if defined(PETSC_HAVE_SAWS) 1143b90c6cbeSBarry Smith { 1144b90c6cbeSBarry Smith PetscBool set; 1145b90c6cbeSBarry Smith flg = PETSC_FALSE; 11469566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_saws_block", "Block for SAWs at end of SNESSolve", "PetscObjectSAWsBlock", ((PetscObject)snes)->amspublishblock, &flg, &set)); 11471baa6e33SBarry Smith if (set) PetscCall(PetscObjectSAWsSetBlock((PetscObject)snes, flg)); 1148b90c6cbeSBarry Smith } 1149b90c6cbeSBarry Smith #endif 1150b90c6cbeSBarry Smith 115148a46eb9SPierre Jolivet for (i = 0; i < numberofsetfromoptions; i++) PetscCall((*othersetfromoptions[i])(snes)); 115276b2cf59SMatthew Knepley 1153dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, setfromoptions, PetscOptionsObject); 11545d973c19SBarry Smith 11555d973c19SBarry Smith /* process any options handlers added with PetscObjectAddOptionsHandler() */ 1156dbbe0bcdSBarry Smith PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)snes, PetscOptionsObject)); 1157d0609cedSBarry Smith PetscOptionsEnd(); 11584bbc92c1SBarry Smith 1159d8d34be6SBarry Smith if (snes->linesearch) { 11609566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 11619566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetFromOptions(snes->linesearch)); 1162d8d34be6SBarry Smith } 11639e764e56SPeter Brune 11646aa5e7e9SBarry Smith if (snes->usesksp) { 11659566063dSJacob Faibussowitsch if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 11669566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(snes->ksp, snes->jacobian, snes->jacobian_pre)); 11679566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(snes->ksp)); 11686aa5e7e9SBarry Smith } 11696991f827SBarry Smith 1170b5badacbSBarry Smith /* if user has set the SNES NPC type via options database, create it. */ 11719566063dSJacob Faibussowitsch PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 11729566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)snes)->options, optionsprefix, "-npc_snes_type", &pcset)); 117348a46eb9SPierre Jolivet if (pcset && (!snes->npc)) PetscCall(SNESGetNPC(snes, &snes->npc)); 11741baa6e33SBarry Smith if (snes->npc) PetscCall(SNESSetFromOptions(snes->npc)); 1175b3cd9a81SMatthew G. Knepley snes->setfromoptionscalled++; 11763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1177b3cd9a81SMatthew G. Knepley } 1178b3cd9a81SMatthew G. Knepley 1179b3cd9a81SMatthew G. Knepley /*@ 1180420bcc1bSBarry Smith SNESResetFromOptions - Sets various `SNES` and `KSP` parameters from user options ONLY if the `SNESSetFromOptions()` was previously called 1181b3cd9a81SMatthew G. Knepley 1182c3339decSBarry Smith Collective 1183b3cd9a81SMatthew G. Knepley 1184b3cd9a81SMatthew G. Knepley Input Parameter: 1185f6dfbefdSBarry Smith . snes - the `SNES` context 1186b3cd9a81SMatthew G. Knepley 1187420bcc1bSBarry Smith Level: advanced 1188b3cd9a81SMatthew G. Knepley 11891cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESSetOptionsPrefix()` 1190b3cd9a81SMatthew G. Knepley @*/ 1191d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESResetFromOptions(SNES snes) 1192d71ae5a4SJacob Faibussowitsch { 1193b3cd9a81SMatthew G. Knepley PetscFunctionBegin; 11949566063dSJacob Faibussowitsch if (snes->setfromoptionscalled) PetscCall(SNESSetFromOptions(snes)); 11953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11969b94acceSBarry Smith } 11979b94acceSBarry Smith 1198bb9467b5SJed Brown /*@C 1199d25893d9SBarry Smith SNESSetComputeApplicationContext - Sets an optional function to compute a user-defined context for 1200d25893d9SBarry Smith the nonlinear solvers. 1201d25893d9SBarry Smith 1202dc4c0fb0SBarry Smith Logically Collective; No Fortran Support 1203d25893d9SBarry Smith 1204d25893d9SBarry Smith Input Parameters: 1205f6dfbefdSBarry Smith + snes - the `SNES` context 1206d25893d9SBarry Smith . compute - function to compute the context 120749abdd8aSBarry Smith - destroy - function to destroy the context, see `PetscCtxDestroyFn` for the calling sequence 1208d25893d9SBarry Smith 1209420bcc1bSBarry Smith Calling sequence of `compute`: 1210420bcc1bSBarry Smith + snes - the `SNES` context 1211420bcc1bSBarry Smith - ctx - context to be computed 1212420bcc1bSBarry Smith 1213d25893d9SBarry Smith Level: intermediate 1214d25893d9SBarry Smith 1215f6dfbefdSBarry Smith Note: 1216f6dfbefdSBarry Smith This routine is useful if you are performing grid sequencing or using `SNESFAS` and need the appropriate context generated for each level. 1217f6dfbefdSBarry Smith 1218f6dfbefdSBarry Smith Use `SNESSetApplicationContext()` to see the context immediately 1219f6dfbefdSBarry Smith 122049abdd8aSBarry Smith .seealso: [](ch_snes), `SNESGetApplicationContext()`, `SNESSetApplicationContext()`, `PetscCtxDestroyFn` 1221d25893d9SBarry Smith @*/ 122249abdd8aSBarry Smith PetscErrorCode SNESSetComputeApplicationContext(SNES snes, PetscErrorCode (*compute)(SNES snes, void **ctx), PetscCtxDestroyFn *destroy) 1223d71ae5a4SJacob Faibussowitsch { 1224d25893d9SBarry Smith PetscFunctionBegin; 1225d25893d9SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1226d25893d9SBarry Smith snes->ops->usercompute = compute; 122749abdd8aSBarry Smith snes->ops->ctxdestroy = destroy; 12283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1229d25893d9SBarry Smith } 1230a847f771SSatish Balay 1231b07ff414SBarry Smith /*@ 1232f6dfbefdSBarry Smith SNESSetApplicationContext - Sets the optional user-defined context for the nonlinear solvers. 12339b94acceSBarry Smith 1234c3339decSBarry Smith Logically Collective 1235fee21e36SBarry Smith 1236c7afd0dbSLois Curfman McInnes Input Parameters: 1237f6dfbefdSBarry Smith + snes - the `SNES` context 1238ce78bad3SBarry Smith - ctx - the user context 1239c7afd0dbSLois Curfman McInnes 124036851e7fSLois Curfman McInnes Level: intermediate 124136851e7fSLois Curfman McInnes 1242f6dfbefdSBarry Smith Notes: 1243ce78bad3SBarry Smith Users can provide a context when constructing the `SNES` options and then access it inside their function, Jacobian computation, or other evaluation function 1244f6dfbefdSBarry Smith with `SNESGetApplicationContext()` 1245f6dfbefdSBarry Smith 1246f6dfbefdSBarry Smith To provide a function that computes the context for you use `SNESSetComputeApplicationContext()` 1247f6dfbefdSBarry Smith 1248420bcc1bSBarry Smith Fortran Note: 1249ce78bad3SBarry Smith This only works when `ctx` is a Fortran derived type (it cannot be a `PetscObject`), we recommend writing a Fortran interface definition for this 1250ce78bad3SBarry Smith function that tells the Fortran compiler the derived data type that is passed in as the `ctx` argument. See `SNESGetApplicationContext()` for 1251ce78bad3SBarry Smith an example. 1252daf670e6SBarry Smith 12531cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetComputeApplicationContext()`, `SNESGetApplicationContext()` 12549b94acceSBarry Smith @*/ 125549abdd8aSBarry Smith PetscErrorCode SNESSetApplicationContext(SNES snes, void *ctx) 1256d71ae5a4SJacob Faibussowitsch { 1257b07ff414SBarry Smith KSP ksp; 12581b2093e4SBarry Smith 12593a40ed3dSBarry Smith PetscFunctionBegin; 12600700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 12619566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 126249abdd8aSBarry Smith PetscCall(KSPSetApplicationContext(ksp, ctx)); 126349abdd8aSBarry Smith snes->ctx = ctx; 12643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12659b94acceSBarry Smith } 126674679c65SBarry Smith 1267b07ff414SBarry Smith /*@ 12689b94acceSBarry Smith SNESGetApplicationContext - Gets the user-defined context for the 1269420bcc1bSBarry Smith nonlinear solvers set with `SNESGetApplicationContext()` or `SNESSetComputeApplicationContext()` 12709b94acceSBarry Smith 1271c7afd0dbSLois Curfman McInnes Not Collective 1272c7afd0dbSLois Curfman McInnes 12739b94acceSBarry Smith Input Parameter: 1274f6dfbefdSBarry Smith . snes - `SNES` context 12759b94acceSBarry Smith 12769b94acceSBarry Smith Output Parameter: 127749abdd8aSBarry Smith . ctx - user context 12789b94acceSBarry Smith 127936851e7fSLois Curfman McInnes Level: intermediate 128036851e7fSLois Curfman McInnes 1281ce78bad3SBarry Smith Fortran Notes: 1282ce78bad3SBarry Smith This only works when the context is a Fortran derived type (it cannot be a `PetscObject`) and you **must** write a Fortran interface definition for this 1283ce78bad3SBarry Smith function that tells the Fortran compiler the derived data type that is returned as the `ctx` argument. For example, 1284ce78bad3SBarry Smith .vb 1285ce78bad3SBarry Smith Interface SNESGetApplicationContext 1286ce78bad3SBarry Smith Subroutine SNESGetApplicationContext(snes,ctx,ierr) 1287ce78bad3SBarry Smith #include <petsc/finclude/petscsnes.h> 1288ce78bad3SBarry Smith use petscsnes 1289ce78bad3SBarry Smith SNES snes 1290ce78bad3SBarry Smith type(tUsertype), pointer :: ctx 1291ce78bad3SBarry Smith PetscErrorCode ierr 1292ce78bad3SBarry Smith End Subroutine 1293ce78bad3SBarry Smith End Interface SNESGetApplicationContext 1294ce78bad3SBarry Smith .ve 1295ce78bad3SBarry Smith 1296bfe80ac4SPierre Jolivet The prototype for `ctx` must be 1297ce78bad3SBarry Smith .vb 1298ce78bad3SBarry Smith type(tUsertype), pointer :: ctx 1299ce78bad3SBarry Smith .ve 1300dc4c0fb0SBarry Smith 1301420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESSetApplicationContext()`, `SNESSetComputeApplicationContext()` 13029b94acceSBarry Smith @*/ 1303ce78bad3SBarry Smith PetscErrorCode SNESGetApplicationContext(SNES snes, PeCtx ctx) 1304d71ae5a4SJacob Faibussowitsch { 13053a40ed3dSBarry Smith PetscFunctionBegin; 13060700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 130749abdd8aSBarry Smith *(void **)ctx = snes->ctx; 13083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13099b94acceSBarry Smith } 131074679c65SBarry Smith 13119b94acceSBarry Smith /*@ 1312420bcc1bSBarry Smith SNESSetUseMatrixFree - indicates that `SNES` should use matrix-free finite difference matrix-vector products to apply the Jacobian. 13133565c898SBarry Smith 1314dc4c0fb0SBarry Smith Logically Collective 13153565c898SBarry Smith 13163565c898SBarry Smith Input Parameters: 1317f6dfbefdSBarry Smith + snes - `SNES` context 1318f6dfbefdSBarry Smith . mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used 1319f6dfbefdSBarry 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 1320420bcc1bSBarry Smith this option no matrix-element based preconditioners can be used in the linear solve since the matrix won't be explicitly available 13213565c898SBarry Smith 1322f6dfbefdSBarry Smith Options Database Keys: 132301c1178eSBarry Smith + -snes_mf_operator - use matrix-free only for the mat operator 1324f6dfbefdSBarry Smith . -snes_mf - use matrix-free for both the mat and pmat operator 1325ec5066bdSBarry Smith . -snes_fd_color - compute the Jacobian via coloring and finite differences. 1326ec5066bdSBarry Smith - -snes_fd - compute the Jacobian via finite differences (slow) 13273565c898SBarry Smith 13283565c898SBarry Smith Level: intermediate 13293565c898SBarry Smith 1330f6dfbefdSBarry Smith Note: 1331420bcc1bSBarry Smith `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`, 1332420bcc1bSBarry Smith and computing explicitly with 1333f6dfbefdSBarry Smith finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object. 1334ec5066bdSBarry Smith 1335420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetUseMatrixFree()`, `MatCreateSNESMF()`, `SNESComputeJacobianDefaultColor()`, `MatFDColoring` 13363565c898SBarry Smith @*/ 1337d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUseMatrixFree(SNES snes, PetscBool mf_operator, PetscBool mf) 1338d71ae5a4SJacob Faibussowitsch { 13393565c898SBarry Smith PetscFunctionBegin; 13403565c898SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 134188b4c220SStefano Zampini PetscValidLogicalCollectiveBool(snes, mf_operator, 2); 134288b4c220SStefano Zampini PetscValidLogicalCollectiveBool(snes, mf, 3); 13434ddffce6SLisandro Dalcin snes->mf = mf_operator ? PETSC_TRUE : mf; 13443565c898SBarry Smith snes->mf_operator = mf_operator; 13453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13463565c898SBarry Smith } 13473565c898SBarry Smith 13483565c898SBarry Smith /*@ 1349dc4c0fb0SBarry Smith SNESGetUseMatrixFree - indicates if the `SNES` uses matrix-free finite difference matrix vector products to apply the Jacobian. 13503565c898SBarry Smith 1351420bcc1bSBarry Smith Not Collective, but the resulting flags will be the same on all MPI processes 13523565c898SBarry Smith 13533565c898SBarry Smith Input Parameter: 1354f6dfbefdSBarry Smith . snes - `SNES` context 13553565c898SBarry Smith 13563565c898SBarry Smith Output Parameters: 1357f6dfbefdSBarry Smith + mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used 1358f6dfbefdSBarry 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 13593565c898SBarry Smith 13603565c898SBarry Smith Level: intermediate 13613565c898SBarry Smith 13621cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUseMatrixFree()`, `MatCreateSNESMF()` 13633565c898SBarry Smith @*/ 1364d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUseMatrixFree(SNES snes, PetscBool *mf_operator, PetscBool *mf) 1365d71ae5a4SJacob Faibussowitsch { 13663565c898SBarry Smith PetscFunctionBegin; 13673565c898SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 13683565c898SBarry Smith if (mf) *mf = snes->mf; 13693565c898SBarry Smith if (mf_operator) *mf_operator = snes->mf_operator; 13703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13713565c898SBarry Smith } 13723565c898SBarry Smith 13733565c898SBarry Smith /*@ 1374420bcc1bSBarry Smith SNESGetIterationNumber - Gets the number of nonlinear iterations completed in the current or most recent `SNESSolve()` 13759b94acceSBarry Smith 1376c7afd0dbSLois Curfman McInnes Not Collective 1377c7afd0dbSLois Curfman McInnes 13789b94acceSBarry Smith Input Parameter: 1379f6dfbefdSBarry Smith . snes - `SNES` context 13809b94acceSBarry Smith 13819b94acceSBarry Smith Output Parameter: 13829b94acceSBarry Smith . iter - iteration number 13839b94acceSBarry Smith 1384dc4c0fb0SBarry Smith Level: intermediate 1385dc4c0fb0SBarry Smith 1386c8228a4eSBarry Smith Notes: 1387c8228a4eSBarry Smith For example, during the computation of iteration 2 this would return 1. 1388c8228a4eSBarry Smith 1389c8228a4eSBarry Smith This is useful for using lagged Jacobians (where one does not recompute the 1390f6dfbefdSBarry Smith Jacobian at each `SNES` iteration). For example, the code 139108405cd6SLois Curfman McInnes .vb 139208405cd6SLois Curfman McInnes ierr = SNESGetIterationNumber(snes,&it); 139308405cd6SLois Curfman McInnes if (!(it % 2)) { 139408405cd6SLois Curfman McInnes [compute Jacobian here] 139508405cd6SLois Curfman McInnes } 139608405cd6SLois Curfman McInnes .ve 1397f6dfbefdSBarry Smith can be used in your function that computes the Jacobian to cause the Jacobian to be 1398f6dfbefdSBarry Smith recomputed every second `SNES` iteration. See also `SNESSetLagJacobian()` 1399c8228a4eSBarry Smith 1400f6dfbefdSBarry Smith After the `SNES` solve is complete this will return the number of nonlinear iterations used. 1401c04deec6SBarry Smith 1402420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetLagJacobian()`, `SNESGetLinearSolveIterations()`, `SNESSetMonitor()` 14039b94acceSBarry Smith @*/ 1404d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetIterationNumber(SNES snes, PetscInt *iter) 1405d71ae5a4SJacob Faibussowitsch { 14063a40ed3dSBarry Smith PetscFunctionBegin; 14070700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 14084f572ea9SToby Isaac PetscAssertPointer(iter, 2); 14099b94acceSBarry Smith *iter = snes->iter; 14103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14119b94acceSBarry Smith } 141274679c65SBarry Smith 1413360c497dSPeter Brune /*@ 1414360c497dSPeter Brune SNESSetIterationNumber - Sets the current iteration number. 1415360c497dSPeter Brune 1416360c497dSPeter Brune Not Collective 1417360c497dSPeter Brune 1418d8d19677SJose E. Roman Input Parameters: 1419f6dfbefdSBarry Smith + snes - `SNES` context 1420a2b725a8SWilliam Gropp - iter - iteration number 1421360c497dSPeter Brune 1422360c497dSPeter Brune Level: developer 1423360c497dSPeter Brune 1424420bcc1bSBarry Smith Note: 1425420bcc1bSBarry Smith This should only be called inside a `SNES` nonlinear solver. 1426420bcc1bSBarry Smith 14271cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetLinearSolveIterations()` 1428360c497dSPeter Brune @*/ 1429d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetIterationNumber(SNES snes, PetscInt iter) 1430d71ae5a4SJacob Faibussowitsch { 1431360c497dSPeter Brune PetscFunctionBegin; 1432360c497dSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 14339566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes)); 1434360c497dSPeter Brune snes->iter = iter; 14359566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes)); 14363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1437360c497dSPeter Brune } 1438360c497dSPeter Brune 14399b94acceSBarry Smith /*@ 1440b850b91aSLisandro Dalcin SNESGetNonlinearStepFailures - Gets the number of unsuccessful steps 1441420bcc1bSBarry Smith attempted by the nonlinear solver in the current or most recent `SNESSolve()` . 14429b94acceSBarry Smith 1443c7afd0dbSLois Curfman McInnes Not Collective 1444c7afd0dbSLois Curfman McInnes 14459b94acceSBarry Smith Input Parameter: 1446f6dfbefdSBarry Smith . snes - `SNES` context 14479b94acceSBarry Smith 14489b94acceSBarry Smith Output Parameter: 14499b94acceSBarry Smith . nfails - number of unsuccessful steps attempted 14509b94acceSBarry Smith 1451dc4c0fb0SBarry Smith Level: intermediate 1452dc4c0fb0SBarry Smith 1453f6dfbefdSBarry Smith Note: 1454f6dfbefdSBarry Smith This counter is reset to zero for each successive call to `SNESSolve()`. 1455c96a6f78SLois Curfman McInnes 14561cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, 1457db781477SPatrick Sanan `SNESSetMaxNonlinearStepFailures()`, `SNESGetMaxNonlinearStepFailures()` 14589b94acceSBarry Smith @*/ 1459d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNonlinearStepFailures(SNES snes, PetscInt *nfails) 1460d71ae5a4SJacob Faibussowitsch { 14613a40ed3dSBarry Smith PetscFunctionBegin; 14620700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 14634f572ea9SToby Isaac PetscAssertPointer(nfails, 2); 146450ffb88aSMatthew Knepley *nfails = snes->numFailures; 14653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 146650ffb88aSMatthew Knepley } 146750ffb88aSMatthew Knepley 146850ffb88aSMatthew Knepley /*@ 1469b850b91aSLisandro Dalcin SNESSetMaxNonlinearStepFailures - Sets the maximum number of unsuccessful steps 1470420bcc1bSBarry Smith attempted by the nonlinear solver before it gives up and returns unconverged or generates an error 147150ffb88aSMatthew Knepley 147250ffb88aSMatthew Knepley Not Collective 147350ffb88aSMatthew Knepley 147450ffb88aSMatthew Knepley Input Parameters: 1475f6dfbefdSBarry Smith + snes - `SNES` context 147677e5a1f9SBarry Smith - maxFails - maximum of unsuccessful steps allowed, use `PETSC_UNLIMITED` to have no limit on the number of failures 147750ffb88aSMatthew Knepley 1478420bcc1bSBarry Smith Options Database Key: 1479420bcc1bSBarry Smith . -snes_max_fail <n> - maximum number of unsuccessful steps allowed 1480420bcc1bSBarry Smith 148150ffb88aSMatthew Knepley Level: intermediate 148250ffb88aSMatthew Knepley 1483420bcc1bSBarry Smith Developer Note: 1484420bcc1bSBarry Smith The options database key is wrong for this function name 1485420bcc1bSBarry Smith 14861cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, 1487db781477SPatrick Sanan `SNESGetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()` 148850ffb88aSMatthew Knepley @*/ 1489d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxNonlinearStepFailures(SNES snes, PetscInt maxFails) 1490d71ae5a4SJacob Faibussowitsch { 149150ffb88aSMatthew Knepley PetscFunctionBegin; 14920700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 149377e5a1f9SBarry Smith 149477e5a1f9SBarry Smith if (maxFails == PETSC_UNLIMITED) { 14951690c2aeSBarry Smith snes->maxFailures = PETSC_INT_MAX; 149677e5a1f9SBarry Smith } else { 149777e5a1f9SBarry Smith PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures"); 149850ffb88aSMatthew Knepley snes->maxFailures = maxFails; 149977e5a1f9SBarry Smith } 15003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 150150ffb88aSMatthew Knepley } 150250ffb88aSMatthew Knepley 150350ffb88aSMatthew Knepley /*@ 1504b850b91aSLisandro Dalcin SNESGetMaxNonlinearStepFailures - Gets the maximum number of unsuccessful steps 1505420bcc1bSBarry Smith attempted by the nonlinear solver before it gives up and returns unconverged or generates an error 150650ffb88aSMatthew Knepley 150750ffb88aSMatthew Knepley Not Collective 150850ffb88aSMatthew Knepley 150950ffb88aSMatthew Knepley Input Parameter: 151020f4b53cSBarry Smith . snes - `SNES` context 151150ffb88aSMatthew Knepley 151250ffb88aSMatthew Knepley Output Parameter: 151350ffb88aSMatthew Knepley . maxFails - maximum of unsuccessful steps 151450ffb88aSMatthew Knepley 151550ffb88aSMatthew Knepley Level: intermediate 151650ffb88aSMatthew Knepley 15171cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, 1518db781477SPatrick Sanan `SNESSetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()` 151950ffb88aSMatthew Knepley @*/ 1520d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxNonlinearStepFailures(SNES snes, PetscInt *maxFails) 1521d71ae5a4SJacob Faibussowitsch { 152250ffb88aSMatthew Knepley PetscFunctionBegin; 15230700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 15244f572ea9SToby Isaac PetscAssertPointer(maxFails, 2); 152550ffb88aSMatthew Knepley *maxFails = snes->maxFailures; 15263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15279b94acceSBarry Smith } 1528a847f771SSatish Balay 15292541af92SBarry Smith /*@ 15302541af92SBarry Smith SNESGetNumberFunctionEvals - Gets the number of user provided function evaluations 1531420bcc1bSBarry Smith done by the `SNES` object in the current or most recent `SNESSolve()` 15322541af92SBarry Smith 15332541af92SBarry Smith Not Collective 15342541af92SBarry Smith 15352541af92SBarry Smith Input Parameter: 1536f6dfbefdSBarry Smith . snes - `SNES` context 15372541af92SBarry Smith 15382541af92SBarry Smith Output Parameter: 15392541af92SBarry Smith . nfuncs - number of evaluations 15402541af92SBarry Smith 15412541af92SBarry Smith Level: intermediate 15422541af92SBarry Smith 1543f6dfbefdSBarry Smith Note: 1544f6dfbefdSBarry Smith Reset every time `SNESSolve()` is called unless `SNESSetCountersReset()` is used. 1545971e163fSPeter Brune 15461cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, `SNESSetCountersReset()` 15472541af92SBarry Smith @*/ 1548d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNumberFunctionEvals(SNES snes, PetscInt *nfuncs) 1549d71ae5a4SJacob Faibussowitsch { 15502541af92SBarry Smith PetscFunctionBegin; 15510700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 15524f572ea9SToby Isaac PetscAssertPointer(nfuncs, 2); 15532541af92SBarry Smith *nfuncs = snes->nfuncs; 15543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15552541af92SBarry Smith } 15562541af92SBarry Smith 15573d4c4710SBarry Smith /*@ 15583d4c4710SBarry Smith SNESGetLinearSolveFailures - Gets the number of failed (non-converged) 1559420bcc1bSBarry Smith linear solvers in the current or most recent `SNESSolve()` 15603d4c4710SBarry Smith 15613d4c4710SBarry Smith Not Collective 15623d4c4710SBarry Smith 15633d4c4710SBarry Smith Input Parameter: 1564f6dfbefdSBarry Smith . snes - `SNES` context 15653d4c4710SBarry Smith 15663d4c4710SBarry Smith Output Parameter: 15673d4c4710SBarry Smith . nfails - number of failed solves 15683d4c4710SBarry Smith 1569f6dfbefdSBarry Smith Options Database Key: 15709d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated 15719d85da0cSMatthew G. Knepley 1572f6dfbefdSBarry Smith Level: intermediate 1573f6dfbefdSBarry Smith 1574f6dfbefdSBarry Smith Note: 1575f6dfbefdSBarry Smith This counter is reset to zero for each successive call to `SNESSolve()`. 15763d4c4710SBarry Smith 15771cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()` 15783d4c4710SBarry Smith @*/ 1579d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveFailures(SNES snes, PetscInt *nfails) 1580d71ae5a4SJacob Faibussowitsch { 15813d4c4710SBarry Smith PetscFunctionBegin; 15820700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 15834f572ea9SToby Isaac PetscAssertPointer(nfails, 2); 15843d4c4710SBarry Smith *nfails = snes->numLinearSolveFailures; 15853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15863d4c4710SBarry Smith } 15873d4c4710SBarry Smith 15883d4c4710SBarry Smith /*@ 15893d4c4710SBarry Smith SNESSetMaxLinearSolveFailures - the number of failed linear solve attempts 1590f6dfbefdSBarry Smith allowed before `SNES` returns with a diverged reason of `SNES_DIVERGED_LINEAR_SOLVE` 15913d4c4710SBarry Smith 1592c3339decSBarry Smith Logically Collective 15933d4c4710SBarry Smith 15943d4c4710SBarry Smith Input Parameters: 1595f6dfbefdSBarry Smith + snes - `SNES` context 159677e5a1f9SBarry Smith - maxFails - maximum allowed linear solve failures, use `PETSC_UNLIMITED` to have no limit on the number of failures 15973d4c4710SBarry Smith 1598f6dfbefdSBarry Smith Options Database Key: 15999d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated 16009d85da0cSMatthew G. Knepley 1601dc4c0fb0SBarry Smith Level: intermediate 1602dc4c0fb0SBarry Smith 1603f6dfbefdSBarry Smith Note: 1604f6dfbefdSBarry Smith By default this is 0; that is `SNES` returns on the first failed linear solve 16053d4c4710SBarry Smith 1606420bcc1bSBarry Smith Developer Note: 1607420bcc1bSBarry Smith The options database key is wrong for this function name 1608420bcc1bSBarry Smith 16091cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()` 16103d4c4710SBarry Smith @*/ 1611d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxLinearSolveFailures(SNES snes, PetscInt maxFails) 1612d71ae5a4SJacob Faibussowitsch { 16133d4c4710SBarry Smith PetscFunctionBegin; 16140700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1615c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, maxFails, 2); 161677e5a1f9SBarry Smith 161777e5a1f9SBarry Smith if (maxFails == PETSC_UNLIMITED) { 16181690c2aeSBarry Smith snes->maxLinearSolveFailures = PETSC_INT_MAX; 161977e5a1f9SBarry Smith } else { 162077e5a1f9SBarry Smith PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures"); 16213d4c4710SBarry Smith snes->maxLinearSolveFailures = maxFails; 162277e5a1f9SBarry Smith } 16233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16243d4c4710SBarry Smith } 16253d4c4710SBarry Smith 16263d4c4710SBarry Smith /*@ 16273d4c4710SBarry Smith SNESGetMaxLinearSolveFailures - gets the maximum number of linear solve failures that 1628f6dfbefdSBarry Smith are allowed before `SNES` returns as unsuccessful 16293d4c4710SBarry Smith 16303d4c4710SBarry Smith Not Collective 16313d4c4710SBarry Smith 16323d4c4710SBarry Smith Input Parameter: 1633f6dfbefdSBarry Smith . snes - `SNES` context 16343d4c4710SBarry Smith 16353d4c4710SBarry Smith Output Parameter: 16363d4c4710SBarry Smith . maxFails - maximum of unsuccessful solves allowed 16373d4c4710SBarry Smith 16383d4c4710SBarry Smith Level: intermediate 16393d4c4710SBarry Smith 1640f6dfbefdSBarry Smith Note: 1641f6dfbefdSBarry Smith By default this is 1; that is `SNES` returns on the first failed linear solve 16423d4c4710SBarry Smith 16431cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, 16443d4c4710SBarry Smith @*/ 1645d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxLinearSolveFailures(SNES snes, PetscInt *maxFails) 1646d71ae5a4SJacob Faibussowitsch { 16473d4c4710SBarry Smith PetscFunctionBegin; 16480700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 16494f572ea9SToby Isaac PetscAssertPointer(maxFails, 2); 16503d4c4710SBarry Smith *maxFails = snes->maxLinearSolveFailures; 16513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16523d4c4710SBarry Smith } 16533d4c4710SBarry Smith 1654c96a6f78SLois Curfman McInnes /*@ 1655b850b91aSLisandro Dalcin SNESGetLinearSolveIterations - Gets the total number of linear iterations 1656420bcc1bSBarry Smith used by the nonlinear solver in the most recent `SNESSolve()` 1657c96a6f78SLois Curfman McInnes 1658c7afd0dbSLois Curfman McInnes Not Collective 1659c7afd0dbSLois Curfman McInnes 1660c96a6f78SLois Curfman McInnes Input Parameter: 1661f6dfbefdSBarry Smith . snes - `SNES` context 1662c96a6f78SLois Curfman McInnes 1663c96a6f78SLois Curfman McInnes Output Parameter: 1664c96a6f78SLois Curfman McInnes . lits - number of linear iterations 1665c96a6f78SLois Curfman McInnes 1666dc4c0fb0SBarry Smith Level: intermediate 1667dc4c0fb0SBarry Smith 1668c96a6f78SLois Curfman McInnes Notes: 1669f6dfbefdSBarry Smith This counter is reset to zero for each successive call to `SNESSolve()` unless `SNESSetCountersReset()` is used. 1670c96a6f78SLois Curfman McInnes 1671f6dfbefdSBarry 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 1672f6dfbefdSBarry Smith then call `KSPGetIterationNumber()` after the failed solve. 1673010be392SBarry Smith 16741cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetIterationNumber()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESSetCountersReset()` 1675c96a6f78SLois Curfman McInnes @*/ 1676d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveIterations(SNES snes, PetscInt *lits) 1677d71ae5a4SJacob Faibussowitsch { 16783a40ed3dSBarry Smith PetscFunctionBegin; 16790700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 16804f572ea9SToby Isaac PetscAssertPointer(lits, 2); 1681c96a6f78SLois Curfman McInnes *lits = snes->linear_its; 16823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1683c96a6f78SLois Curfman McInnes } 1684c96a6f78SLois Curfman McInnes 1685971e163fSPeter Brune /*@ 1686971e163fSPeter Brune SNESSetCountersReset - Sets whether or not the counters for linear iterations and function evaluations 1687f6dfbefdSBarry Smith are reset every time `SNESSolve()` is called. 1688971e163fSPeter Brune 1689c3339decSBarry Smith Logically Collective 1690971e163fSPeter Brune 1691d8d19677SJose E. Roman Input Parameters: 1692f6dfbefdSBarry Smith + snes - `SNES` context 1693f6dfbefdSBarry Smith - reset - whether to reset the counters or not, defaults to `PETSC_TRUE` 1694971e163fSPeter Brune 1695971e163fSPeter Brune Level: developer 1696971e163fSPeter Brune 16971cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()` 1698971e163fSPeter Brune @*/ 1699d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCountersReset(SNES snes, PetscBool reset) 1700d71ae5a4SJacob Faibussowitsch { 1701971e163fSPeter Brune PetscFunctionBegin; 1702971e163fSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1703971e163fSPeter Brune PetscValidLogicalCollectiveBool(snes, reset, 2); 1704971e163fSPeter Brune snes->counters_reset = reset; 17053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1706971e163fSPeter Brune } 1707971e163fSPeter Brune 17082999313aSBarry Smith /*@ 170912b1dd1aSStefano Zampini SNESResetCounters - Reset counters for linear iterations and function evaluations. 171012b1dd1aSStefano Zampini 171112b1dd1aSStefano Zampini Logically Collective 171212b1dd1aSStefano Zampini 171312b1dd1aSStefano Zampini Input Parameters: 171412b1dd1aSStefano Zampini . snes - `SNES` context 171512b1dd1aSStefano Zampini 171612b1dd1aSStefano Zampini Level: developer 171712b1dd1aSStefano Zampini 171812b1dd1aSStefano Zampini Note: 171912b1dd1aSStefano Zampini It honors the flag set with `SNESSetCountersReset()` 172012b1dd1aSStefano Zampini 172112b1dd1aSStefano Zampini .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()` 172212b1dd1aSStefano Zampini @*/ 172312b1dd1aSStefano Zampini PetscErrorCode SNESResetCounters(SNES snes) 172412b1dd1aSStefano Zampini { 172512b1dd1aSStefano Zampini PetscFunctionBegin; 172612b1dd1aSStefano Zampini PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 172712b1dd1aSStefano Zampini if (snes->counters_reset) { 172812b1dd1aSStefano Zampini snes->nfuncs = 0; 172912b1dd1aSStefano Zampini snes->linear_its = 0; 173012b1dd1aSStefano Zampini snes->numFailures = 0; 173112b1dd1aSStefano Zampini } 173212b1dd1aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 173312b1dd1aSStefano Zampini } 173412b1dd1aSStefano Zampini 173512b1dd1aSStefano Zampini /*@ 1736f6dfbefdSBarry Smith SNESSetKSP - Sets a `KSP` context for the `SNES` object to use 17372999313aSBarry Smith 1738420bcc1bSBarry Smith Not Collective, but the `SNES` and `KSP` objects must live on the same `MPI_Comm` 17392999313aSBarry Smith 17402999313aSBarry Smith Input Parameters: 1741f6dfbefdSBarry Smith + snes - the `SNES` context 1742f6dfbefdSBarry Smith - ksp - the `KSP` context 17432999313aSBarry Smith 1744dc4c0fb0SBarry Smith Level: developer 1745dc4c0fb0SBarry Smith 17462999313aSBarry Smith Notes: 1747f6dfbefdSBarry Smith The `SNES` object already has its `KSP` object, you can obtain with `SNESGetKSP()` 17482999313aSBarry Smith so this routine is rarely needed. 17492999313aSBarry Smith 1750f6dfbefdSBarry Smith The `KSP` object that is already in the `SNES` object has its reference count 1751420bcc1bSBarry Smith decreased by one when this is called. 17522999313aSBarry Smith 175342747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `KSP`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()` 17542999313aSBarry Smith @*/ 1755d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetKSP(SNES snes, KSP ksp) 1756d71ae5a4SJacob Faibussowitsch { 17572999313aSBarry Smith PetscFunctionBegin; 17580700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 17590700a824SBarry Smith PetscValidHeaderSpecific(ksp, KSP_CLASSID, 2); 17602999313aSBarry Smith PetscCheckSameComm(snes, 1, ksp, 2); 17619566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)ksp)); 17629566063dSJacob Faibussowitsch if (snes->ksp) PetscCall(PetscObjectDereference((PetscObject)snes->ksp)); 17632999313aSBarry Smith snes->ksp = ksp; 17643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17652999313aSBarry Smith } 17662999313aSBarry Smith 176752baeb72SSatish Balay /*@ 176877e5a1f9SBarry Smith SNESParametersInitialize - Sets all the parameters in `snes` to their default value (when `SNESCreate()` was called) if they 176977e5a1f9SBarry Smith currently contain default values 177077e5a1f9SBarry Smith 177177e5a1f9SBarry Smith Collective 177277e5a1f9SBarry Smith 177377e5a1f9SBarry Smith Input Parameter: 177477e5a1f9SBarry Smith . snes - the `SNES` object 177577e5a1f9SBarry Smith 177677e5a1f9SBarry Smith Level: developer 177777e5a1f9SBarry Smith 177877e5a1f9SBarry Smith Developer Note: 177977e5a1f9SBarry Smith This is called by all the `SNESCreate_XXX()` routines. 178077e5a1f9SBarry Smith 178177e5a1f9SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`, 178277e5a1f9SBarry Smith `PetscObjectParameterSetDefault()` 178377e5a1f9SBarry Smith @*/ 178477e5a1f9SBarry Smith PetscErrorCode SNESParametersInitialize(SNES snes) 178577e5a1f9SBarry Smith { 178677e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, max_its, 50); 178777e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, max_funcs, 10000); 178877e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, rtol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8); 178977e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, abstol, PetscDefined(USE_REAL_SINGLE) ? 1.e-25 : 1.e-50); 179077e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, stol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8); 179177e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, divtol, 1.e4); 179277e5a1f9SBarry Smith return PETSC_SUCCESS; 179377e5a1f9SBarry Smith } 179477e5a1f9SBarry Smith 179577e5a1f9SBarry Smith /*@ 1796dc4c0fb0SBarry Smith SNESCreate - Creates a nonlinear solver context used to manage a set of nonlinear solves 17979b94acceSBarry Smith 1798d083f849SBarry Smith Collective 1799c7afd0dbSLois Curfman McInnes 1800f6dfbefdSBarry Smith Input Parameter: 1801906ed7ccSBarry Smith . comm - MPI communicator 18029b94acceSBarry Smith 18039b94acceSBarry Smith Output Parameter: 180420f4b53cSBarry Smith . outsnes - the new `SNES` context 18059b94acceSBarry Smith 1806c7afd0dbSLois Curfman McInnes Options Database Keys: 18077addb90fSBarry Smith + -snes_mf - Activates default matrix-free Jacobian-vector products, and no matrix to construct a preconditioner 18087addb90fSBarry Smith . -snes_mf_operator - Activates default matrix-free Jacobian-vector products, and a user-provided matrix as set by `SNESSetJacobian()` 1809dc4c0fb0SBarry Smith . -snes_fd_coloring - uses a relative fast computation of the Jacobian using finite differences and a graph coloring 1810c7afd0dbSLois Curfman McInnes - -snes_fd - Uses (slow!) finite differences to compute Jacobian 1811c1f60f51SBarry Smith 181236851e7fSLois Curfman McInnes Level: beginner 181336851e7fSLois Curfman McInnes 181495452b02SPatrick Sanan Developer Notes: 1815f6dfbefdSBarry Smith `SNES` always creates a `KSP` object even though many `SNES` methods do not use it. This is 1816efd4aadfSBarry Smith unfortunate and should be fixed at some point. The flag snes->usesksp indicates if the 1817f6dfbefdSBarry Smith particular method does use `KSP` and regulates if the information about the `KSP` is printed 1818f6dfbefdSBarry Smith in `SNESView()`. 1819efd4aadfSBarry Smith 1820f6dfbefdSBarry Smith `TSSetFromOptions()` does call `SNESSetFromOptions()` which can lead to users being confused 1821f6dfbefdSBarry Smith by help messages about meaningless `SNES` options. 1822f6dfbefdSBarry Smith 18237addb90fSBarry Smith `SNES` always creates the `snes->kspconvctx` even though it is used by only one type. This should be fixed. 1824efd4aadfSBarry Smith 1825e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()` 18269b94acceSBarry Smith @*/ 1827d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESCreate(MPI_Comm comm, SNES *outsnes) 1828d71ae5a4SJacob Faibussowitsch { 18299b94acceSBarry Smith SNES snes; 1830fa9f3622SBarry Smith SNESKSPEW *kctx; 183137fcc0dbSBarry Smith 18323a40ed3dSBarry Smith PetscFunctionBegin; 18334f572ea9SToby Isaac PetscAssertPointer(outsnes, 2); 18349566063dSJacob Faibussowitsch PetscCall(SNESInitializePackage()); 18358ba1e511SMatthew Knepley 18369566063dSJacob Faibussowitsch PetscCall(PetscHeaderCreate(snes, SNES_CLASSID, "SNES", "Nonlinear solver", "SNES", comm, SNESDestroy, SNESView)); 18378d359177SBarry Smith snes->ops->converged = SNESConvergedDefault; 18382c155ee1SBarry Smith snes->usesksp = PETSC_TRUE; 18399b94acceSBarry Smith snes->norm = 0.0; 1840c1e67a49SFande Kong snes->xnorm = 0.0; 1841c1e67a49SFande Kong snes->ynorm = 0.0; 1842365a6726SPeter Brune snes->normschedule = SNES_NORM_ALWAYS; 18436c67d002SPeter Brune snes->functype = SNES_FUNCTION_DEFAULT; 1844b4874afaSBarry Smith snes->ttol = 0.0; 184577e5a1f9SBarry Smith 1846e37c518bSBarry Smith snes->rnorm0 = 0; 18479b94acceSBarry Smith snes->nfuncs = 0; 184850ffb88aSMatthew Knepley snes->numFailures = 0; 184950ffb88aSMatthew Knepley snes->maxFailures = 1; 18507a00f4a9SLois Curfman McInnes snes->linear_its = 0; 1851e35cf81dSBarry Smith snes->lagjacobian = 1; 185237ec4e1aSPeter Brune snes->jac_iter = 0; 185337ec4e1aSPeter Brune snes->lagjac_persist = PETSC_FALSE; 1854a8054027SBarry Smith snes->lagpreconditioner = 1; 185537ec4e1aSPeter Brune snes->pre_iter = 0; 185637ec4e1aSPeter Brune snes->lagpre_persist = PETSC_FALSE; 1857639f9d9dSBarry Smith snes->numbermonitors = 0; 1858c4421ceaSFande Kong snes->numberreasonviews = 0; 18599e5d0892SLisandro Dalcin snes->data = NULL; 18604dc4c822SBarry Smith snes->setupcalled = PETSC_FALSE; 1861186905e3SBarry Smith snes->ksp_ewconv = PETSC_FALSE; 18626f24a144SLois Curfman McInnes snes->nwork = 0; 18639e5d0892SLisandro Dalcin snes->work = NULL; 186458c9b817SLisandro Dalcin snes->nvwork = 0; 18659e5d0892SLisandro Dalcin snes->vwork = NULL; 1866758f92a0SBarry Smith snes->conv_hist_len = 0; 1867758f92a0SBarry Smith snes->conv_hist_max = 0; 18680298fd71SBarry Smith snes->conv_hist = NULL; 18690298fd71SBarry Smith snes->conv_hist_its = NULL; 1870758f92a0SBarry Smith snes->conv_hist_reset = PETSC_TRUE; 1871971e163fSPeter Brune snes->counters_reset = PETSC_TRUE; 1872e4ed7901SPeter Brune snes->vec_func_init_set = PETSC_FALSE; 1873184914b5SBarry Smith snes->reason = SNES_CONVERGED_ITERATING; 1874efd4aadfSBarry Smith snes->npcside = PC_RIGHT; 1875b3cd9a81SMatthew G. Knepley snes->setfromoptionscalled = 0; 1876c40d0f55SPeter Brune 1877d8f46077SPeter Brune snes->mf = PETSC_FALSE; 1878d8f46077SPeter Brune snes->mf_operator = PETSC_FALSE; 1879d8f46077SPeter Brune snes->mf_version = 1; 1880d8f46077SPeter Brune 18813d4c4710SBarry Smith snes->numLinearSolveFailures = 0; 18823d4c4710SBarry Smith snes->maxLinearSolveFailures = 1; 18833d4c4710SBarry Smith 1884349187a7SBarry Smith snes->vizerotolerance = 1.e-8; 188576bd3646SJed Brown snes->checkjacdomainerror = PetscDefined(USE_DEBUG) ? PETSC_TRUE : PETSC_FALSE; 1886349187a7SBarry Smith 18874fc747eaSLawrence Mitchell /* Set this to true if the implementation of SNESSolve_XXX does compute the residual at the final solution. */ 18884fc747eaSLawrence Mitchell snes->alwayscomputesfinalresidual = PETSC_FALSE; 18894fc747eaSLawrence Mitchell 18909b94acceSBarry Smith /* Create context to compute Eisenstat-Walker relative tolerance for KSP */ 18914dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&kctx)); 1892f5af7f23SKarl Rupp 1893835f2295SStefano Zampini snes->kspconvctx = kctx; 18949b94acceSBarry Smith kctx->version = 2; 18950f0abf79SStefano Zampini kctx->rtol_0 = 0.3; /* Eisenstat and Walker suggest rtol_0=.5, but 18969b94acceSBarry Smith this was too large for some test cases */ 189775567043SBarry Smith kctx->rtol_last = 0.0; 18980f0abf79SStefano Zampini kctx->rtol_max = 0.9; 18999b94acceSBarry Smith kctx->gamma = 1.0; 19000f0abf79SStefano Zampini kctx->alpha = 0.5 * (1.0 + PetscSqrtReal(5.0)); 190171f87433Sdalcinl kctx->alpha2 = kctx->alpha; 19020f0abf79SStefano Zampini kctx->threshold = 0.1; 190375567043SBarry Smith kctx->lresid_last = 0.0; 190475567043SBarry Smith kctx->norm_last = 0.0; 19059b94acceSBarry Smith 19060f0abf79SStefano Zampini kctx->rk_last = 0.0; 19070f0abf79SStefano Zampini kctx->rk_last_2 = 0.0; 19080f0abf79SStefano Zampini kctx->rtol_last_2 = 0.0; 19090f0abf79SStefano Zampini kctx->v4_p1 = 0.1; 19100f0abf79SStefano Zampini kctx->v4_p2 = 0.4; 19110f0abf79SStefano Zampini kctx->v4_p3 = 0.7; 19120f0abf79SStefano Zampini kctx->v4_m1 = 0.8; 19130f0abf79SStefano Zampini kctx->v4_m2 = 0.5; 19140f0abf79SStefano Zampini kctx->v4_m3 = 0.1; 19150f0abf79SStefano Zampini kctx->v4_m4 = 0.5; 19160f0abf79SStefano Zampini 1917b50c806fSBarry Smith PetscCall(SNESParametersInitialize(snes)); 19189b94acceSBarry Smith *outsnes = snes; 19193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19209b94acceSBarry Smith } 19219b94acceSBarry Smith 19229b94acceSBarry Smith /*@C 19239b94acceSBarry Smith SNESSetFunction - Sets the function evaluation routine and function 1924f6dfbefdSBarry Smith vector for use by the `SNES` routines in solving systems of nonlinear 19259b94acceSBarry Smith equations. 19269b94acceSBarry Smith 1927c3339decSBarry Smith Logically Collective 1928fee21e36SBarry Smith 1929c7afd0dbSLois Curfman McInnes Input Parameters: 1930f6dfbefdSBarry Smith + snes - the `SNES` context 1931dc4c0fb0SBarry Smith . r - vector to store function values, may be `NULL` 19328434afd1SBarry Smith . f - function evaluation routine; for calling sequence see `SNESFunctionFn` 1933c7afd0dbSLois Curfman McInnes - ctx - [optional] user-defined context for private data for the 1934dc4c0fb0SBarry Smith function evaluation routine (may be `NULL`) 19359b94acceSBarry Smith 193636851e7fSLois Curfman McInnes Level: beginner 193736851e7fSLois Curfman McInnes 19388434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetPicard()`, `SNESFunctionFn` 19399b94acceSBarry Smith @*/ 19408434afd1SBarry Smith PetscErrorCode SNESSetFunction(SNES snes, Vec r, SNESFunctionFn *f, void *ctx) 1941d71ae5a4SJacob Faibussowitsch { 19426cab3a1bSJed Brown DM dm; 19436cab3a1bSJed Brown 19443a40ed3dSBarry Smith PetscFunctionBegin; 19450700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1946d2a683ecSLisandro Dalcin if (r) { 1947d2a683ecSLisandro Dalcin PetscValidHeaderSpecific(r, VEC_CLASSID, 2); 1948d2a683ecSLisandro Dalcin PetscCheckSameComm(snes, 1, r, 2); 19499566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)r)); 19509566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_func)); 195185385478SLisandro Dalcin snes->vec_func = r; 1952d2a683ecSLisandro Dalcin } 19539566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 19549566063dSJacob Faibussowitsch PetscCall(DMSNESSetFunction(dm, f, ctx)); 195548a46eb9SPierre Jolivet if (f == SNESPicardComputeFunction) PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx)); 19563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19579b94acceSBarry Smith } 19589b94acceSBarry Smith 1959e4ed7901SPeter Brune /*@C 19600b4db180SJacob Faibussowitsch SNESSetInitialFunction - Set an already computed function evaluation at the initial guess to be reused by `SNESSolve()`. 1961e4ed7901SPeter Brune 1962c3339decSBarry Smith Logically Collective 1963e4ed7901SPeter Brune 1964e4ed7901SPeter Brune Input Parameters: 1965f6dfbefdSBarry Smith + snes - the `SNES` context 1966e4ed7901SPeter Brune - f - vector to store function value 1967e4ed7901SPeter Brune 1968dc4c0fb0SBarry Smith Level: developer 1969dc4c0fb0SBarry Smith 1970e4ed7901SPeter Brune Notes: 1971e4ed7901SPeter Brune This should not be modified during the solution procedure. 1972e4ed7901SPeter Brune 1973f6dfbefdSBarry Smith This is used extensively in the `SNESFAS` hierarchy and in nonlinear preconditioning. 1974e4ed7901SPeter Brune 19751cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetInitialFunctionNorm()` 1976e4ed7901SPeter Brune @*/ 1977d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetInitialFunction(SNES snes, Vec f) 1978d71ae5a4SJacob Faibussowitsch { 1979e4ed7901SPeter Brune Vec vec_func; 1980e4ed7901SPeter Brune 1981e4ed7901SPeter Brune PetscFunctionBegin; 1982e4ed7901SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1983e4ed7901SPeter Brune PetscValidHeaderSpecific(f, VEC_CLASSID, 2); 1984e4ed7901SPeter Brune PetscCheckSameComm(snes, 1, f, 2); 1985efd4aadfSBarry Smith if (snes->npcside == PC_LEFT && snes->functype == SNES_FUNCTION_PRECONDITIONED) { 1986902f982fSPeter Brune snes->vec_func_init_set = PETSC_FALSE; 19873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1988902f982fSPeter Brune } 19899566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &vec_func, NULL, NULL)); 19909566063dSJacob Faibussowitsch PetscCall(VecCopy(f, vec_func)); 1991f5af7f23SKarl Rupp 1992217b9c2eSPeter Brune snes->vec_func_init_set = PETSC_TRUE; 19933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1994e4ed7901SPeter Brune } 1995e4ed7901SPeter Brune 1996534ebe21SPeter Brune /*@ 1997f6dfbefdSBarry Smith SNESSetNormSchedule - Sets the `SNESNormSchedule` used in convergence and monitoring 1998f6dfbefdSBarry Smith of the `SNES` method, when norms are computed in the solving process 1999534ebe21SPeter Brune 2000c3339decSBarry Smith Logically Collective 2001534ebe21SPeter Brune 2002534ebe21SPeter Brune Input Parameters: 2003f6dfbefdSBarry Smith + snes - the `SNES` context 2004365a6726SPeter Brune - normschedule - the frequency of norm computation 2005534ebe21SPeter Brune 2006517f1916SMatthew G. Knepley Options Database Key: 200767b8a455SSatish Balay . -snes_norm_schedule <none, always, initialonly, finalonly, initialfinalonly> - set the schedule 2008517f1916SMatthew G. Knepley 2009dc4c0fb0SBarry Smith Level: advanced 2010dc4c0fb0SBarry Smith 2011534ebe21SPeter Brune Notes: 2012f6dfbefdSBarry Smith Only certain `SNES` methods support certain `SNESNormSchedules`. Most require evaluation 2013534ebe21SPeter Brune of the nonlinear function and the taking of its norm at every iteration to 2014534ebe21SPeter Brune even ensure convergence at all. However, methods such as custom Gauss-Seidel methods 2015f6dfbefdSBarry Smith `SNESNGS` and the like do not require the norm of the function to be computed, and therefore 2016534ebe21SPeter Brune may either be monitored for convergence or not. As these are often used as nonlinear 2017534ebe21SPeter Brune preconditioners, monitoring the norm of their error is not a useful enterprise within 2018534ebe21SPeter Brune their solution. 2019534ebe21SPeter Brune 2020e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNESNormSchedule`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()` 2021534ebe21SPeter Brune @*/ 2022d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNormSchedule(SNES snes, SNESNormSchedule normschedule) 2023d71ae5a4SJacob Faibussowitsch { 2024534ebe21SPeter Brune PetscFunctionBegin; 2025534ebe21SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2026365a6726SPeter Brune snes->normschedule = normschedule; 20273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2028534ebe21SPeter Brune } 2029534ebe21SPeter Brune 2030534ebe21SPeter Brune /*@ 2031f6dfbefdSBarry Smith SNESGetNormSchedule - Gets the `SNESNormSchedule` used in convergence and monitoring 2032f6dfbefdSBarry Smith of the `SNES` method. 2033534ebe21SPeter Brune 2034c3339decSBarry Smith Logically Collective 2035534ebe21SPeter Brune 2036534ebe21SPeter Brune Input Parameters: 2037f6dfbefdSBarry Smith + snes - the `SNES` context 2038365a6726SPeter Brune - normschedule - the type of the norm used 2039534ebe21SPeter Brune 2040534ebe21SPeter Brune Level: advanced 2041534ebe21SPeter Brune 20421cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 2043534ebe21SPeter Brune @*/ 2044d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNormSchedule(SNES snes, SNESNormSchedule *normschedule) 2045d71ae5a4SJacob Faibussowitsch { 2046534ebe21SPeter Brune PetscFunctionBegin; 2047534ebe21SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2048365a6726SPeter Brune *normschedule = snes->normschedule; 20493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2050534ebe21SPeter Brune } 2051534ebe21SPeter Brune 2052c5ce4427SMatthew G. Knepley /*@ 2053c5ce4427SMatthew G. Knepley SNESSetFunctionNorm - Sets the last computed residual norm. 2054c5ce4427SMatthew G. Knepley 2055c3339decSBarry Smith Logically Collective 2056c5ce4427SMatthew G. Knepley 2057c5ce4427SMatthew G. Knepley Input Parameters: 2058f6dfbefdSBarry Smith + snes - the `SNES` context 2059f6dfbefdSBarry Smith - norm - the value of the norm 2060c5ce4427SMatthew G. Knepley 2061c5ce4427SMatthew G. Knepley Level: developer 2062c5ce4427SMatthew G. Knepley 20631cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 2064c5ce4427SMatthew G. Knepley @*/ 2065d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionNorm(SNES snes, PetscReal norm) 2066d71ae5a4SJacob Faibussowitsch { 2067c5ce4427SMatthew G. Knepley PetscFunctionBegin; 2068c5ce4427SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2069c5ce4427SMatthew G. Knepley snes->norm = norm; 20703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2071c5ce4427SMatthew G. Knepley } 2072c5ce4427SMatthew G. Knepley 2073c5ce4427SMatthew G. Knepley /*@ 2074c5ce4427SMatthew G. Knepley SNESGetFunctionNorm - Gets the last computed norm of the residual 2075c5ce4427SMatthew G. Knepley 2076c5ce4427SMatthew G. Knepley Not Collective 2077c5ce4427SMatthew G. Knepley 2078c5ce4427SMatthew G. Knepley Input Parameter: 2079f6dfbefdSBarry Smith . snes - the `SNES` context 2080c5ce4427SMatthew G. Knepley 2081c5ce4427SMatthew G. Knepley Output Parameter: 2082c5ce4427SMatthew G. Knepley . norm - the last computed residual norm 2083c5ce4427SMatthew G. Knepley 2084c5ce4427SMatthew G. Knepley Level: developer 2085c5ce4427SMatthew G. Knepley 20861cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 2087c5ce4427SMatthew G. Knepley @*/ 2088d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionNorm(SNES snes, PetscReal *norm) 2089d71ae5a4SJacob Faibussowitsch { 2090c5ce4427SMatthew G. Knepley PetscFunctionBegin; 2091c5ce4427SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 20924f572ea9SToby Isaac PetscAssertPointer(norm, 2); 2093c5ce4427SMatthew G. Knepley *norm = snes->norm; 20943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2095c5ce4427SMatthew G. Knepley } 2096c5ce4427SMatthew G. Knepley 2097c1e67a49SFande Kong /*@ 2098f6dfbefdSBarry Smith SNESGetUpdateNorm - Gets the last computed norm of the solution update 2099c1e67a49SFande Kong 2100c1e67a49SFande Kong Not Collective 2101c1e67a49SFande Kong 2102c1e67a49SFande Kong Input Parameter: 2103f6dfbefdSBarry Smith . snes - the `SNES` context 2104c1e67a49SFande Kong 2105c1e67a49SFande Kong Output Parameter: 2106c1e67a49SFande Kong . ynorm - the last computed update norm 2107c1e67a49SFande Kong 2108c1e67a49SFande Kong Level: developer 2109c1e67a49SFande Kong 2110f6dfbefdSBarry Smith Note: 2111f6dfbefdSBarry Smith The new solution is the current solution plus the update, so this norm is an indication of the size of the update 2112f6dfbefdSBarry Smith 21131cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()` 2114c1e67a49SFande Kong @*/ 2115d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUpdateNorm(SNES snes, PetscReal *ynorm) 2116d71ae5a4SJacob Faibussowitsch { 2117c1e67a49SFande Kong PetscFunctionBegin; 2118c1e67a49SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 21194f572ea9SToby Isaac PetscAssertPointer(ynorm, 2); 2120c1e67a49SFande Kong *ynorm = snes->ynorm; 21213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2122c1e67a49SFande Kong } 2123c1e67a49SFande Kong 2124c1e67a49SFande Kong /*@ 21254591eaf2SFande Kong SNESGetSolutionNorm - Gets the last computed norm of the solution 2126c1e67a49SFande Kong 2127c1e67a49SFande Kong Not Collective 2128c1e67a49SFande Kong 2129c1e67a49SFande Kong Input Parameter: 2130f6dfbefdSBarry Smith . snes - the `SNES` context 2131c1e67a49SFande Kong 2132c1e67a49SFande Kong Output Parameter: 2133c1e67a49SFande Kong . xnorm - the last computed solution norm 2134c1e67a49SFande Kong 2135c1e67a49SFande Kong Level: developer 2136c1e67a49SFande Kong 21371cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`, `SNESGetUpdateNorm()` 2138c1e67a49SFande Kong @*/ 2139d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionNorm(SNES snes, PetscReal *xnorm) 2140d71ae5a4SJacob Faibussowitsch { 2141c1e67a49SFande Kong PetscFunctionBegin; 2142c1e67a49SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 21434f572ea9SToby Isaac PetscAssertPointer(xnorm, 2); 2144c1e67a49SFande Kong *xnorm = snes->xnorm; 21453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2146c1e67a49SFande Kong } 2147c1e67a49SFande Kong 2148cc4c1da9SBarry Smith /*@ 2149f6dfbefdSBarry Smith SNESSetFunctionType - Sets the `SNESFunctionType` 2150f6dfbefdSBarry Smith of the `SNES` method. 215147073ea2SPeter Brune 2152c3339decSBarry Smith Logically Collective 215347073ea2SPeter Brune 215447073ea2SPeter Brune Input Parameters: 2155f6dfbefdSBarry Smith + snes - the `SNES` context 2156f6dfbefdSBarry Smith - type - the function type 215747073ea2SPeter Brune 215847073ea2SPeter Brune Level: developer 215947073ea2SPeter Brune 2160420bcc1bSBarry Smith Values of the function type\: 2161f6dfbefdSBarry Smith + `SNES_FUNCTION_DEFAULT` - the default for the given `SNESType` 2162f6dfbefdSBarry Smith . `SNES_FUNCTION_UNPRECONDITIONED` - an unpreconditioned function evaluation (this is the function provided with `SNESSetFunction()` 2163f6dfbefdSBarry Smith - `SNES_FUNCTION_PRECONDITIONED` - a transformation of the function provided with `SNESSetFunction()` 2164f6dfbefdSBarry Smith 2165420bcc1bSBarry Smith Note: 2166f6dfbefdSBarry Smith Different `SNESType`s use this value in different ways 2167f6dfbefdSBarry Smith 21681cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFunctionType`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 216947073ea2SPeter Brune @*/ 2170d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionType(SNES snes, SNESFunctionType type) 2171d71ae5a4SJacob Faibussowitsch { 217247073ea2SPeter Brune PetscFunctionBegin; 217347073ea2SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 217447073ea2SPeter Brune snes->functype = type; 21753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 217647073ea2SPeter Brune } 217747073ea2SPeter Brune 2178cc4c1da9SBarry Smith /*@ 2179f6dfbefdSBarry Smith SNESGetFunctionType - Gets the `SNESFunctionType` used in convergence and monitoring set with `SNESSetFunctionType()` 218047073ea2SPeter Brune of the SNES method. 218147073ea2SPeter Brune 2182c3339decSBarry Smith Logically Collective 218347073ea2SPeter Brune 218447073ea2SPeter Brune Input Parameters: 2185f6dfbefdSBarry Smith + snes - the `SNES` context 2186f6dfbefdSBarry Smith - type - the type of the function evaluation, see `SNESSetFunctionType()` 218747073ea2SPeter Brune 218847073ea2SPeter Brune Level: advanced 218947073ea2SPeter Brune 21901cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetFunctionType()`, `SNESFunctionType`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 219147073ea2SPeter Brune @*/ 2192d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionType(SNES snes, SNESFunctionType *type) 2193d71ae5a4SJacob Faibussowitsch { 219447073ea2SPeter Brune PetscFunctionBegin; 219547073ea2SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 219647073ea2SPeter Brune *type = snes->functype; 21973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2198534ebe21SPeter Brune } 2199534ebe21SPeter Brune 2200c79ef259SPeter Brune /*@C 2201be95d8f1SBarry Smith SNESSetNGS - Sets the user nonlinear Gauss-Seidel routine for 2202c79ef259SPeter Brune use with composed nonlinear solvers. 2203c79ef259SPeter Brune 2204c79ef259SPeter Brune Input Parameters: 22059bcc50f1SBarry Smith + snes - the `SNES` context, usually of the `SNESType` `SNESNGS` 22068434afd1SBarry Smith . f - function evaluation routine to apply Gauss-Seidel, see `SNESNGSFn` for calling sequence 220777e5a1f9SBarry Smith - ctx - [optional] user-defined context for private data for the smoother evaluation routine (may be `NULL`) 2208c79ef259SPeter Brune 2209dc4c0fb0SBarry Smith Level: intermediate 2210dc4c0fb0SBarry Smith 2211f6dfbefdSBarry Smith Note: 2212f6dfbefdSBarry Smith The `SNESNGS` routines are used by the composed nonlinear solver to generate 2213f6dfbefdSBarry Smith a problem appropriate update to the solution, particularly `SNESFAS`. 2214c79ef259SPeter Brune 22158434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGS`, `SNESGetNGS()`, `SNESNCG`, `SNESGetFunction()`, `SNESComputeNGS()`, `SNESNGSFn` 2216c79ef259SPeter Brune @*/ 22178434afd1SBarry Smith PetscErrorCode SNESSetNGS(SNES snes, SNESNGSFn *f, void *ctx) 2218d71ae5a4SJacob Faibussowitsch { 22196cab3a1bSJed Brown DM dm; 22206cab3a1bSJed Brown 2221646217ecSPeter Brune PetscFunctionBegin; 22226cab3a1bSJed Brown PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 22239566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 22249566063dSJacob Faibussowitsch PetscCall(DMSNESSetNGS(dm, f, ctx)); 22253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2226646217ecSPeter Brune } 2227646217ecSPeter Brune 2228bbc1464cSBarry Smith /* 2229bbc1464cSBarry Smith This is used for -snes_mf_operator; it uses a duplicate of snes->jacobian_pre because snes->jacobian_pre cannot be 2230bbc1464cSBarry Smith changed during the KSPSolve() 2231bbc1464cSBarry Smith */ 2232d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeMFFunction(SNES snes, Vec x, Vec f, void *ctx) 2233d71ae5a4SJacob Faibussowitsch { 2234bbc1464cSBarry Smith DM dm; 2235bbc1464cSBarry Smith DMSNES sdm; 2236bbc1464cSBarry Smith 2237bbc1464cSBarry Smith PetscFunctionBegin; 22389566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 22399566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 2240bbc1464cSBarry Smith /* A(x)*x - b(x) */ 2241bbc1464cSBarry Smith if (sdm->ops->computepfunction) { 2242792fecdfSBarry Smith PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx)); 22439566063dSJacob Faibussowitsch PetscCall(VecScale(f, -1.0)); 22440df40c35SBarry Smith /* Cannot share nonzero pattern because of the possible use of SNESComputeJacobianDefault() */ 2245ef1023bdSBarry Smith if (!snes->picard) PetscCall(MatDuplicate(snes->jacobian_pre, MAT_DO_NOT_COPY_VALUES, &snes->picard)); 2246792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx)); 22479566063dSJacob Faibussowitsch PetscCall(MatMultAdd(snes->picard, x, f, f)); 2248bbc1464cSBarry Smith } else { 2249792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx)); 22509566063dSJacob Faibussowitsch PetscCall(MatMult(snes->picard, x, f)); 2251bbc1464cSBarry Smith } 22523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2253bbc1464cSBarry Smith } 2254bbc1464cSBarry Smith 2255d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeFunction(SNES snes, Vec x, Vec f, void *ctx) 2256d71ae5a4SJacob Faibussowitsch { 2257e03ab78fSPeter Brune DM dm; 2258942e3340SBarry Smith DMSNES sdm; 22596cab3a1bSJed Brown 22608b0a5094SBarry Smith PetscFunctionBegin; 22619566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 22629566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 22638b0a5094SBarry Smith /* A(x)*x - b(x) */ 2264bbc1464cSBarry Smith if (sdm->ops->computepfunction) { 2265792fecdfSBarry Smith PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx)); 22669566063dSJacob Faibussowitsch PetscCall(VecScale(f, -1.0)); 2267792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx)); 22689566063dSJacob Faibussowitsch PetscCall(MatMultAdd(snes->jacobian_pre, x, f, f)); 2269bbc1464cSBarry Smith } else { 2270792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx)); 22719566063dSJacob Faibussowitsch PetscCall(MatMult(snes->jacobian_pre, x, f)); 2272bbc1464cSBarry Smith } 22733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22748b0a5094SBarry Smith } 22758b0a5094SBarry Smith 2276d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeJacobian(SNES snes, Vec x1, Mat J, Mat B, void *ctx) 2277d71ae5a4SJacob Faibussowitsch { 22788b0a5094SBarry Smith PetscFunctionBegin; 2279e03ab78fSPeter Brune /* the jacobian matrix should be pre-filled in SNESPicardComputeFunction */ 2280bbc1464cSBarry Smith /* must assembly if matrix-free to get the last SNES solution */ 22819566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 22829566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 22833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22848b0a5094SBarry Smith } 22858b0a5094SBarry Smith 22868b0a5094SBarry Smith /*@C 22871d27aa22SBarry Smith SNESSetPicard - Use `SNES` to solve the system $A(x) x = bp(x) + b $ via a Picard type iteration (Picard linearization) 22888b0a5094SBarry Smith 2289c3339decSBarry Smith Logically Collective 22908b0a5094SBarry Smith 22918b0a5094SBarry Smith Input Parameters: 2292f6dfbefdSBarry Smith + snes - the `SNES` context 2293dc4c0fb0SBarry Smith . r - vector to store function values, may be `NULL` 22948434afd1SBarry Smith . bp - function evaluation routine, may be `NULL`, for the calling sequence see `SNESFunctionFn` 229526a11704SBarry Smith . Amat - matrix with which $A(x) x - bp(x) - b$ is to be computed 2296dc4c0fb0SBarry Smith . Pmat - matrix from which preconditioner is computed (usually the same as `Amat`) 22978434afd1SBarry Smith . J - function to compute matrix values, for the calling sequence see `SNESJacobianFn` 2298dc4c0fb0SBarry Smith - ctx - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`) 2299dc4c0fb0SBarry Smith 2300dc4c0fb0SBarry Smith Level: intermediate 23018b0a5094SBarry Smith 23028b0a5094SBarry Smith Notes: 230326a11704SBarry Smith It is often better to provide the nonlinear function $F()$ and some approximation to its Jacobian directly and use 2304f450aa47SBarry 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. 2305f450aa47SBarry Smith 2306f6dfbefdSBarry Smith One can call `SNESSetPicard()` or `SNESSetFunction()` (and possibly `SNESSetJacobian()`) but cannot call both 23078b0a5094SBarry Smith 23081d27aa22SBarry 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}$. 23091d27aa22SBarry Smith When an exact solver is used this corresponds to the "classic" Picard $A(x^{n}) x^{n+1} = bp(x^{n}) + b$ iteration. 23108b0a5094SBarry Smith 231126a11704SBarry Smith Run with `-snes_mf_operator` to solve the system with Newton's method using $A(x^{n})$ to construct the preconditioner. 23128b0a5094SBarry Smith 23130d04baf8SBarry Smith We implement the defect correction form of the Picard iteration because it converges much more generally when inexact linear solvers are used then 23141d27aa22SBarry Smith the direct Picard iteration $A(x^n) x^{n+1} = bp(x^n) + b$ 23158b0a5094SBarry Smith 23168b0a5094SBarry 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 23171d27aa22SBarry 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 23181d27aa22SBarry Smith different please contact us at petsc-dev@mcs.anl.gov and we'll have an entirely new argument \:-). 23198b0a5094SBarry Smith 23201d27aa22SBarry 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 232126a11704SBarry Smith $A(x^{n})$ is used to build the preconditioner 23226b7fb656SBarry Smith 232315229ffcSPierre 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. 23246b7fb656SBarry Smith 2325dc4c0fb0SBarry 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 232626a11704SBarry 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 232726a11704SBarry 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`. 2328aaa8cc7dSPierre Jolivet See the comment in src/snes/tutorials/ex15.c. 2329bbc1464cSBarry Smith 23309bcc50f1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESGetPicard()`, `SNESLineSearchPreCheckPicard()`, 23318434afd1SBarry Smith `SNESFunctionFn`, `SNESJacobianFn` 23328b0a5094SBarry Smith @*/ 23338434afd1SBarry Smith PetscErrorCode SNESSetPicard(SNES snes, Vec r, SNESFunctionFn *bp, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx) 2334d71ae5a4SJacob Faibussowitsch { 2335e03ab78fSPeter Brune DM dm; 2336e03ab78fSPeter Brune 23378b0a5094SBarry Smith PetscFunctionBegin; 23388b0a5094SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 23399566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 23409566063dSJacob Faibussowitsch PetscCall(DMSNESSetPicard(dm, bp, J, ctx)); 23419566063dSJacob Faibussowitsch PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx)); 23429566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes, r, SNESPicardComputeFunction, ctx)); 23439566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESPicardComputeJacobian, ctx)); 23443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23458b0a5094SBarry Smith } 23468b0a5094SBarry Smith 23477971a8bfSPeter Brune /*@C 23487971a8bfSPeter Brune SNESGetPicard - Returns the context for the Picard iteration 23497971a8bfSPeter Brune 2350f6dfbefdSBarry Smith Not Collective, but `Vec` is parallel if `SNES` is parallel. Collective if `Vec` is requested, but has not been created yet. 23517971a8bfSPeter Brune 23527971a8bfSPeter Brune Input Parameter: 2353f6dfbefdSBarry Smith . snes - the `SNES` context 23547971a8bfSPeter Brune 2355d8d19677SJose E. Roman Output Parameters: 2356dc4c0fb0SBarry Smith + r - the function (or `NULL`) 23578434afd1SBarry Smith . f - the function (or `NULL`); for calling sequence see `SNESFunctionFn` 2358dc4c0fb0SBarry Smith . Amat - the matrix used to defined the operation A(x) x - b(x) (or `NULL`) 2359dc4c0fb0SBarry Smith . Pmat - the matrix from which the preconditioner will be constructed (or `NULL`) 23608434afd1SBarry Smith . J - the function for matrix evaluation (or `NULL`); for calling sequence see `SNESJacobianFn` 2361dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`) 23627971a8bfSPeter Brune 23637971a8bfSPeter Brune Level: advanced 23647971a8bfSPeter Brune 23658434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetFunction()`, `SNESSetPicard()`, `SNESGetFunction()`, `SNESGetJacobian()`, `SNESGetDM()`, `SNESFunctionFn`, `SNESJacobianFn` 23667971a8bfSPeter Brune @*/ 23678434afd1SBarry Smith PetscErrorCode SNESGetPicard(SNES snes, Vec *r, SNESFunctionFn **f, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx) 2368d71ae5a4SJacob Faibussowitsch { 23697971a8bfSPeter Brune DM dm; 23707971a8bfSPeter Brune 23717971a8bfSPeter Brune PetscFunctionBegin; 23727971a8bfSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 23739566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, r, NULL, NULL)); 23749566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL)); 23759566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 23769566063dSJacob Faibussowitsch PetscCall(DMSNESGetPicard(dm, f, J, ctx)); 23773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23787971a8bfSPeter Brune } 23797971a8bfSPeter Brune 2380d25893d9SBarry Smith /*@C 2381dc4c0fb0SBarry Smith SNESSetComputeInitialGuess - Sets a routine used to compute an initial guess for the nonlinear problem 2382d25893d9SBarry Smith 2383c3339decSBarry Smith Logically Collective 2384d25893d9SBarry Smith 2385d25893d9SBarry Smith Input Parameters: 2386f6dfbefdSBarry Smith + snes - the `SNES` context 23878434afd1SBarry Smith . func - function evaluation routine, see `SNESInitialGuessFn` for the calling sequence 2388d25893d9SBarry Smith - ctx - [optional] user-defined context for private data for the 2389dc4c0fb0SBarry Smith function evaluation routine (may be `NULL`) 2390d25893d9SBarry Smith 2391d25893d9SBarry Smith Level: intermediate 2392d25893d9SBarry Smith 23938434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESInitialGuessFn` 2394d25893d9SBarry Smith @*/ 23958434afd1SBarry Smith PetscErrorCode SNESSetComputeInitialGuess(SNES snes, SNESInitialGuessFn *func, void *ctx) 2396d71ae5a4SJacob Faibussowitsch { 2397d25893d9SBarry Smith PetscFunctionBegin; 2398d25893d9SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2399d25893d9SBarry Smith if (func) snes->ops->computeinitialguess = func; 2400d25893d9SBarry Smith if (ctx) snes->initialguessP = ctx; 24013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2402d25893d9SBarry Smith } 2403d25893d9SBarry Smith 24041096aae1SMatthew Knepley /*@C 2405dc4c0fb0SBarry Smith SNESGetRhs - Gets the vector for solving F(x) = `rhs`. If `rhs` is not set 2406dd8e379bSPierre Jolivet it assumes a zero right-hand side. 24071096aae1SMatthew Knepley 2408c3339decSBarry Smith Logically Collective 24091096aae1SMatthew Knepley 24101096aae1SMatthew Knepley Input Parameter: 2411f6dfbefdSBarry Smith . snes - the `SNES` context 24121096aae1SMatthew Knepley 24131096aae1SMatthew Knepley Output Parameter: 2414dd8e379bSPierre Jolivet . rhs - the right-hand side vector or `NULL` if there is no right-hand side vector 24151096aae1SMatthew Knepley 24161096aae1SMatthew Knepley Level: intermediate 24171096aae1SMatthew Knepley 24181cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetFunction()` 24191096aae1SMatthew Knepley @*/ 2420d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetRhs(SNES snes, Vec *rhs) 2421d71ae5a4SJacob Faibussowitsch { 24221096aae1SMatthew Knepley PetscFunctionBegin; 24230700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 24244f572ea9SToby Isaac PetscAssertPointer(rhs, 2); 242585385478SLisandro Dalcin *rhs = snes->vec_rhs; 24263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24271096aae1SMatthew Knepley } 24281096aae1SMatthew Knepley 24299b94acceSBarry Smith /*@ 2430f6dfbefdSBarry Smith SNESComputeFunction - Calls the function that has been set with `SNESSetFunction()`. 24319b94acceSBarry Smith 2432c3339decSBarry Smith Collective 2433c7afd0dbSLois Curfman McInnes 24349b94acceSBarry Smith Input Parameters: 2435f6dfbefdSBarry Smith + snes - the `SNES` context 2436c7afd0dbSLois Curfman McInnes - x - input vector 24379b94acceSBarry Smith 24389b94acceSBarry Smith Output Parameter: 2439f6dfbefdSBarry Smith . y - function vector, as set by `SNESSetFunction()` 24409b94acceSBarry Smith 2441dc4c0fb0SBarry Smith Level: developer 2442dc4c0fb0SBarry Smith 244300677de2SStefano Zampini Notes: 2444f6dfbefdSBarry Smith `SNESComputeFunction()` is typically used within nonlinear solvers 2445bbc1464cSBarry Smith implementations, so users would not generally call this routine themselves. 244636851e7fSLois Curfman McInnes 244700677de2SStefano Zampini When solving for $F(x) = b$, this routine computes $y = F(x) - b$. 244800677de2SStefano Zampini 24491cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeMFFunction()` 24509b94acceSBarry Smith @*/ 2451d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeFunction(SNES snes, Vec x, Vec y) 2452d71ae5a4SJacob Faibussowitsch { 24536cab3a1bSJed Brown DM dm; 2454942e3340SBarry Smith DMSNES sdm; 24559b94acceSBarry Smith 24563a40ed3dSBarry Smith PetscFunctionBegin; 24570700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 24580700a824SBarry Smith PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 24590700a824SBarry Smith PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2460c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, x, 2); 2461c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, y, 3); 2462e0f629ddSJacob Faibussowitsch PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2463184914b5SBarry Smith 24649566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 24659566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 24660fdf79fbSJacob 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()."); 246732f3f7c2SPeter Brune if (sdm->ops->computefunction) { 246848a46eb9SPierre Jolivet if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0)); 24699566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(x)); 24708ddeebeaSSteve Benbow /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */ 24718ddeebeaSSteve Benbow snes->domainerror = PETSC_FALSE; 2472800f99ffSJeremy L Thompson { 2473800f99ffSJeremy L Thompson void *ctx; 24748434afd1SBarry Smith SNESFunctionFn *computefunction; 2475800f99ffSJeremy L Thompson PetscCall(DMSNESGetFunction(dm, &computefunction, &ctx)); 2476800f99ffSJeremy L Thompson PetscCallBack("SNES callback function", (*computefunction)(snes, x, y, ctx)); 2477800f99ffSJeremy L Thompson } 24789566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(x)); 247948a46eb9SPierre Jolivet if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0)); 24800fdf79fbSJacob Faibussowitsch } else /* if (snes->vec_rhs) */ { 24819566063dSJacob Faibussowitsch PetscCall(MatMult(snes->jacobian, x, y)); 24820fdf79fbSJacob Faibussowitsch } 24831baa6e33SBarry Smith if (snes->vec_rhs) PetscCall(VecAXPY(y, -1.0, snes->vec_rhs)); 2484ae3c334cSLois Curfman McInnes snes->nfuncs++; 2485422a814eSBarry Smith /* 2486422a814eSBarry Smith domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will 2487422a814eSBarry Smith propagate the value to all processes 2488422a814eSBarry Smith */ 2489f480ea8aSBarry Smith PetscCall(VecFlag(y, snes->domainerror)); 24903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24919b94acceSBarry Smith } 24929b94acceSBarry Smith 2493c79ef259SPeter Brune /*@ 24940b4b7b1cSBarry Smith SNESComputeMFFunction - Calls the function that has been set with `DMSNESSetMFFunction()`. 2495bbc1464cSBarry Smith 2496c3339decSBarry Smith Collective 2497bbc1464cSBarry Smith 2498bbc1464cSBarry Smith Input Parameters: 2499f6dfbefdSBarry Smith + snes - the `SNES` context 2500bbc1464cSBarry Smith - x - input vector 2501bbc1464cSBarry Smith 2502bbc1464cSBarry Smith Output Parameter: 25030b4b7b1cSBarry Smith . y - output vector 2504bbc1464cSBarry Smith 2505dc4c0fb0SBarry Smith Level: developer 2506dc4c0fb0SBarry Smith 2507bbc1464cSBarry Smith Notes: 2508420bcc1bSBarry Smith `SNESComputeMFFunction()` is used within the matrix-vector products called by the matrix created with `MatCreateSNESMF()` 2509bbc1464cSBarry Smith so users would not generally call this routine themselves. 2510bbc1464cSBarry Smith 2511dd8e379bSPierre Jolivet Since this function is intended for use with finite differencing it does not subtract the right-hand side vector provided with `SNESSolve()` 2512f6dfbefdSBarry Smith while `SNESComputeFunction()` does. As such, this routine cannot be used with `MatMFFDSetBase()` with a provided F function value even if it applies the 2513dd8e379bSPierre 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. 2514bbc1464cSBarry Smith 25150b4b7b1cSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `MatCreateSNESMF()`, `DMSNESSetMFFunction()` 2516bbc1464cSBarry Smith @*/ 2517d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeMFFunction(SNES snes, Vec x, Vec y) 2518d71ae5a4SJacob Faibussowitsch { 2519bbc1464cSBarry Smith DM dm; 2520bbc1464cSBarry Smith DMSNES sdm; 2521bbc1464cSBarry Smith 2522bbc1464cSBarry Smith PetscFunctionBegin; 2523bbc1464cSBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2524bbc1464cSBarry Smith PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2525bbc1464cSBarry Smith PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2526bbc1464cSBarry Smith PetscCheckSameComm(snes, 1, x, 2); 2527bbc1464cSBarry Smith PetscCheckSameComm(snes, 1, y, 3); 2528e0f629ddSJacob Faibussowitsch PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2529bbc1464cSBarry Smith 25309566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 25319566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 25329566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0)); 25339566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(x)); 2534bbc1464cSBarry Smith /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */ 2535bbc1464cSBarry Smith snes->domainerror = PETSC_FALSE; 2536792fecdfSBarry Smith PetscCallBack("SNES callback function", (*sdm->ops->computemffunction)(snes, x, y, sdm->mffunctionctx)); 25379566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(x)); 25389566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0)); 2539bbc1464cSBarry Smith snes->nfuncs++; 2540bbc1464cSBarry Smith /* 2541bbc1464cSBarry Smith domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will 2542bbc1464cSBarry Smith propagate the value to all processes 2543bbc1464cSBarry Smith */ 2544f480ea8aSBarry Smith PetscCall(VecFlag(y, snes->domainerror)); 25453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2546bbc1464cSBarry Smith } 2547bbc1464cSBarry Smith 2548bbc1464cSBarry Smith /*@ 2549f6dfbefdSBarry Smith SNESComputeNGS - Calls the Gauss-Seidel function that has been set with `SNESSetNGS()`. 2550c79ef259SPeter Brune 2551c3339decSBarry Smith Collective 2552c79ef259SPeter Brune 2553c79ef259SPeter Brune Input Parameters: 2554f6dfbefdSBarry Smith + snes - the `SNES` context 2555c79ef259SPeter Brune . x - input vector 2556c79ef259SPeter Brune - b - rhs vector 2557c79ef259SPeter Brune 2558c79ef259SPeter Brune Output Parameter: 2559c79ef259SPeter Brune . x - new solution vector 2560c79ef259SPeter Brune 2561dc4c0fb0SBarry Smith Level: developer 2562dc4c0fb0SBarry Smith 2563f6dfbefdSBarry Smith Note: 2564f6dfbefdSBarry Smith `SNESComputeNGS()` is typically used within composed nonlinear solver 2565c79ef259SPeter Brune implementations, so most users would not generally call this routine 2566c79ef259SPeter Brune themselves. 2567c79ef259SPeter Brune 25688434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGSFn`, `SNESSetNGS()`, `SNESComputeFunction()`, `SNESNGS` 2569c79ef259SPeter Brune @*/ 2570d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeNGS(SNES snes, Vec b, Vec x) 2571d71ae5a4SJacob Faibussowitsch { 25726cab3a1bSJed Brown DM dm; 2573942e3340SBarry Smith DMSNES sdm; 2574646217ecSPeter Brune 2575646217ecSPeter Brune PetscFunctionBegin; 2576646217ecSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2577064a246eSJacob Faibussowitsch PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 2578064a246eSJacob Faibussowitsch if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 2579064a246eSJacob Faibussowitsch PetscCheckSameComm(snes, 1, x, 3); 2580064a246eSJacob Faibussowitsch if (b) PetscCheckSameComm(snes, 1, b, 2); 2581e0f629ddSJacob Faibussowitsch if (b) PetscCall(VecValidValues_Internal(b, 2, PETSC_TRUE)); 25829566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_NGSEval, snes, x, b, 0)); 25839566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 25849566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 25850fdf79fbSJacob Faibussowitsch PetscCheck(sdm->ops->computegs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetNGS() before SNESComputeNGS(), likely called from SNESSolve()."); 25869566063dSJacob Faibussowitsch if (b) PetscCall(VecLockReadPush(b)); 2587792fecdfSBarry Smith PetscCallBack("SNES callback NGS", (*sdm->ops->computegs)(snes, x, b, sdm->gsctx)); 25889566063dSJacob Faibussowitsch if (b) PetscCall(VecLockReadPop(b)); 25899566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_NGSEval, snes, x, b, 0)); 25903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2591646217ecSPeter Brune } 2592646217ecSPeter Brune 2593494a190aSStefano Zampini static PetscErrorCode SNESComputeFunction_FD(SNES snes, Vec Xin, Vec G) 2594494a190aSStefano Zampini { 2595494a190aSStefano Zampini Vec X; 2596494a190aSStefano Zampini PetscScalar *g; 2597494a190aSStefano Zampini PetscReal f, f2; 2598494a190aSStefano Zampini PetscInt low, high, N, i; 2599494a190aSStefano Zampini PetscBool flg; 2600494a190aSStefano Zampini PetscReal h = .5 * PETSC_SQRT_MACHINE_EPSILON; 2601494a190aSStefano Zampini 2602494a190aSStefano Zampini PetscFunctionBegin; 2603494a190aSStefano Zampini PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_fd_delta", &h, &flg)); 2604494a190aSStefano Zampini PetscCall(VecDuplicate(Xin, &X)); 2605494a190aSStefano Zampini PetscCall(VecCopy(Xin, X)); 2606494a190aSStefano Zampini PetscCall(VecGetSize(X, &N)); 2607494a190aSStefano Zampini PetscCall(VecGetOwnershipRange(X, &low, &high)); 2608494a190aSStefano Zampini PetscCall(VecSetOption(X, VEC_IGNORE_OFF_PROC_ENTRIES, PETSC_TRUE)); 2609494a190aSStefano Zampini PetscCall(VecGetArray(G, &g)); 2610494a190aSStefano Zampini for (i = 0; i < N; i++) { 2611494a190aSStefano Zampini PetscCall(VecSetValue(X, i, -h, ADD_VALUES)); 2612494a190aSStefano Zampini PetscCall(VecAssemblyBegin(X)); 2613494a190aSStefano Zampini PetscCall(VecAssemblyEnd(X)); 2614494a190aSStefano Zampini PetscCall(SNESComputeObjective(snes, X, &f)); 2615494a190aSStefano Zampini PetscCall(VecSetValue(X, i, 2.0 * h, ADD_VALUES)); 2616494a190aSStefano Zampini PetscCall(VecAssemblyBegin(X)); 2617494a190aSStefano Zampini PetscCall(VecAssemblyEnd(X)); 2618494a190aSStefano Zampini PetscCall(SNESComputeObjective(snes, X, &f2)); 2619494a190aSStefano Zampini PetscCall(VecSetValue(X, i, -h, ADD_VALUES)); 2620494a190aSStefano Zampini PetscCall(VecAssemblyBegin(X)); 2621494a190aSStefano Zampini PetscCall(VecAssemblyEnd(X)); 2622494a190aSStefano Zampini if (i >= low && i < high) g[i - low] = (f2 - f) / (2.0 * h); 2623494a190aSStefano Zampini } 2624494a190aSStefano Zampini PetscCall(VecRestoreArray(G, &g)); 2625494a190aSStefano Zampini PetscCall(VecDestroy(&X)); 2626494a190aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2627494a190aSStefano Zampini } 2628494a190aSStefano Zampini 2629494a190aSStefano Zampini PetscErrorCode SNESTestFunction(SNES snes) 2630494a190aSStefano Zampini { 2631494a190aSStefano Zampini Vec x, g1, g2, g3; 2632494a190aSStefano Zampini PetscBool complete_print = PETSC_FALSE, test = PETSC_FALSE; 2633494a190aSStefano Zampini PetscReal hcnorm, fdnorm, hcmax, fdmax, diffmax, diffnorm; 2634494a190aSStefano Zampini PetscScalar dot; 2635494a190aSStefano Zampini MPI_Comm comm; 2636494a190aSStefano Zampini PetscViewer viewer, mviewer; 2637494a190aSStefano Zampini PetscViewerFormat format; 2638494a190aSStefano Zampini PetscInt tabs; 2639494a190aSStefano Zampini static PetscBool directionsprinted = PETSC_FALSE; 26408434afd1SBarry Smith SNESObjectiveFn *objective; 2641494a190aSStefano Zampini 2642494a190aSStefano Zampini PetscFunctionBegin; 2643494a190aSStefano Zampini PetscCall(SNESGetObjective(snes, &objective, NULL)); 2644494a190aSStefano Zampini if (!objective) PetscFunctionReturn(PETSC_SUCCESS); 2645494a190aSStefano Zampini 2646494a190aSStefano Zampini PetscObjectOptionsBegin((PetscObject)snes); 2647494a190aSStefano Zampini PetscCall(PetscOptionsName("-snes_test_function", "Compare hand-coded and finite difference function", "None", &test)); 2648494a190aSStefano Zampini PetscCall(PetscOptionsViewer("-snes_test_function_view", "View difference between hand-coded and finite difference function element entries", "None", &mviewer, &format, &complete_print)); 2649494a190aSStefano Zampini PetscOptionsEnd(); 2650494a190aSStefano Zampini if (!test) { 2651494a190aSStefano Zampini if (complete_print) PetscCall(PetscViewerDestroy(&mviewer)); 2652494a190aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2653494a190aSStefano Zampini } 2654494a190aSStefano Zampini 2655494a190aSStefano Zampini PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 2656494a190aSStefano Zampini PetscCall(PetscViewerASCIIGetStdout(comm, &viewer)); 2657494a190aSStefano Zampini PetscCall(PetscViewerASCIIGetTab(viewer, &tabs)); 2658494a190aSStefano Zampini PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel)); 2659494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Function -------------\n")); 2660494a190aSStefano Zampini if (!complete_print && !directionsprinted) { 2661494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Run with -snes_test_function_view and optionally -snes_test_function <threshold> to show difference\n")); 2662494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " of hand-coded and finite difference function entries greater than <threshold>.\n")); 2663494a190aSStefano Zampini } 2664494a190aSStefano Zampini if (!directionsprinted) { 2665494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Testing hand-coded Function, if (for double precision runs) ||F - Ffd||/||F|| is\n")); 2666494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " O(1.e-8), the hand-coded Function is probably correct.\n")); 2667494a190aSStefano Zampini directionsprinted = PETSC_TRUE; 2668494a190aSStefano Zampini } 2669494a190aSStefano Zampini if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format)); 2670494a190aSStefano Zampini 2671494a190aSStefano Zampini PetscCall(SNESGetSolution(snes, &x)); 2672494a190aSStefano Zampini PetscCall(VecDuplicate(x, &g1)); 2673494a190aSStefano Zampini PetscCall(VecDuplicate(x, &g2)); 2674494a190aSStefano Zampini PetscCall(VecDuplicate(x, &g3)); 2675494a190aSStefano Zampini PetscCall(SNESComputeFunction(snes, x, g1)); 2676494a190aSStefano Zampini PetscCall(SNESComputeFunction_FD(snes, x, g2)); 2677494a190aSStefano Zampini 2678494a190aSStefano Zampini PetscCall(VecNorm(g2, NORM_2, &fdnorm)); 2679494a190aSStefano Zampini PetscCall(VecNorm(g1, NORM_2, &hcnorm)); 2680494a190aSStefano Zampini PetscCall(VecNorm(g2, NORM_INFINITY, &fdmax)); 2681494a190aSStefano Zampini PetscCall(VecNorm(g1, NORM_INFINITY, &hcmax)); 2682494a190aSStefano Zampini PetscCall(VecDot(g1, g2, &dot)); 2683494a190aSStefano Zampini PetscCall(VecCopy(g1, g3)); 2684494a190aSStefano Zampini PetscCall(VecAXPY(g3, -1.0, g2)); 2685494a190aSStefano Zampini PetscCall(VecNorm(g3, NORM_2, &diffnorm)); 2686494a190aSStefano Zampini PetscCall(VecNorm(g3, NORM_INFINITY, &diffmax)); 2687494a190aSStefano 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)))); 2688494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " 2-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffnorm / PetscMax(hcnorm, fdnorm)), (double)diffnorm)); 2689494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " max-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffmax / PetscMax(hcmax, fdmax)), (double)diffmax)); 2690494a190aSStefano Zampini 2691494a190aSStefano Zampini if (complete_print) { 2692494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded function ----------\n")); 2693494a190aSStefano Zampini PetscCall(VecView(g1, mviewer)); 2694494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Finite difference function ----------\n")); 2695494a190aSStefano Zampini PetscCall(VecView(g2, mviewer)); 2696494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded minus finite-difference function ----------\n")); 2697494a190aSStefano Zampini PetscCall(VecView(g3, mviewer)); 2698494a190aSStefano Zampini } 2699494a190aSStefano Zampini PetscCall(VecDestroy(&g1)); 2700494a190aSStefano Zampini PetscCall(VecDestroy(&g2)); 2701494a190aSStefano Zampini PetscCall(VecDestroy(&g3)); 2702494a190aSStefano Zampini 2703494a190aSStefano Zampini if (complete_print) { 2704494a190aSStefano Zampini PetscCall(PetscViewerPopFormat(mviewer)); 2705494a190aSStefano Zampini PetscCall(PetscViewerDestroy(&mviewer)); 2706494a190aSStefano Zampini } 2707494a190aSStefano Zampini PetscCall(PetscViewerASCIISetTab(viewer, tabs)); 2708494a190aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2709494a190aSStefano Zampini } 2710494a190aSStefano Zampini 2711d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestJacobian(SNES snes) 2712d71ae5a4SJacob Faibussowitsch { 271312837594SBarry Smith Mat A, B, C, D, jacobian; 27144df93895SStefano Zampini Vec x = snes->vec_sol, f; 2715e885f1abSBarry Smith PetscReal nrm, gnorm; 271681e7118cSBarry Smith PetscReal threshold = 1.e-5; 27170e276705SLisandro Dalcin MatType mattype; 2718e885f1abSBarry Smith PetscInt m, n, M, N; 2719e885f1abSBarry Smith void *functx; 27202cd624f9SStefano Zampini PetscBool complete_print = PETSC_FALSE, threshold_print = PETSC_FALSE, test = PETSC_FALSE, flg, istranspose; 27213325ff46SBarry Smith PetscViewer viewer, mviewer; 2722e885f1abSBarry Smith MPI_Comm comm; 2723e885f1abSBarry Smith PetscInt tabs; 272412837594SBarry Smith static PetscBool directionsprinted = PETSC_FALSE; 27253325ff46SBarry Smith PetscViewerFormat format; 2726e885f1abSBarry Smith 2727e885f1abSBarry Smith PetscFunctionBegin; 2728d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)snes); 27299566063dSJacob Faibussowitsch PetscCall(PetscOptionsName("-snes_test_jacobian", "Compare hand-coded and finite difference Jacobians", "None", &test)); 27309566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-snes_test_jacobian", "Threshold for element difference between hand-coded and finite difference being meaningful", "None", threshold, &threshold, NULL)); 27319566063dSJacob Faibussowitsch PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display", "-snes_test_jacobian_view", "3.13", NULL)); 27324ead3382SBarry Smith PetscCall(PetscOptionsViewer("-snes_test_jacobian_view", "View difference between hand-coded and finite difference Jacobians element entries", "None", &mviewer, &format, &complete_print)); 27339566063dSJacob Faibussowitsch PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display_threshold", "-snes_test_jacobian", "3.13", "-snes_test_jacobian accepts an optional threshold (since v3.10)")); 27349566063dSJacob 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)); 2735d0609cedSBarry Smith PetscOptionsEnd(); 27363ba16761SJacob Faibussowitsch if (!test) PetscFunctionReturn(PETSC_SUCCESS); 2737e885f1abSBarry Smith 27389566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 27399566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(comm, &viewer)); 27409566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetTab(viewer, &tabs)); 27419566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel)); 27429566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Jacobian -------------\n")); 274312837594SBarry Smith if (!complete_print && !directionsprinted) { 27449566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Run with -snes_test_jacobian_view and optionally -snes_test_jacobian <threshold> to show difference\n")); 27459566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " of hand-coded and finite difference Jacobian entries greater than <threshold>.\n")); 274612837594SBarry Smith } 274712837594SBarry Smith if (!directionsprinted) { 27489566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Testing hand-coded Jacobian, if (for double precision runs) ||J - Jfd||_F/||J||_F is\n")); 27499566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " O(1.e-8), the hand-coded Jacobian is probably correct.\n")); 275012837594SBarry Smith directionsprinted = PETSC_TRUE; 2751e885f1abSBarry Smith } 27521baa6e33SBarry Smith if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format)); 2753e885f1abSBarry Smith 27549566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes->jacobian, MATMFFD, &flg)); 275512837594SBarry Smith if (!flg) jacobian = snes->jacobian; 275612837594SBarry Smith else jacobian = snes->jacobian_pre; 275712837594SBarry Smith 27584df93895SStefano Zampini if (!x) PetscCall(MatCreateVecs(jacobian, &x, NULL)); 27594df93895SStefano Zampini else PetscCall(PetscObjectReference((PetscObject)x)); 27609566063dSJacob Faibussowitsch PetscCall(VecDuplicate(x, &f)); 27614df93895SStefano Zampini 2762a82339d0SMatthew G. Knepley /* evaluate the function at this point because SNESComputeJacobianDefault() assumes that the function has been evaluated and put into snes->vec_func */ 27639566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, x, f)); 27649566063dSJacob Faibussowitsch PetscCall(VecDestroy(&f)); 27659566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESKSPTRANSPOSEONLY, &istranspose)); 276612837594SBarry Smith while (jacobian) { 27672cd624f9SStefano Zampini Mat JT = NULL, Jsave = NULL; 27682cd624f9SStefano Zampini 27692cd624f9SStefano Zampini if (istranspose) { 27709566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(jacobian, &JT)); 27712cd624f9SStefano Zampini Jsave = jacobian; 27722cd624f9SStefano Zampini jacobian = JT; 27732cd624f9SStefano Zampini } 27749566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)jacobian, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, "")); 277512837594SBarry Smith if (flg) { 277612837594SBarry Smith A = jacobian; 27779566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 277812837594SBarry Smith } else { 27799566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(jacobian, MATAIJ, &A)); 278012837594SBarry Smith } 2781e885f1abSBarry Smith 27829566063dSJacob Faibussowitsch PetscCall(MatGetType(A, &mattype)); 27839566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &M, &N)); 27849566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &m, &n)); 27859566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B)); 27869566063dSJacob Faibussowitsch PetscCall(MatSetType(B, mattype)); 27879566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, m, n, M, N)); 27889566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(B, A, A)); 27899566063dSJacob Faibussowitsch PetscCall(MatSetUp(B)); 27909566063dSJacob Faibussowitsch PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 2791e885f1abSBarry Smith 27929566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, NULL, &functx)); 27939566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobianDefault(snes, x, B, B, functx)); 279412837594SBarry Smith 27959566063dSJacob Faibussowitsch PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &D)); 27969566063dSJacob Faibussowitsch PetscCall(MatAYPX(D, -1.0, A, DIFFERENT_NONZERO_PATTERN)); 27979566063dSJacob Faibussowitsch PetscCall(MatNorm(D, NORM_FROBENIUS, &nrm)); 27989566063dSJacob Faibussowitsch PetscCall(MatNorm(A, NORM_FROBENIUS, &gnorm)); 27999566063dSJacob Faibussowitsch PetscCall(MatDestroy(&D)); 280012837594SBarry Smith if (!gnorm) gnorm = 1; /* just in case */ 28019566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " ||J - Jfd||_F/||J||_F = %g, ||J - Jfd||_F = %g\n", (double)(nrm / gnorm), (double)nrm)); 280212837594SBarry Smith 2803e885f1abSBarry Smith if (complete_print) { 28049566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded Jacobian ----------\n")); 28059566063dSJacob Faibussowitsch PetscCall(MatView(A, mviewer)); 28069566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Finite difference Jacobian ----------\n")); 28079566063dSJacob Faibussowitsch PetscCall(MatView(B, mviewer)); 2808e885f1abSBarry Smith } 2809e885f1abSBarry Smith 2810df10fb39SFande Kong if (threshold_print || complete_print) { 2811e885f1abSBarry Smith PetscInt Istart, Iend, *ccols, bncols, cncols, j, row; 2812e885f1abSBarry Smith PetscScalar *cvals; 2813e885f1abSBarry Smith const PetscInt *bcols; 2814e885f1abSBarry Smith const PetscScalar *bvals; 2815e885f1abSBarry Smith 28169566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C)); 28179566063dSJacob Faibussowitsch PetscCall(MatSetType(C, mattype)); 28189566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, m, n, M, N)); 28199566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(C, A, A)); 28209566063dSJacob Faibussowitsch PetscCall(MatSetUp(C)); 28219566063dSJacob Faibussowitsch PetscCall(MatSetOption(C, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 28220e276705SLisandro Dalcin 28239566063dSJacob Faibussowitsch PetscCall(MatAYPX(B, -1.0, A, DIFFERENT_NONZERO_PATTERN)); 28249566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(B, &Istart, &Iend)); 2825e885f1abSBarry Smith 2826e885f1abSBarry Smith for (row = Istart; row < Iend; row++) { 28279566063dSJacob Faibussowitsch PetscCall(MatGetRow(B, row, &bncols, &bcols, &bvals)); 28289566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(bncols, &ccols, bncols, &cvals)); 2829e885f1abSBarry Smith for (j = 0, cncols = 0; j < bncols; j++) { 283023a52b1dSBarry Smith if (PetscAbsScalar(bvals[j]) > threshold) { 2831e885f1abSBarry Smith ccols[cncols] = bcols[j]; 2832e885f1abSBarry Smith cvals[cncols] = bvals[j]; 2833e885f1abSBarry Smith cncols += 1; 2834e885f1abSBarry Smith } 2835e885f1abSBarry Smith } 283648a46eb9SPierre Jolivet if (cncols) PetscCall(MatSetValues(C, 1, &row, cncols, ccols, cvals, INSERT_VALUES)); 28379566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(B, row, &bncols, &bcols, &bvals)); 28389566063dSJacob Faibussowitsch PetscCall(PetscFree2(ccols, cvals)); 2839e885f1abSBarry Smith } 28409566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 28419566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 28429566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded minus finite-difference Jacobian with tolerance %g ----------\n", (double)threshold)); 28439566063dSJacob Faibussowitsch PetscCall(MatView(C, complete_print ? mviewer : viewer)); 28449566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C)); 2845e885f1abSBarry Smith } 28469566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A)); 28479566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 28489566063dSJacob Faibussowitsch PetscCall(MatDestroy(&JT)); 28492cd624f9SStefano Zampini if (Jsave) jacobian = Jsave; 285012837594SBarry Smith if (jacobian != snes->jacobian_pre) { 285112837594SBarry Smith jacobian = snes->jacobian_pre; 28529566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Jacobian for preconditioner -------------\n")); 28539371c9d4SSatish Balay } else jacobian = NULL; 285412837594SBarry Smith } 28559566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); 28561baa6e33SBarry Smith if (complete_print) PetscCall(PetscViewerPopFormat(mviewer)); 2857648c30bcSBarry Smith if (mviewer) PetscCall(PetscViewerDestroy(&mviewer)); 28589566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISetTab(viewer, tabs)); 28593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2860e885f1abSBarry Smith } 2861e885f1abSBarry Smith 286262fef451SLois Curfman McInnes /*@ 2863f6dfbefdSBarry Smith SNESComputeJacobian - Computes the Jacobian matrix that has been set with `SNESSetJacobian()`. 286462fef451SLois Curfman McInnes 2865c3339decSBarry Smith Collective 2866c7afd0dbSLois Curfman McInnes 286762fef451SLois Curfman McInnes Input Parameters: 2868f6dfbefdSBarry Smith + snes - the `SNES` context 2869e4094ef1SJacob Faibussowitsch - X - input vector 287062fef451SLois Curfman McInnes 287162fef451SLois Curfman McInnes Output Parameters: 2872c7afd0dbSLois Curfman McInnes + A - Jacobian matrix 2873420bcc1bSBarry Smith - B - optional matrix for building the preconditioner, usually the same as `A` 2874fee21e36SBarry Smith 2875e35cf81dSBarry Smith Options Database Keys: 287667b8a455SSatish Balay + -snes_lag_preconditioner <lag> - how often to rebuild preconditioner 287767b8a455SSatish Balay . -snes_lag_jacobian <lag> - how often to rebuild Jacobian 2878455a5933SJed 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. 2879455a5933SJed 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 2880693365a8SJed Brown . -snes_compare_explicit - Compare the computed Jacobian to the finite difference Jacobian and output the differences 2881693365a8SJed Brown . -snes_compare_explicit_draw - Compare the computed Jacobian to the finite difference Jacobian and draw the result 2882693365a8SJed Brown . -snes_compare_explicit_contour - Compare the computed Jacobian to the finite difference Jacobian and draw a contour plot with the result 28837addb90fSBarry Smith . -snes_compare_operator - Make the comparison options above use the operator instead of the matrix used to construct the preconditioner 288494d6a431SBarry Smith . -snes_compare_coloring - Compute the finite difference Jacobian using coloring and display norms of difference 2885a5b23f4aSJose E. Roman . -snes_compare_coloring_display - Compute the finite difference Jacobian using coloring and display verbose differences 2886c01495d3SJed Brown . -snes_compare_coloring_threshold - Display only those matrix entries that differ by more than a given threshold 2887dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_atol - Absolute tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold` 2888dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_rtol - Relative tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold` 2889a5b23f4aSJose E. Roman . -snes_compare_coloring_draw - Compute the finite difference Jacobian using coloring and draw differences 2890a5b23f4aSJose E. Roman - -snes_compare_coloring_draw_contour - Compute the finite difference Jacobian using coloring and show contours of matrices and differences 2891c01495d3SJed Brown 2892dc4c0fb0SBarry Smith Level: developer 2893dc4c0fb0SBarry Smith 2894f6dfbefdSBarry Smith Note: 289562fef451SLois Curfman McInnes Most users should not need to explicitly call this routine, as it 289662fef451SLois Curfman McInnes is used internally within the nonlinear solvers. 289762fef451SLois Curfman McInnes 2898420bcc1bSBarry Smith Developer Note: 2899dc4c0fb0SBarry 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 2900420bcc1bSBarry Smith with the `SNESType` of test that has been removed. 2901e885f1abSBarry Smith 29021cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetJacobian()`, `KSPSetOperators()`, `MatStructure`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()` 290362fef451SLois Curfman McInnes @*/ 2904d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeJacobian(SNES snes, Vec X, Mat A, Mat B) 2905d71ae5a4SJacob Faibussowitsch { 2906ace3abfcSBarry Smith PetscBool flag; 29076cab3a1bSJed Brown DM dm; 2908942e3340SBarry Smith DMSNES sdm; 2909e0e3a89bSBarry Smith KSP ksp; 29103a40ed3dSBarry Smith 29113a40ed3dSBarry Smith PetscFunctionBegin; 29120700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 29130700a824SBarry Smith PetscValidHeaderSpecific(X, VEC_CLASSID, 2); 2914c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, X, 2); 2915e0f629ddSJacob Faibussowitsch PetscCall(VecValidValues_Internal(X, 2, PETSC_TRUE)); 29169566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 29179566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 29183232da50SPeter Brune 291901c1178eSBarry Smith /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix-free */ 2920fe3ffe1eSBarry Smith if (snes->lagjacobian == -2) { 2921fe3ffe1eSBarry Smith snes->lagjacobian = -1; 2922f5af7f23SKarl Rupp 29239566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n")); 2924fe3ffe1eSBarry Smith } else if (snes->lagjacobian == -1) { 29259566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is -1\n")); 29269566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag)); 2927ebd3b9afSBarry Smith if (flag) { 29289566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 29299566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 2930ebd3b9afSBarry Smith } 29313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 293237ec4e1aSPeter Brune } else if (snes->lagjacobian > 1 && (snes->iter + snes->jac_iter) % snes->lagjacobian) { 293363a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagjacobian, snes->iter)); 29349566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag)); 2935ebd3b9afSBarry Smith if (flag) { 29369566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 29379566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 2938ebd3b9afSBarry Smith } 29393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2940e35cf81dSBarry Smith } 2941efd4aadfSBarry Smith if (snes->npc && snes->npcside == PC_LEFT) { 29429566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 29439566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 29443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2945d728fb7dSPeter Brune } 2946e35cf81dSBarry Smith 29479566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_JacobianEval, snes, X, A, B)); 29489566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(X)); 2949800f99ffSJeremy L Thompson { 2950800f99ffSJeremy L Thompson void *ctx; 29518434afd1SBarry Smith SNESJacobianFn *J; 2952800f99ffSJeremy L Thompson PetscCall(DMSNESGetJacobian(dm, &J, &ctx)); 2953800f99ffSJeremy L Thompson PetscCallBack("SNES callback Jacobian", (*J)(snes, X, A, B, ctx)); 2954800f99ffSJeremy L Thompson } 29559566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(X)); 29569566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_JacobianEval, snes, X, A, B)); 295728d58a37SPierre Jolivet 29587addb90fSBarry Smith /* attach latest linearization point to the matrix used to construct the preconditioner */ 29599566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)B, "__SNES_latest_X", (PetscObject)X)); 2960a8054027SBarry Smith 2961e0e3a89bSBarry Smith /* the next line ensures that snes->ksp exists */ 29629566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 29633b4f5425SBarry Smith if (snes->lagpreconditioner == -2) { 29649566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Rebuilding preconditioner exactly once since lag is -2\n")); 29659566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE)); 29663b4f5425SBarry Smith snes->lagpreconditioner = -1; 29673b4f5425SBarry Smith } else if (snes->lagpreconditioner == -1) { 29689566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is -1\n")); 29699566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE)); 297037ec4e1aSPeter Brune } else if (snes->lagpreconditioner > 1 && (snes->iter + snes->pre_iter) % snes->lagpreconditioner) { 297163a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagpreconditioner, snes->iter)); 29729566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE)); 2973d1e9a80fSBarry Smith } else { 29749566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Rebuilding preconditioner\n")); 29759566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE)); 2976a8054027SBarry Smith } 2977a8054027SBarry Smith 29784df93895SStefano Zampini /* monkey business to allow testing Jacobians in multilevel solvers. 29794df93895SStefano Zampini This is needed because the SNESTestXXX interface does not accept vectors and matrices */ 29804df93895SStefano Zampini { 29814df93895SStefano Zampini Vec xsave = snes->vec_sol; 29824df93895SStefano Zampini Mat jacobiansave = snes->jacobian; 29834df93895SStefano Zampini Mat jacobian_presave = snes->jacobian_pre; 29844df93895SStefano Zampini 29854df93895SStefano Zampini snes->vec_sol = X; 29864df93895SStefano Zampini snes->jacobian = A; 29874df93895SStefano Zampini snes->jacobian_pre = B; 2988494a190aSStefano Zampini PetscCall(SNESTestFunction(snes)); 29899566063dSJacob Faibussowitsch PetscCall(SNESTestJacobian(snes)); 2990494a190aSStefano Zampini 29914df93895SStefano Zampini snes->vec_sol = xsave; 29924df93895SStefano Zampini snes->jacobian = jacobiansave; 29934df93895SStefano Zampini snes->jacobian_pre = jacobian_presave; 29944df93895SStefano Zampini } 29954df93895SStefano Zampini 2996693365a8SJed Brown { 2997693365a8SJed Brown PetscBool flag = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_operator = PETSC_FALSE; 2998648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit", NULL, NULL, &flag)); 2999648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw", NULL, NULL, &flag_draw)); 3000648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw_contour", NULL, NULL, &flag_contour)); 3001648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_operator", NULL, NULL, &flag_operator)); 3002693365a8SJed Brown if (flag || flag_draw || flag_contour) { 30030298fd71SBarry Smith Mat Bexp_mine = NULL, Bexp, FDexp; 3004693365a8SJed Brown PetscViewer vdraw, vstdout; 30056b3a5b13SJed Brown PetscBool flg; 3006693365a8SJed Brown if (flag_operator) { 30079566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(A, MATAIJ, &Bexp_mine)); 3008693365a8SJed Brown Bexp = Bexp_mine; 3009693365a8SJed Brown } else { 30107addb90fSBarry Smith /* See if the matrix used to construct the preconditioner can be viewed and added directly */ 30119566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)B, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPIBAIJ, "")); 301294ab13aaSBarry Smith if (flg) Bexp = B; 3013693365a8SJed Brown else { 3014693365a8SJed Brown /* If the "preconditioning" matrix is itself MATSHELL or some other type without direct support */ 30159566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(B, MATAIJ, &Bexp_mine)); 3016693365a8SJed Brown Bexp = Bexp_mine; 3017693365a8SJed Brown } 3018693365a8SJed Brown } 30199566063dSJacob Faibussowitsch PetscCall(MatConvert(Bexp, MATSAME, MAT_INITIAL_MATRIX, &FDexp)); 30209566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobianDefault(snes, X, FDexp, FDexp, NULL)); 30219566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout)); 3022693365a8SJed Brown if (flag_draw || flag_contour) { 30239566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Explicit Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw)); 30249566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 30250298fd71SBarry Smith } else vdraw = NULL; 30269566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit %s\n", flag_operator ? "Jacobian" : "preconditioning Jacobian")); 30279566063dSJacob Faibussowitsch if (flag) PetscCall(MatView(Bexp, vstdout)); 30289566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(Bexp, vdraw)); 30299566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Finite difference Jacobian\n")); 30309566063dSJacob Faibussowitsch if (flag) PetscCall(MatView(FDexp, vstdout)); 30319566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(FDexp, vdraw)); 30329566063dSJacob Faibussowitsch PetscCall(MatAYPX(FDexp, -1.0, Bexp, SAME_NONZERO_PATTERN)); 30339566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian\n")); 30349566063dSJacob Faibussowitsch if (flag) PetscCall(MatView(FDexp, vstdout)); 3035693365a8SJed Brown if (vdraw) { /* Always use contour for the difference */ 30369566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 30379566063dSJacob Faibussowitsch PetscCall(MatView(FDexp, vdraw)); 30389566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(vdraw)); 3039693365a8SJed Brown } 30409566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw)); 30419566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&vdraw)); 30429566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bexp_mine)); 30439566063dSJacob Faibussowitsch PetscCall(MatDestroy(&FDexp)); 3044693365a8SJed Brown } 3045693365a8SJed Brown } 30464c30e9fbSJed Brown { 30476719d8e4SJed Brown PetscBool flag = PETSC_FALSE, flag_display = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_threshold = PETSC_FALSE; 30486719d8e4SJed Brown PetscReal threshold_atol = PETSC_SQRT_MACHINE_EPSILON, threshold_rtol = 10 * PETSC_SQRT_MACHINE_EPSILON; 3049648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring", NULL, NULL, &flag)); 3050648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_display", NULL, NULL, &flag_display)); 3051648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw", NULL, NULL, &flag_draw)); 3052648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw_contour", NULL, NULL, &flag_contour)); 3053648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold", NULL, NULL, &flag_threshold)); 305427b0f280SBarry Smith if (flag_threshold) { 30559566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_rtol", &threshold_rtol, NULL)); 30569566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_atol", &threshold_atol, NULL)); 305727b0f280SBarry Smith } 30586719d8e4SJed Brown if (flag || flag_display || flag_draw || flag_contour || flag_threshold) { 30594c30e9fbSJed Brown Mat Bfd; 30604c30e9fbSJed Brown PetscViewer vdraw, vstdout; 3061335efc43SPeter Brune MatColoring coloring; 30624c30e9fbSJed Brown ISColoring iscoloring; 30634c30e9fbSJed Brown MatFDColoring matfdcoloring; 30648434afd1SBarry Smith SNESFunctionFn *func; 30654c30e9fbSJed Brown void *funcctx; 30666719d8e4SJed Brown PetscReal norm1, norm2, normmax; 30674c30e9fbSJed Brown 30689566063dSJacob Faibussowitsch PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &Bfd)); 30699566063dSJacob Faibussowitsch PetscCall(MatColoringCreate(Bfd, &coloring)); 30709566063dSJacob Faibussowitsch PetscCall(MatColoringSetType(coloring, MATCOLORINGSL)); 30719566063dSJacob Faibussowitsch PetscCall(MatColoringSetFromOptions(coloring)); 30729566063dSJacob Faibussowitsch PetscCall(MatColoringApply(coloring, &iscoloring)); 30739566063dSJacob Faibussowitsch PetscCall(MatColoringDestroy(&coloring)); 30749566063dSJacob Faibussowitsch PetscCall(MatFDColoringCreate(Bfd, iscoloring, &matfdcoloring)); 30759566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFromOptions(matfdcoloring)); 30769566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetUp(Bfd, iscoloring, matfdcoloring)); 30779566063dSJacob Faibussowitsch PetscCall(ISColoringDestroy(&iscoloring)); 30784c30e9fbSJed Brown 30794c30e9fbSJed Brown /* This method of getting the function is currently unreliable since it doesn't work for DM local functions. */ 30809566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, &func, &funcctx)); 30819566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFunction(matfdcoloring, (PetscErrorCode (*)(void))func, funcctx)); 30829566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)matfdcoloring, ((PetscObject)snes)->prefix)); 30839566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)matfdcoloring, "coloring_")); 30849566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFromOptions(matfdcoloring)); 30859566063dSJacob Faibussowitsch PetscCall(MatFDColoringApply(Bfd, matfdcoloring, X, snes)); 30869566063dSJacob Faibussowitsch PetscCall(MatFDColoringDestroy(&matfdcoloring)); 30874c30e9fbSJed Brown 30889566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout)); 30894c30e9fbSJed Brown if (flag_draw || flag_contour) { 30909566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Colored Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw)); 30919566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 30920298fd71SBarry Smith } else vdraw = NULL; 30939566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit preconditioning Jacobian\n")); 30949566063dSJacob Faibussowitsch if (flag_display) PetscCall(MatView(B, vstdout)); 30959566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(B, vdraw)); 30969566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Colored Finite difference Jacobian\n")); 30979566063dSJacob Faibussowitsch if (flag_display) PetscCall(MatView(Bfd, vstdout)); 30989566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(Bfd, vdraw)); 30999566063dSJacob Faibussowitsch PetscCall(MatAYPX(Bfd, -1.0, B, SAME_NONZERO_PATTERN)); 31009566063dSJacob Faibussowitsch PetscCall(MatNorm(Bfd, NORM_1, &norm1)); 31019566063dSJacob Faibussowitsch PetscCall(MatNorm(Bfd, NORM_FROBENIUS, &norm2)); 31029566063dSJacob Faibussowitsch PetscCall(MatNorm(Bfd, NORM_MAX, &normmax)); 31039566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian, norm1=%g normFrob=%g normmax=%g\n", (double)norm1, (double)norm2, (double)normmax)); 31049566063dSJacob Faibussowitsch if (flag_display) PetscCall(MatView(Bfd, vstdout)); 31054c30e9fbSJed Brown if (vdraw) { /* Always use contour for the difference */ 31069566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 31079566063dSJacob Faibussowitsch PetscCall(MatView(Bfd, vdraw)); 31089566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(vdraw)); 31094c30e9fbSJed Brown } 31109566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw)); 31116719d8e4SJed Brown 31126719d8e4SJed Brown if (flag_threshold) { 31136719d8e4SJed Brown PetscInt bs, rstart, rend, i; 31149566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(B, &bs)); 31159566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(B, &rstart, &rend)); 31166719d8e4SJed Brown for (i = rstart; i < rend; i++) { 31176719d8e4SJed Brown const PetscScalar *ba, *ca; 31186719d8e4SJed Brown const PetscInt *bj, *cj; 31196719d8e4SJed Brown PetscInt bn, cn, j, maxentrycol = -1, maxdiffcol = -1, maxrdiffcol = -1; 31206719d8e4SJed Brown PetscReal maxentry = 0, maxdiff = 0, maxrdiff = 0; 31219566063dSJacob Faibussowitsch PetscCall(MatGetRow(B, i, &bn, &bj, &ba)); 31229566063dSJacob Faibussowitsch PetscCall(MatGetRow(Bfd, i, &cn, &cj, &ca)); 31235f80ce2aSJacob Faibussowitsch PetscCheck(bn == cn, ((PetscObject)A)->comm, PETSC_ERR_PLIB, "Unexpected different nonzero pattern in -snes_compare_coloring_threshold"); 31246719d8e4SJed Brown for (j = 0; j < bn; j++) { 31256719d8e4SJed Brown PetscReal rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j])); 31266719d8e4SJed Brown if (PetscAbsScalar(ba[j]) > PetscAbs(maxentry)) { 31276719d8e4SJed Brown maxentrycol = bj[j]; 31286719d8e4SJed Brown maxentry = PetscRealPart(ba[j]); 31296719d8e4SJed Brown } 31306719d8e4SJed Brown if (PetscAbsScalar(ca[j]) > PetscAbs(maxdiff)) { 31316719d8e4SJed Brown maxdiffcol = bj[j]; 31326719d8e4SJed Brown maxdiff = PetscRealPart(ca[j]); 31336719d8e4SJed Brown } 31346719d8e4SJed Brown if (rdiff > maxrdiff) { 31356719d8e4SJed Brown maxrdiffcol = bj[j]; 31366719d8e4SJed Brown maxrdiff = rdiff; 31376719d8e4SJed Brown } 31386719d8e4SJed Brown } 31396719d8e4SJed Brown if (maxrdiff > 1) { 314063a3b9bcSJacob 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)); 31416719d8e4SJed Brown for (j = 0; j < bn; j++) { 31426719d8e4SJed Brown PetscReal rdiff; 31436719d8e4SJed Brown rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j])); 314448a46eb9SPierre Jolivet if (rdiff > 1) PetscCall(PetscViewerASCIIPrintf(vstdout, " (%" PetscInt_FMT ",%g:%g)", bj[j], (double)PetscRealPart(ba[j]), (double)PetscRealPart(ca[j]))); 31456719d8e4SJed Brown } 314663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "\n")); 31476719d8e4SJed Brown } 31489566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(B, i, &bn, &bj, &ba)); 31499566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(Bfd, i, &cn, &cj, &ca)); 31506719d8e4SJed Brown } 31516719d8e4SJed Brown } 31529566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&vdraw)); 31539566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bfd)); 31544c30e9fbSJed Brown } 31554c30e9fbSJed Brown } 31563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 31579b94acceSBarry Smith } 31589b94acceSBarry Smith 31599b94acceSBarry Smith /*@C 31609b94acceSBarry Smith SNESSetJacobian - Sets the function to compute Jacobian as well as the 3161044dda88SLois Curfman McInnes location to store the matrix. 31629b94acceSBarry Smith 3163c3339decSBarry Smith Logically Collective 3164c7afd0dbSLois Curfman McInnes 31659b94acceSBarry Smith Input Parameters: 3166f6dfbefdSBarry Smith + snes - the `SNES` context 3167e5d3d808SBarry Smith . Amat - the matrix that defines the (approximate) Jacobian 3168dc4c0fb0SBarry Smith . Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`. 31698434afd1SBarry Smith . J - Jacobian evaluation routine (if `NULL` then `SNES` retains any previously set value), see `SNESJacobianFn` for details 3170c7afd0dbSLois Curfman McInnes - ctx - [optional] user-defined context for private data for the 3171dc4c0fb0SBarry Smith Jacobian evaluation routine (may be `NULL`) (if `NULL` then `SNES` retains any previously set value) 3172dc4c0fb0SBarry Smith 3173dc4c0fb0SBarry Smith Level: beginner 31749b94acceSBarry Smith 31759b94acceSBarry Smith Notes: 3176dc4c0fb0SBarry Smith If the `Amat` matrix and `Pmat` matrix are different you must call `MatAssemblyBegin()`/`MatAssemblyEnd()` on 317716913363SBarry Smith each matrix. 317816913363SBarry Smith 3179dc4c0fb0SBarry Smith If you know the operator `Amat` has a null space you can use `MatSetNullSpace()` and `MatSetTransposeNullSpace()` to supply the null 3180dc4c0fb0SBarry Smith space to `Amat` and the `KSP` solvers will automatically use that null space as needed during the solution process. 3181895c21f2SBarry Smith 3182dc4c0fb0SBarry Smith If using `SNESComputeJacobianDefaultColor()` to assemble a Jacobian, the `ctx` argument 3183f6dfbefdSBarry Smith must be a `MatFDColoring`. 3184a8a26c1eSJed Brown 3185c3cc8fd1SJed Brown Other defect-correction schemes can be used by computing a different matrix in place of the Jacobian. One common 3186f6dfbefdSBarry Smith example is to use the "Picard linearization" which only differentiates through the highest order parts of each term using `SNESSetPicard()` 3187c3cc8fd1SJed Brown 31881cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSPSetOperators()`, `SNESSetFunction()`, `MatMFFDComputeJacobian()`, `SNESComputeJacobianDefaultColor()`, `MatStructure`, 31898434afd1SBarry Smith `SNESSetPicard()`, `SNESJacobianFn`, `SNESFunctionFn` 31909b94acceSBarry Smith @*/ 31918434afd1SBarry Smith PetscErrorCode SNESSetJacobian(SNES snes, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx) 3192d71ae5a4SJacob Faibussowitsch { 31936cab3a1bSJed Brown DM dm; 31943a7fca6bSBarry Smith 31953a40ed3dSBarry Smith PetscFunctionBegin; 31960700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3197e5d3d808SBarry Smith if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2); 3198e5d3d808SBarry Smith if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3); 3199e5d3d808SBarry Smith if (Amat) PetscCheckSameComm(snes, 1, Amat, 2); 3200e5d3d808SBarry Smith if (Pmat) PetscCheckSameComm(snes, 1, Pmat, 3); 32019566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 32029566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, J, ctx)); 3203e5d3d808SBarry Smith if (Amat) { 32049566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)Amat)); 32059566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian)); 3206f5af7f23SKarl Rupp 3207e5d3d808SBarry Smith snes->jacobian = Amat; 32083a7fca6bSBarry Smith } 3209e5d3d808SBarry Smith if (Pmat) { 32109566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)Pmat)); 32119566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian_pre)); 3212f5af7f23SKarl Rupp 3213e5d3d808SBarry Smith snes->jacobian_pre = Pmat; 32143a7fca6bSBarry Smith } 32153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 32169b94acceSBarry Smith } 321762fef451SLois Curfman McInnes 3218c2aafc4cSSatish Balay /*@C 3219b4fd4287SBarry Smith SNESGetJacobian - Returns the Jacobian matrix and optionally the user 3220b4fd4287SBarry Smith provided context for evaluating the Jacobian. 3221b4fd4287SBarry Smith 3222420bcc1bSBarry Smith Not Collective, but `Mat` object will be parallel if `SNES` is 3223c7afd0dbSLois Curfman McInnes 3224b4fd4287SBarry Smith Input Parameter: 3225b4fd4287SBarry Smith . snes - the nonlinear solver context 3226b4fd4287SBarry Smith 3227b4fd4287SBarry Smith Output Parameters: 3228dc4c0fb0SBarry Smith + Amat - location to stash (approximate) Jacobian matrix (or `NULL`) 3229dc4c0fb0SBarry Smith . Pmat - location to stash matrix used to compute the preconditioner (or `NULL`) 32308434afd1SBarry Smith . J - location to put Jacobian function (or `NULL`), for calling sequence see `SNESJacobianFn` 3231dc4c0fb0SBarry Smith - ctx - location to stash Jacobian ctx (or `NULL`) 3232fee21e36SBarry Smith 323336851e7fSLois Curfman McInnes Level: advanced 323436851e7fSLois Curfman McInnes 32358434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `Mat`, `SNESSetJacobian()`, `SNESComputeJacobian()`, `SNESJacobianFn`, `SNESGetFunction()` 3236b4fd4287SBarry Smith @*/ 32378434afd1SBarry Smith PetscErrorCode SNESGetJacobian(SNES snes, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx) 3238d71ae5a4SJacob Faibussowitsch { 32396cab3a1bSJed Brown DM dm; 32406cab3a1bSJed Brown 32413a40ed3dSBarry Smith PetscFunctionBegin; 32420700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3243e5d3d808SBarry Smith if (Amat) *Amat = snes->jacobian; 3244e5d3d808SBarry Smith if (Pmat) *Pmat = snes->jacobian_pre; 32459566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 3246800f99ffSJeremy L Thompson PetscCall(DMSNESGetJacobian(dm, J, ctx)); 32473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3248b4fd4287SBarry Smith } 3249b4fd4287SBarry Smith 3250d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetDefaultComputeJacobian(SNES snes) 3251d71ae5a4SJacob Faibussowitsch { 325258b371f3SBarry Smith DM dm; 325358b371f3SBarry Smith DMSNES sdm; 325458b371f3SBarry Smith 325558b371f3SBarry Smith PetscFunctionBegin; 32569566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 32579566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 325858b371f3SBarry Smith if (!sdm->ops->computejacobian && snes->jacobian_pre) { 325958b371f3SBarry Smith DM dm; 326058b371f3SBarry Smith PetscBool isdense, ismf; 326158b371f3SBarry Smith 32629566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 32639566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &isdense, MATSEQDENSE, MATMPIDENSE, MATDENSE, NULL)); 32649566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &ismf, MATMFFD, MATSHELL, NULL)); 326558b371f3SBarry Smith if (isdense) { 32669566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefault, NULL)); 326758b371f3SBarry Smith } else if (!ismf) { 32689566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefaultColor, NULL)); 326958b371f3SBarry Smith } 327058b371f3SBarry Smith } 32713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 327258b371f3SBarry Smith } 327358b371f3SBarry Smith 32749b94acceSBarry Smith /*@ 32759b94acceSBarry Smith SNESSetUp - Sets up the internal data structures for the later use 32760b4b7b1cSBarry Smith of a nonlinear solver `SNESSolve()`. 32779b94acceSBarry Smith 3278c3339decSBarry Smith Collective 3279fee21e36SBarry Smith 32802fe279fdSBarry Smith Input Parameter: 3281f6dfbefdSBarry Smith . snes - the `SNES` context 3282c7afd0dbSLois Curfman McInnes 3283dc4c0fb0SBarry Smith Level: advanced 3284dc4c0fb0SBarry Smith 3285f6dfbefdSBarry Smith Note: 32860b4b7b1cSBarry Smith For basic use of the `SNES` solvers the user does not need to explicitly call 3287f6dfbefdSBarry Smith `SNESSetUp()`, since these actions will automatically occur during 3288f6dfbefdSBarry Smith the call to `SNESSolve()`. However, if one wishes to control this 3289f6dfbefdSBarry Smith phase separately, `SNESSetUp()` should be called after `SNESCreate()` 3290f6dfbefdSBarry Smith and optional routines of the form SNESSetXXX(), but before `SNESSolve()`. 3291272ac6f2SLois Curfman McInnes 32920b4b7b1cSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`, `SNESDestroy()`, `SNESSetFromOptions()` 32939b94acceSBarry Smith @*/ 3294d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUp(SNES snes) 3295d71ae5a4SJacob Faibussowitsch { 32966cab3a1bSJed Brown DM dm; 3297942e3340SBarry Smith DMSNES sdm; 3298c35f09e5SBarry Smith SNESLineSearch linesearch, pclinesearch; 32996e2a1849SPeter Brune void *lsprectx, *lspostctx; 33009b5c1c08SStefano Zampini PetscBool mf_operator, mf; 33019b5c1c08SStefano Zampini Vec f, fpc; 33029b5c1c08SStefano Zampini void *funcctx; 33039b5c1c08SStefano Zampini void *jacctx, *appctx; 33049b5c1c08SStefano Zampini Mat j, jpre; 33056b2b7091SBarry Smith PetscErrorCode (*precheck)(SNESLineSearch, Vec, Vec, PetscBool *, void *); 33066b2b7091SBarry Smith PetscErrorCode (*postcheck)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *); 33078434afd1SBarry Smith SNESFunctionFn *func; 33088434afd1SBarry Smith SNESJacobianFn *jac; 33093a40ed3dSBarry Smith 33103a40ed3dSBarry Smith PetscFunctionBegin; 33110700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 33123ba16761SJacob Faibussowitsch if (snes->setupcalled) PetscFunctionReturn(PETSC_SUCCESS); 3313fc8bc0e3SRichard Tran Mills PetscCall(PetscLogEventBegin(SNES_SetUp, snes, 0, 0, 0)); 33149b94acceSBarry Smith 331548a46eb9SPierre Jolivet if (!((PetscObject)snes)->type_name) PetscCall(SNESSetType(snes, SNESNEWTONLS)); 331685385478SLisandro Dalcin 33179566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &snes->vec_func, NULL, NULL)); 331858c9b817SLisandro Dalcin 33199566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 33209566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 33219566063dSJacob Faibussowitsch PetscCall(SNESSetDefaultComputeJacobian(snes)); 332258b371f3SBarry Smith 332348a46eb9SPierre Jolivet if (!snes->vec_func) PetscCall(DMCreateGlobalVector(dm, &snes->vec_func)); 3324efd51863SBarry Smith 332548a46eb9SPierre Jolivet if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 3326b710008aSBarry Smith 3327d8d34be6SBarry Smith if (snes->linesearch) { 33289566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 33299566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetFunction(snes->linesearch, SNESComputeFunction)); 3330d8d34be6SBarry Smith } 33319e764e56SPeter Brune 33329b5c1c08SStefano Zampini PetscCall(SNESGetUseMatrixFree(snes, &mf_operator, &mf)); 3333b552625fSStefano Zampini if (snes->npc && snes->npcside == PC_LEFT) { 3334172a4300SPeter Brune snes->mf = PETSC_TRUE; 3335172a4300SPeter Brune snes->mf_operator = PETSC_FALSE; 3336172a4300SPeter Brune } 3337d8f46077SPeter Brune 3338efd4aadfSBarry Smith if (snes->npc) { 33396e2a1849SPeter Brune /* copy the DM over */ 33409566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 33419566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes->npc, dm)); 33426e2a1849SPeter Brune 33439566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &f, &func, &funcctx)); 33449566063dSJacob Faibussowitsch PetscCall(VecDuplicate(f, &fpc)); 33459566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes->npc, fpc, func, funcctx)); 33469566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, &j, &jpre, &jac, &jacctx)); 33479566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes->npc, j, jpre, jac, jacctx)); 33489566063dSJacob Faibussowitsch PetscCall(SNESGetApplicationContext(snes, &appctx)); 33499566063dSJacob Faibussowitsch PetscCall(SNESSetApplicationContext(snes->npc, appctx)); 33509b5c1c08SStefano Zampini PetscCall(SNESSetUseMatrixFree(snes->npc, mf_operator, mf)); 33519566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fpc)); 33526e2a1849SPeter Brune 33536e2a1849SPeter Brune /* copy the function pointers over */ 33549566063dSJacob Faibussowitsch PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)snes->npc)); 33556e2a1849SPeter Brune 33566e2a1849SPeter Brune /* default to 1 iteration */ 33579566063dSJacob Faibussowitsch PetscCall(SNESSetTolerances(snes->npc, 0.0, 0.0, 0.0, 1, snes->npc->max_funcs)); 3358efd4aadfSBarry Smith if (snes->npcside == PC_RIGHT) { 33599566063dSJacob Faibussowitsch PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_FINAL_ONLY)); 3360a9936a0cSPeter Brune } else { 33619566063dSJacob Faibussowitsch PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_NONE)); 3362a9936a0cSPeter Brune } 33639566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes->npc)); 33646e2a1849SPeter Brune 33656e2a1849SPeter Brune /* copy the line search context over */ 3366d8d34be6SBarry Smith if (snes->linesearch && snes->npc->linesearch) { 33679566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &linesearch)); 33689566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes->npc, &pclinesearch)); 33699566063dSJacob Faibussowitsch PetscCall(SNESLineSearchGetPreCheck(linesearch, &precheck, &lsprectx)); 33709566063dSJacob Faibussowitsch PetscCall(SNESLineSearchGetPostCheck(linesearch, &postcheck, &lspostctx)); 33719566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetPreCheck(pclinesearch, precheck, lsprectx)); 33729566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetPostCheck(pclinesearch, postcheck, lspostctx)); 33739566063dSJacob Faibussowitsch PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch)); 33746e2a1849SPeter Brune } 3375d8d34be6SBarry Smith } 33761baa6e33SBarry Smith if (snes->mf) PetscCall(SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version)); 3377835f2295SStefano Zampini if (snes->ops->usercompute && !snes->ctx) PetscCallBack("SNES callback compute application context", (*snes->ops->usercompute)(snes, &snes->ctx)); 33786e2a1849SPeter Brune 337937ec4e1aSPeter Brune snes->jac_iter = 0; 338037ec4e1aSPeter Brune snes->pre_iter = 0; 338137ec4e1aSPeter Brune 3382dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, setup); 338358c9b817SLisandro Dalcin 33849566063dSJacob Faibussowitsch PetscCall(SNESSetDefaultComputeJacobian(snes)); 338558b371f3SBarry Smith 3386b552625fSStefano Zampini if (snes->npc && snes->npcside == PC_LEFT) { 33876c67d002SPeter Brune if (snes->functype == SNES_FUNCTION_PRECONDITIONED) { 3388d8d34be6SBarry Smith if (snes->linesearch) { 33899566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &linesearch)); 33909566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunctionDefaultNPC)); 33916c67d002SPeter Brune } 33926c67d002SPeter Brune } 3393d8d34be6SBarry Smith } 3394fc8bc0e3SRichard Tran Mills PetscCall(PetscLogEventEnd(SNES_SetUp, snes, 0, 0, 0)); 33957aaed0d8SBarry Smith snes->setupcalled = PETSC_TRUE; 33963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 33979b94acceSBarry Smith } 33989b94acceSBarry Smith 339937596af1SLisandro Dalcin /*@ 34000b4b7b1cSBarry Smith SNESReset - Resets a `SNES` context to the state it was in before `SNESSetUp()` was called and removes any allocated `Vec` and `Mat` from its data structures 340137596af1SLisandro Dalcin 3402c3339decSBarry Smith Collective 340337596af1SLisandro Dalcin 340437596af1SLisandro Dalcin Input Parameter: 34050b4b7b1cSBarry Smith . snes - the nonlinear iterative solver context obtained from `SNESCreate()` 340637596af1SLisandro Dalcin 3407d25893d9SBarry Smith Level: intermediate 3408d25893d9SBarry Smith 340995452b02SPatrick Sanan Notes: 34100b4b7b1cSBarry Smith Any options set on the `SNES` object, including those set with `SNESSetFromOptions()` remain. 34110b4b7b1cSBarry Smith 3412f6dfbefdSBarry Smith Call this if you wish to reuse a `SNES` but with different size vectors 341337596af1SLisandro Dalcin 3414f6dfbefdSBarry Smith Also calls the application context destroy routine set with `SNESSetComputeApplicationContext()` 3415f6dfbefdSBarry Smith 34161cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESDestroy()`, `SNESCreate()`, `SNESSetUp()`, `SNESSolve()` 341737596af1SLisandro Dalcin @*/ 3418d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESReset(SNES snes) 3419d71ae5a4SJacob Faibussowitsch { 342037596af1SLisandro Dalcin PetscFunctionBegin; 342137596af1SLisandro Dalcin PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 342249abdd8aSBarry Smith if (snes->ops->ctxdestroy && snes->ctx) { 3423835f2295SStefano Zampini PetscCallBack("SNES callback destroy application context", (*snes->ops->ctxdestroy)(&snes->ctx)); 342449abdd8aSBarry Smith snes->ctx = NULL; 3425d25893d9SBarry Smith } 34261baa6e33SBarry Smith if (snes->npc) PetscCall(SNESReset(snes->npc)); 34278a23116dSBarry Smith 3428dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, reset); 34291baa6e33SBarry Smith if (snes->ksp) PetscCall(KSPReset(snes->ksp)); 34309e764e56SPeter Brune 34311baa6e33SBarry Smith if (snes->linesearch) PetscCall(SNESLineSearchReset(snes->linesearch)); 34329e764e56SPeter Brune 34339566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_rhs)); 34349566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol)); 34359566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol_update)); 34369566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_func)); 34379566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian)); 34389566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian_pre)); 34399566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->picard)); 34409566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(snes->nwork, &snes->work)); 34419566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(snes->nvwork, &snes->vwork)); 3442f5af7f23SKarl Rupp 344340fdac6aSLawrence Mitchell snes->alwayscomputesfinalresidual = PETSC_FALSE; 344440fdac6aSLawrence Mitchell 344537596af1SLisandro Dalcin snes->nwork = snes->nvwork = 0; 344637596af1SLisandro Dalcin snes->setupcalled = PETSC_FALSE; 34473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 344837596af1SLisandro Dalcin } 344937596af1SLisandro Dalcin 345052baeb72SSatish Balay /*@ 345136d43d94SBarry Smith SNESConvergedReasonViewCancel - Clears all the reason view functions for a `SNES` object provided with `SNESConvergedReasonViewSet()` also 345236d43d94SBarry Smith removes the default viewer. 3453c4421ceaSFande Kong 3454c3339decSBarry Smith Collective 3455c4421ceaSFande Kong 3456c4421ceaSFande Kong Input Parameter: 34570b4b7b1cSBarry Smith . snes - the nonlinear iterative solver context obtained from `SNESCreate()` 3458c4421ceaSFande Kong 3459c4421ceaSFande Kong Level: intermediate 3460c4421ceaSFande Kong 3461420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESReset()`, `SNESConvergedReasonViewSet()` 3462c4421ceaSFande Kong @*/ 3463d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewCancel(SNES snes) 3464d71ae5a4SJacob Faibussowitsch { 3465c4421ceaSFande Kong PetscInt i; 3466c4421ceaSFande Kong 3467c4421ceaSFande Kong PetscFunctionBegin; 3468c4421ceaSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3469c4421ceaSFande Kong for (i = 0; i < snes->numberreasonviews; i++) { 347048a46eb9SPierre Jolivet if (snes->reasonviewdestroy[i]) PetscCall((*snes->reasonviewdestroy[i])(&snes->reasonviewcontext[i])); 3471c4421ceaSFande Kong } 3472c4421ceaSFande Kong snes->numberreasonviews = 0; 3473648c30bcSBarry Smith PetscCall(PetscViewerDestroy(&snes->convergedreasonviewer)); 34743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3475c4421ceaSFande Kong } 3476c4421ceaSFande Kong 34770764c050SBarry Smith /*@ 34789b94acceSBarry Smith SNESDestroy - Destroys the nonlinear solver context that was created 3479f6dfbefdSBarry Smith with `SNESCreate()`. 34809b94acceSBarry Smith 3481c3339decSBarry Smith Collective 3482c7afd0dbSLois Curfman McInnes 34839b94acceSBarry Smith Input Parameter: 3484f6dfbefdSBarry Smith . snes - the `SNES` context 34859b94acceSBarry Smith 348636851e7fSLois Curfman McInnes Level: beginner 348736851e7fSLois Curfman McInnes 34881cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()` 34899b94acceSBarry Smith @*/ 3490d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESDestroy(SNES *snes) 3491d71ae5a4SJacob Faibussowitsch { 3492*92e852f7SPablo Brubeck DM dm; 3493*92e852f7SPablo Brubeck 34943a40ed3dSBarry Smith PetscFunctionBegin; 34953ba16761SJacob Faibussowitsch if (!*snes) PetscFunctionReturn(PETSC_SUCCESS); 3496f4f49eeaSPierre Jolivet PetscValidHeaderSpecific(*snes, SNES_CLASSID, 1); 3497f4f49eeaSPierre Jolivet if (--((PetscObject)*snes)->refct > 0) { 34989371c9d4SSatish Balay *snes = NULL; 34993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 35009371c9d4SSatish Balay } 3501d4bb536fSBarry Smith 3502f4f49eeaSPierre Jolivet PetscCall(SNESReset(*snes)); 35039566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&(*snes)->npc)); 35046b8b9a38SLisandro Dalcin 3505e04113cfSBarry Smith /* if memory was published with SAWs then destroy it */ 35069566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsViewOff((PetscObject)*snes)); 3507f4f49eeaSPierre Jolivet PetscTryTypeMethod(*snes, destroy); 35086d4c513bSLisandro Dalcin 3509*92e852f7SPablo Brubeck dm = (*snes)->dm; 3510*92e852f7SPablo Brubeck while (dm) { 3511*92e852f7SPablo Brubeck PetscCall(DMCoarsenHookRemove(dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, *snes)); 3512*92e852f7SPablo Brubeck PetscCall(DMGetCoarseDM(dm, &dm)); 3513*92e852f7SPablo Brubeck } 3514*92e852f7SPablo Brubeck 35159566063dSJacob Faibussowitsch PetscCall(DMDestroy(&(*snes)->dm)); 35169566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&(*snes)->ksp)); 35179566063dSJacob Faibussowitsch PetscCall(SNESLineSearchDestroy(&(*snes)->linesearch)); 35186b8b9a38SLisandro Dalcin 35199566063dSJacob Faibussowitsch PetscCall(PetscFree((*snes)->kspconvctx)); 352048a46eb9SPierre Jolivet if ((*snes)->ops->convergeddestroy) PetscCall((*(*snes)->ops->convergeddestroy)((*snes)->cnvP)); 352148a46eb9SPierre Jolivet if ((*snes)->conv_hist_alloc) PetscCall(PetscFree2((*snes)->conv_hist, (*snes)->conv_hist_its)); 3522f4f49eeaSPierre Jolivet PetscCall(SNESMonitorCancel(*snes)); 3523f4f49eeaSPierre Jolivet PetscCall(SNESConvergedReasonViewCancel(*snes)); 35249566063dSJacob Faibussowitsch PetscCall(PetscHeaderDestroy(snes)); 35253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 35269b94acceSBarry Smith } 35279b94acceSBarry Smith 35289b94acceSBarry Smith /* ----------- Routines to set solver parameters ---------- */ 35299b94acceSBarry Smith 3530a8054027SBarry Smith /*@ 35310b4b7b1cSBarry Smith SNESSetLagPreconditioner - Sets when the preconditioner is rebuilt in the nonlinear solve `SNESSolve()`. 3532a8054027SBarry Smith 3533c3339decSBarry Smith Logically Collective 3534a8054027SBarry Smith 3535a8054027SBarry Smith Input Parameters: 3536f6dfbefdSBarry Smith + snes - the `SNES` context 3537d8e291bfSBarry Smith - lag - 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time 35383b4f5425SBarry Smith the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that 3539a8054027SBarry Smith 3540a8054027SBarry Smith Options Database Keys: 3541420bcc1bSBarry Smith + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple `SNESSolve()` 35423d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 3543420bcc1bSBarry Smith . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple `SNESSolve()` 35443d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 3545a8054027SBarry Smith 3546dc4c0fb0SBarry Smith Level: intermediate 3547dc4c0fb0SBarry Smith 3548420bcc1bSBarry Smith Notes: 3549a8054027SBarry Smith The default is 1 3550420bcc1bSBarry Smith 3551f6dfbefdSBarry Smith The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagPreconditionerPersists()` was called 3552d8e291bfSBarry Smith 3553f6dfbefdSBarry Smith `SNESSetLagPreconditionerPersists()` allows using the same uniform lagging (for example every second linear solve) across multiple nonlinear solves. 3554a8054027SBarry Smith 35553201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetLagPreconditionerPersists()`, 3556f6dfbefdSBarry Smith `SNESSetLagJacobianPersists()`, `SNES`, `SNESSolve()` 3557a8054027SBarry Smith @*/ 3558d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditioner(SNES snes, PetscInt lag) 3559d71ae5a4SJacob Faibussowitsch { 3560a8054027SBarry Smith PetscFunctionBegin; 35610700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 35625f80ce2aSJacob Faibussowitsch PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater"); 35635f80ce2aSJacob Faibussowitsch PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0"); 3564c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, lag, 2); 3565a8054027SBarry Smith snes->lagpreconditioner = lag; 35663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3567a8054027SBarry Smith } 3568a8054027SBarry Smith 3569efd51863SBarry Smith /*@ 3570f6dfbefdSBarry Smith SNESSetGridSequence - sets the number of steps of grid sequencing that `SNES` will do 3571efd51863SBarry Smith 3572c3339decSBarry Smith Logically Collective 3573efd51863SBarry Smith 3574efd51863SBarry Smith Input Parameters: 3575f6dfbefdSBarry Smith + snes - the `SNES` context 3576efd51863SBarry Smith - steps - the number of refinements to do, defaults to 0 3577efd51863SBarry Smith 3578f6dfbefdSBarry Smith Options Database Key: 357967b8a455SSatish Balay . -snes_grid_sequence <steps> - Use grid sequencing to generate initial guess 3580efd51863SBarry Smith 3581efd51863SBarry Smith Level: intermediate 3582efd51863SBarry Smith 35830b4b7b1cSBarry Smith Notes: 35840b4b7b1cSBarry Smith Once grid sequencing is turned on `SNESSolve()` will automatically perform the solve on each grid refinement. 35850b4b7b1cSBarry Smith 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()`, 358954c05997SPierre Jolivet `SNESSetDM()`, `SNESSolve()` 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 /*@ 38430b4b7b1cSBarry Smith SNESSetTolerances - Sets various parameters used in `SNES` convergence tests. 38449b94acceSBarry Smith 3845c3339decSBarry Smith Logically Collective 3846c7afd0dbSLois Curfman McInnes 38479b94acceSBarry Smith Input Parameters: 3848f6dfbefdSBarry Smith + snes - the `SNES` context 38490b4b7b1cSBarry Smith . abstol - the absolute convergence tolerance, $ F(x^n) \le abstol $ 38500b4b7b1cSBarry Smith . rtol - the relative convergence tolerance, $ F(x^n) \le reltol * F(x^0) $ 38515358d0d4SBarry Smith . stol - convergence tolerance in terms of the norm of the change in the solution between steps, || delta x || < stol*|| x || 38520b4b7b1cSBarry Smith . maxit - the maximum number of iterations allowed in the solver, default 50. 38530b4b7b1cSBarry Smith - maxf - the maximum number of function evaluations allowed in the solver (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 3908835f2295SStefano Zampini if (maxit == PETSC_DETERMINE) { 390977e5a1f9SBarry Smith snes->max_its = snes->default_max_its; 3910835f2295SStefano 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 3917835f2295SStefano Zampini if (maxf == PETSC_DETERMINE) { 391877e5a1f9SBarry Smith snes->max_funcs = snes->default_max_funcs; 3919835f2295SStefano 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 39350b4b7b1cSBarry Smith - divtol - the divergence tolerance. Use `PETSC_UNLIMITED` to deactivate the test. If the residual norm $ F(x^n) \ge divtol * F(x^0) $ the solver 39360b4b7b1cSBarry Smith is stopped due to divergence. 3937e4d06f11SPatrick Farrell 3938f6dfbefdSBarry Smith Options Database Key: 3939dc4c0fb0SBarry Smith . -snes_divergence_tolerance <divtol> - Sets `divtol` 3940e4d06f11SPatrick Farrell 3941e4d06f11SPatrick Farrell Level: intermediate 3942e4d06f11SPatrick Farrell 394377e5a1f9SBarry Smith Notes: 394477e5a1f9SBarry Smith Use `PETSC_DETERMINE` to use the default value from when the object's type was set. 3945e5cd489fSStefano Zampini 394677e5a1f9SBarry Smith Fortran Note: 394777e5a1f9SBarry Smith Use ``PETSC_DETERMINE_REAL` or `PETSC_UNLIMITED_REAL` 394877e5a1f9SBarry Smith 394977e5a1f9SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetTolerances()`, `SNESGetDivergenceTolerance()` 3950e4d06f11SPatrick Farrell @*/ 3951d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDivergenceTolerance(SNES snes, PetscReal divtol) 3952d71ae5a4SJacob Faibussowitsch { 3953e4d06f11SPatrick Farrell PetscFunctionBegin; 3954e4d06f11SPatrick Farrell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3955e4d06f11SPatrick Farrell PetscValidLogicalCollectiveReal(snes, divtol, 2); 395677e5a1f9SBarry Smith 395777e5a1f9SBarry Smith if (divtol == (PetscReal)PETSC_DETERMINE) { 395877e5a1f9SBarry Smith snes->divtol = snes->default_divtol; 395977e5a1f9SBarry Smith } else if (divtol == (PetscReal)PETSC_UNLIMITED || divtol == -1) { 396077e5a1f9SBarry Smith snes->divtol = PETSC_UNLIMITED; 396177e5a1f9SBarry Smith } else if (divtol != (PetscReal)PETSC_CURRENT) { 396277e5a1f9SBarry Smith PetscCheck(divtol >= 1.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Divergence tolerance %g must be greater than 1.0", (double)divtol); 396377e5a1f9SBarry Smith snes->divtol = divtol; 396477e5a1f9SBarry Smith } 39653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3966e4d06f11SPatrick Farrell } 3967e4d06f11SPatrick Farrell 39689b94acceSBarry Smith /*@ 39690b4b7b1cSBarry Smith SNESGetTolerances - Gets various parameters used in `SNES` convergence tests. 397033174efeSLois Curfman McInnes 3971c7afd0dbSLois Curfman McInnes Not Collective 3972c7afd0dbSLois Curfman McInnes 397377e5a1f9SBarry Smith Input Parameter: 397477e5a1f9SBarry Smith . snes - the `SNES` context 397577e5a1f9SBarry Smith 397677e5a1f9SBarry Smith Output Parameters: 39770b4b7b1cSBarry Smith + atol - the absolute convergence tolerance 39780b4b7b1cSBarry Smith . rtol - the relative convergence tolerance 397977e5a1f9SBarry Smith . stol - convergence tolerance in terms of the norm of the change in the solution between steps 39800b4b7b1cSBarry Smith . maxit - the maximum number of iterations allowed 39810b4b7b1cSBarry Smith - maxf - the maximum number of function evaluations allowed, `PETSC_UNLIMITED` indicates no bound 3982fee21e36SBarry Smith 398336851e7fSLois Curfman McInnes Level: intermediate 398436851e7fSLois Curfman McInnes 39850b4b7b1cSBarry Smith Notes: 39860b4b7b1cSBarry Smith See `SNESSetTolerances()` for details on the parameters. 39870b4b7b1cSBarry Smith 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 4113c948abdaSPierre Jolivet .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()` 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 /*@ 41310b4b7b1cSBarry Smith SNESMonitor - runs any `SNES` monitor routines provided with `SNESMonitor()` or the options database 4132228d79bcSJed Brown 4133c3339decSBarry Smith Collective 4134228d79bcSJed Brown 4135228d79bcSJed Brown Input Parameters: 4136f6dfbefdSBarry Smith + snes - nonlinear solver context obtained from `SNESCreate()` 41370b4b7b1cSBarry Smith . iter - current iteration number 41380b4b7b1cSBarry Smith - rnorm - current 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 41840b4b7b1cSBarry Smith iteration of the `SNES` 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; 4227835f2295SStefano 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 4286c948abdaSPierre Jolivet .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()` 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 /*@ 43180b4b7b1cSBarry Smith SNESGetConvergedReason - Gets the reason the `SNES` iteration was stopped, which may be due to convergence, divergence, or stagnation 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: 4413ce78bad3SBarry Smith If 'a' and 'its' are `NULL` then space is allocated for the history. If 'na' is `PETSC_DECIDE` (or, deprecated, `PETSC_DEFAULT`) 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 4481ce78bad3SBarry Smith Fortran Notes: 4482ce78bad3SBarry Smith Return the arrays with ``SNESRestoreConvergenceHistory()` 4483ce78bad3SBarry Smith 4484ce78bad3SBarry Smith Use the arguments 4485dc4c0fb0SBarry Smith .vb 4486ce78bad3SBarry Smith PetscReal, pointer :: a(:) 4487ce78bad3SBarry Smith PetscInt, pointer :: its(:) 4488dc4c0fb0SBarry Smith .ve 4489758f92a0SBarry Smith 44901cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceHistory()` 4491758f92a0SBarry Smith @*/ 4492d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergenceHistory(SNES snes, PetscReal *a[], PetscInt *its[], PetscInt *na) 4493d71ae5a4SJacob Faibussowitsch { 4494758f92a0SBarry Smith PetscFunctionBegin; 44950700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4496758f92a0SBarry Smith if (a) *a = snes->conv_hist; 4497758f92a0SBarry Smith if (its) *its = snes->conv_hist_its; 4498115dd874SBarry Smith if (na) *na = (PetscInt)snes->conv_hist_len; 44993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4500c9005455SLois Curfman McInnes } 4501c9005455SLois Curfman McInnes 4502ac226902SBarry Smith /*@C 450376b2cf59SMatthew Knepley SNESSetUpdate - Sets the general-purpose update function called 4504eec8f646SJed Brown at the beginning of every iteration of the nonlinear solve. Specifically 450553e5d35bSStefano Zampini it is called just before the Jacobian is "evaluated" and after the function 450653e5d35bSStefano Zampini evaluation. 450776b2cf59SMatthew Knepley 4508c3339decSBarry Smith Logically Collective 450976b2cf59SMatthew Knepley 451076b2cf59SMatthew Knepley Input Parameters: 4511a2b725a8SWilliam Gropp + snes - The nonlinear solver context 451253e5d35bSStefano Zampini - func - The update function; for calling sequence see `SNESUpdateFn` 451376b2cf59SMatthew Knepley 4514fe97e370SBarry Smith Level: advanced 4515fe97e370SBarry Smith 4516420bcc1bSBarry Smith Notes: 4517f6dfbefdSBarry 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 4518f6dfbefdSBarry Smith to `SNESSetFunction()`, or `SNESSetPicard()` 451953e5d35bSStefano Zampini This is not used by most users, and it is intended to provide a general hook that is run 452053e5d35bSStefano Zampini right before the direction step is computed. 4521ce78bad3SBarry Smith 452253e5d35bSStefano Zampini Users are free to modify the current residual vector, 452353e5d35bSStefano Zampini the current linearization point, or any other vector associated to the specific solver used. 452453e5d35bSStefano Zampini If such modifications take place, it is the user responsibility to update all the relevant 4525ce78bad3SBarry Smith vectors. For example, if one is adjusting the model parameters at each Newton step their code may look like 4526ce78bad3SBarry Smith .vb 4527ce78bad3SBarry Smith PetscErrorCode update(SNES snes, PetscInt iteration) 4528ce78bad3SBarry Smith { 4529ce78bad3SBarry Smith PetscFunctionBeginUser; 4530ce78bad3SBarry Smith if (iteration > 0) { 4531ce78bad3SBarry Smith // update the model parameters here 4532ce78bad3SBarry Smith Vec x,f; 4533ce78bad3SBarry Smith PetscCall(SNESGetSolution(snes,&x)); 4534ce78bad3SBarry Smith PetcCall(SNESGetFunction(snes,&f,NULL,NULL)); 4535ce78bad3SBarry Smith PetscCall(SNESComputeFunction(snes,x,f)); 4536ce78bad3SBarry Smith } 4537ce78bad3SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 4538ce78bad3SBarry Smith } 4539ce78bad3SBarry Smith .ve 454076b2cf59SMatthew Knepley 4541aaa8cc7dSPierre 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. 45426b7fb656SBarry Smith 4543e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetJacobian()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRSetPostCheck()`, 454453e5d35bSStefano Zampini `SNESMonitorSet()` 454576b2cf59SMatthew Knepley @*/ 454653e5d35bSStefano Zampini PetscErrorCode SNESSetUpdate(SNES snes, SNESUpdateFn *func) 4547d71ae5a4SJacob Faibussowitsch { 454876b2cf59SMatthew Knepley PetscFunctionBegin; 45490700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4550e7788613SBarry Smith snes->ops->update = func; 45513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 455276b2cf59SMatthew Knepley } 455376b2cf59SMatthew Knepley 4554ffeef943SBarry Smith /*@ 4555f6dfbefdSBarry Smith SNESConvergedReasonView - Displays the reason a `SNES` solve converged or diverged to a viewer 45562a359c20SBarry Smith 4557c3339decSBarry Smith Collective 45582a359c20SBarry Smith 4559e4094ef1SJacob Faibussowitsch Input Parameters: 4560f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 45612a359c20SBarry Smith - viewer - the viewer to display the reason 45622a359c20SBarry Smith 45632a359c20SBarry Smith Options Database Keys: 4564ee300463SSatish Balay + -snes_converged_reason - print reason for converged or diverged, also prints number of iterations 4565ee300463SSatish Balay - -snes_converged_reason ::failed - only print reason and number of iterations when diverged 4566eafd5ff0SAlex Lindsay 4567420bcc1bSBarry Smith Level: beginner 4568420bcc1bSBarry Smith 4569f6dfbefdSBarry Smith Note: 4570f6dfbefdSBarry Smith To change the format of the output call `PetscViewerPushFormat`(viewer,format) before this call. Use `PETSC_VIEWER_DEFAULT` for the default, 4571f6dfbefdSBarry Smith use `PETSC_VIEWER_FAILED` to only display a reason if it fails. 45722a359c20SBarry Smith 45731cc06b55SBarry Smith .seealso: [](ch_snes), `SNESConvergedReason`, `PetscViewer`, `SNES`, 4574f6dfbefdSBarry Smith `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, 4575f6dfbefdSBarry Smith `SNESConvergedReasonViewFromOptions()`, 4576db781477SPatrick Sanan `PetscViewerPushFormat()`, `PetscViewerPopFormat()` 45772a359c20SBarry Smith @*/ 4578d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonView(SNES snes, PetscViewer viewer) 4579d71ae5a4SJacob Faibussowitsch { 458075cca76cSMatthew G. Knepley PetscViewerFormat format; 45812a359c20SBarry Smith PetscBool isAscii; 45822a359c20SBarry Smith 45832a359c20SBarry Smith PetscFunctionBegin; 458419a666eeSBarry Smith if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)); 45859566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii)); 45862a359c20SBarry Smith if (isAscii) { 45879566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 458865bf60d2SBarry Smith PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel + 1)); 458975cca76cSMatthew G. Knepley if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 459075cca76cSMatthew G. Knepley DM dm; 459175cca76cSMatthew G. Knepley Vec u; 459275cca76cSMatthew G. Knepley PetscDS prob; 459375cca76cSMatthew G. Knepley PetscInt Nf, f; 459495cbbfd3SMatthew G. Knepley PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *); 459595cbbfd3SMatthew G. Knepley void **exactCtx; 459675cca76cSMatthew G. Knepley PetscReal error; 459775cca76cSMatthew G. Knepley 45989566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 45999566063dSJacob Faibussowitsch PetscCall(SNESGetSolution(snes, &u)); 46009566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob)); 46019566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(prob, &Nf)); 46029566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(Nf, &exactSol, Nf, &exactCtx)); 46039566063dSJacob Faibussowitsch for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f])); 46049566063dSJacob Faibussowitsch PetscCall(DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error)); 46059566063dSJacob Faibussowitsch PetscCall(PetscFree2(exactSol, exactCtx)); 46069566063dSJacob Faibussowitsch if (error < 1.0e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n")); 460763a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", (double)error)); 460875cca76cSMatthew G. Knepley } 4609eafd5ff0SAlex Lindsay if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) { 46102a359c20SBarry Smith if (((PetscObject)snes)->prefix) { 461163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter)); 46122a359c20SBarry Smith } else { 461363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve converged due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter)); 46142a359c20SBarry Smith } 4615eafd5ff0SAlex Lindsay } else if (snes->reason <= 0) { 46162a359c20SBarry Smith if (((PetscObject)snes)->prefix) { 461763a3b9bcSJacob 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)); 46182a359c20SBarry Smith } else { 461963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve did not converge due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter)); 46202a359c20SBarry Smith } 46212a359c20SBarry Smith } 462265bf60d2SBarry Smith PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel + 1)); 46232a359c20SBarry Smith } 46243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 46252a359c20SBarry Smith } 46262a359c20SBarry Smith 4627c4421ceaSFande Kong /*@C 4628c4421ceaSFande Kong SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the 4629aaa8cc7dSPierre Jolivet end of the nonlinear solver to display the convergence reason of the nonlinear solver. 4630c4421ceaSFande Kong 4631c3339decSBarry Smith Logically Collective 4632c4421ceaSFande Kong 4633c4421ceaSFande Kong Input Parameters: 4634f6dfbefdSBarry Smith + snes - the `SNES` context 4635420bcc1bSBarry Smith . f - the `SNESConvergedReason` view function 4636420bcc1bSBarry Smith . vctx - [optional] user-defined context for private data for the `SNESConvergedReason` view function (use `NULL` if no context is desired) 463749abdd8aSBarry Smith - reasonviewdestroy - [optional] routine that frees the context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence 4638420bcc1bSBarry Smith 4639420bcc1bSBarry Smith Calling sequence of `f`: 4640420bcc1bSBarry Smith + snes - the `SNES` context 464149abdd8aSBarry Smith - vctx - [optional] context for private data for the function 4642c4421ceaSFande Kong 4643c4421ceaSFande Kong Options Database Keys: 4644f6dfbefdSBarry Smith + -snes_converged_reason - sets a default `SNESConvergedReasonView()` 4645420bcc1bSBarry Smith - -snes_converged_reason_view_cancel - cancels all converged reason viewers that have been hardwired into a code by 4646420bcc1bSBarry Smith calls to `SNESConvergedReasonViewSet()`, but does not cancel those set via the options database. 4647c4421ceaSFande Kong 4648dc4c0fb0SBarry Smith Level: intermediate 4649dc4c0fb0SBarry Smith 4650f6dfbefdSBarry Smith Note: 4651c4421ceaSFande Kong Several different converged reason view routines may be set by calling 4652f6dfbefdSBarry Smith `SNESConvergedReasonViewSet()` multiple times; all will be called in the 4653c4421ceaSFande Kong order in which they were set. 4654c4421ceaSFande Kong 465549abdd8aSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`, `SNESConvergedReasonViewCancel()`, 465649abdd8aSBarry Smith `PetscCtxDestroyFn` 4657c4421ceaSFande Kong @*/ 465849abdd8aSBarry Smith PetscErrorCode SNESConvergedReasonViewSet(SNES snes, PetscErrorCode (*f)(SNES snes, void *vctx), void *vctx, PetscCtxDestroyFn *reasonviewdestroy) 4659d71ae5a4SJacob Faibussowitsch { 4660c4421ceaSFande Kong PetscInt i; 4661c4421ceaSFande Kong PetscBool identical; 4662c4421ceaSFande Kong 4663c4421ceaSFande Kong PetscFunctionBegin; 4664c4421ceaSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4665c4421ceaSFande Kong for (i = 0; i < snes->numberreasonviews; i++) { 46669566063dSJacob Faibussowitsch PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))f, vctx, reasonviewdestroy, (PetscErrorCode (*)(void))snes->reasonview[i], snes->reasonviewcontext[i], snes->reasonviewdestroy[i], &identical)); 46673ba16761SJacob Faibussowitsch if (identical) PetscFunctionReturn(PETSC_SUCCESS); 4668c4421ceaSFande Kong } 46695f80ce2aSJacob Faibussowitsch PetscCheck(snes->numberreasonviews < MAXSNESREASONVIEWS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many SNES reasonview set"); 4670c4421ceaSFande Kong snes->reasonview[snes->numberreasonviews] = f; 4671c4421ceaSFande Kong snes->reasonviewdestroy[snes->numberreasonviews] = reasonviewdestroy; 4672835f2295SStefano Zampini snes->reasonviewcontext[snes->numberreasonviews++] = vctx; 46733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4674c4421ceaSFande Kong } 4675c4421ceaSFande Kong 467691f3e32bSBarry Smith /*@ 4677420bcc1bSBarry Smith SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a `SNESConvergedReason` is to be viewed at the end of `SNESSolve()` 46780b4b7b1cSBarry Smith All the user-provided viewer routines set with `SNESConvergedReasonViewSet()` will be called, if they exist. 46792a359c20SBarry Smith 4680c3339decSBarry Smith Collective 46812a359c20SBarry Smith 46822fe279fdSBarry Smith Input Parameter: 4683f6dfbefdSBarry Smith . snes - the `SNES` object 46842a359c20SBarry Smith 4685f6dfbefdSBarry Smith Level: advanced 46862a359c20SBarry Smith 46871cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESConvergedReasonViewSet()`, `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, 4688f6dfbefdSBarry Smith `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()` 46892a359c20SBarry Smith @*/ 4690d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes) 4691d71ae5a4SJacob Faibussowitsch { 46922a359c20SBarry Smith static PetscBool incall = PETSC_FALSE; 46932a359c20SBarry Smith 46942a359c20SBarry Smith PetscFunctionBegin; 46953ba16761SJacob Faibussowitsch if (incall) PetscFunctionReturn(PETSC_SUCCESS); 46962a359c20SBarry Smith incall = PETSC_TRUE; 4697c4421ceaSFande Kong 4698c4421ceaSFande Kong /* All user-provided viewers are called first, if they exist. */ 469936d43d94SBarry Smith for (PetscInt i = 0; i < snes->numberreasonviews; i++) PetscCall((*snes->reasonview[i])(snes, snes->reasonviewcontext[i])); 4700c4421ceaSFande Kong 4701c4421ceaSFande Kong /* Call PETSc default routine if users ask for it */ 470236d43d94SBarry Smith if (snes->convergedreasonviewer) { 470336d43d94SBarry Smith PetscCall(PetscViewerPushFormat(snes->convergedreasonviewer, snes->convergedreasonformat)); 470436d43d94SBarry Smith PetscCall(SNESConvergedReasonView(snes, snes->convergedreasonviewer)); 470536d43d94SBarry Smith PetscCall(PetscViewerPopFormat(snes->convergedreasonviewer)); 47062a359c20SBarry Smith } 47072a359c20SBarry Smith incall = PETSC_FALSE; 47083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 47092a359c20SBarry Smith } 47102a359c20SBarry Smith 4711487a658cSBarry Smith /*@ 47120b4b7b1cSBarry Smith SNESSolve - Solves a nonlinear system $F(x) = b $ associated with a `SNES` object 47139b94acceSBarry Smith 4714c3339decSBarry Smith Collective 4715c7afd0dbSLois Curfman McInnes 4716b2002411SLois Curfman McInnes Input Parameters: 4717f6dfbefdSBarry Smith + snes - the `SNES` context 47180b4b7b1cSBarry Smith . b - the constant part of the equation $F(x) = b$, or `NULL` to use zero. 471985385478SLisandro Dalcin - x - the solution vector. 47209b94acceSBarry Smith 4721dc4c0fb0SBarry Smith Level: beginner 4722dc4c0fb0SBarry Smith 4723f6dfbefdSBarry Smith Note: 4724420bcc1bSBarry Smith The user should initialize the vector, `x`, with the initial guess 4725a9b45538SStefano Zampini for the nonlinear solve prior to calling `SNESSolve()` . 47268ddd3da0SLois Curfman McInnes 47271cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESSetFunction()`, `SNESSetJacobian()`, `SNESSetGridSequence()`, `SNESGetSolution()`, 4728db781477SPatrick Sanan `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRGetPreCheck()`, `SNESNewtonTRSetPostCheck()`, `SNESNewtonTRGetPostCheck()`, 4729a9b45538SStefano Zampini `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()` 47309b94acceSBarry Smith @*/ 4731d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSolve(SNES snes, Vec b, Vec x) 4732d71ae5a4SJacob Faibussowitsch { 4733ace3abfcSBarry Smith PetscBool flg; 4734efd51863SBarry Smith PetscInt grid; 47350298fd71SBarry Smith Vec xcreated = NULL; 4736caa4e7f2SJed Brown DM dm; 4737052efed2SBarry Smith 47383a40ed3dSBarry Smith PetscFunctionBegin; 47390700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4740a69afd8bSBarry Smith if (x) PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4741a69afd8bSBarry Smith if (x) PetscCheckSameComm(snes, 1, x, 3); 47420700a824SBarry Smith if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 474385385478SLisandro Dalcin if (b) PetscCheckSameComm(snes, 1, b, 2); 474485385478SLisandro Dalcin 474534b4d3a8SMatthew G. Knepley /* High level operations using the nonlinear solver */ 474606fc46c8SMatthew G. Knepley { 474706fc46c8SMatthew G. Knepley PetscViewer viewer; 474806fc46c8SMatthew G. Knepley PetscViewerFormat format; 47497c88af5aSMatthew G. Knepley PetscInt num; 475006fc46c8SMatthew G. Knepley PetscBool flg; 475106fc46c8SMatthew G. Knepley static PetscBool incall = PETSC_FALSE; 475206fc46c8SMatthew G. Knepley 475306fc46c8SMatthew G. Knepley if (!incall) { 475434b4d3a8SMatthew G. Knepley /* Estimate the convergence rate of the discretization */ 4755648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg)); 475606fc46c8SMatthew G. Knepley if (flg) { 475706fc46c8SMatthew G. Knepley PetscConvEst conv; 475846079b62SMatthew G. Knepley DM dm; 475946079b62SMatthew G. Knepley PetscReal *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */ 476046079b62SMatthew G. Knepley PetscInt Nf; 476106fc46c8SMatthew G. Knepley 476206fc46c8SMatthew G. Knepley incall = PETSC_TRUE; 47639566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 47649566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 47659566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(Nf, &alpha)); 47669566063dSJacob Faibussowitsch PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)snes), &conv)); 47679566063dSJacob Faibussowitsch PetscCall(PetscConvEstSetSolver(conv, (PetscObject)snes)); 47689566063dSJacob Faibussowitsch PetscCall(PetscConvEstSetFromOptions(conv)); 47699566063dSJacob Faibussowitsch PetscCall(PetscConvEstSetUp(conv)); 47709566063dSJacob Faibussowitsch PetscCall(PetscConvEstGetConvRate(conv, alpha)); 47719566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(viewer, format)); 47729566063dSJacob Faibussowitsch PetscCall(PetscConvEstRateView(conv, alpha, viewer)); 47739566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer)); 4774648c30bcSBarry Smith PetscCall(PetscViewerDestroy(&viewer)); 47759566063dSJacob Faibussowitsch PetscCall(PetscConvEstDestroy(&conv)); 47769566063dSJacob Faibussowitsch PetscCall(PetscFree(alpha)); 477706fc46c8SMatthew G. Knepley incall = PETSC_FALSE; 477806fc46c8SMatthew G. Knepley } 477934b4d3a8SMatthew G. Knepley /* Adaptively refine the initial grid */ 4780b2588ea6SMatthew G. Knepley num = 1; 47819566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_initial", &num, &flg)); 478234b4d3a8SMatthew G. Knepley if (flg) { 478334b4d3a8SMatthew G. Knepley DMAdaptor adaptor; 478434b4d3a8SMatthew G. Knepley 478534b4d3a8SMatthew G. Knepley incall = PETSC_TRUE; 47869566063dSJacob Faibussowitsch PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor)); 47879566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSolver(adaptor, snes)); 47889566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSequenceLength(adaptor, num)); 47899566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetFromOptions(adaptor)); 47909566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetUp(adaptor)); 47919566063dSJacob Faibussowitsch PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x)); 47929566063dSJacob Faibussowitsch PetscCall(DMAdaptorDestroy(&adaptor)); 479334b4d3a8SMatthew G. Knepley incall = PETSC_FALSE; 479434b4d3a8SMatthew G. Knepley } 47957c88af5aSMatthew G. Knepley /* Use grid sequencing to adapt */ 47967c88af5aSMatthew G. Knepley num = 0; 47979566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_sequence", &num, NULL)); 47987c88af5aSMatthew G. Knepley if (num) { 47997c88af5aSMatthew G. Knepley DMAdaptor adaptor; 4800e03fd340SMatthew G. Knepley const char *prefix; 48017c88af5aSMatthew G. Knepley 48027c88af5aSMatthew G. Knepley incall = PETSC_TRUE; 48039566063dSJacob Faibussowitsch PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor)); 4804e03fd340SMatthew G. Knepley PetscCall(SNESGetOptionsPrefix(snes, &prefix)); 4805e03fd340SMatthew G. Knepley PetscCall(DMAdaptorSetOptionsPrefix(adaptor, prefix)); 48069566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSolver(adaptor, snes)); 48079566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSequenceLength(adaptor, num)); 48089566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetFromOptions(adaptor)); 48099566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetUp(adaptor)); 4810e5148a0bSMatthew G. Knepley PetscCall(PetscObjectViewFromOptions((PetscObject)adaptor, NULL, "-snes_adapt_view")); 48119566063dSJacob Faibussowitsch PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x)); 48129566063dSJacob Faibussowitsch PetscCall(DMAdaptorDestroy(&adaptor)); 48137c88af5aSMatthew G. Knepley incall = PETSC_FALSE; 48147c88af5aSMatthew G. Knepley } 481506fc46c8SMatthew G. Knepley } 481606fc46c8SMatthew G. Knepley } 4817ad540459SPierre Jolivet if (!x) x = snes->vec_sol; 4818caa4e7f2SJed Brown if (!x) { 48199566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 48209566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dm, &xcreated)); 4821a69afd8bSBarry Smith x = xcreated; 4822a69afd8bSBarry Smith } 48239566063dSJacob Faibussowitsch PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view_pre")); 4824f05ece33SBarry Smith 48259566063dSJacob Faibussowitsch for (grid = 0; grid < snes->gridsequence; grid++) PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)))); 4826efd51863SBarry Smith for (grid = 0; grid < snes->gridsequence + 1; grid++) { 482785385478SLisandro Dalcin /* set solution vector */ 48289566063dSJacob Faibussowitsch if (!grid) PetscCall(PetscObjectReference((PetscObject)x)); 48299566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol)); 483085385478SLisandro Dalcin snes->vec_sol = x; 48319566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 4832caa4e7f2SJed Brown 4833caa4e7f2SJed Brown /* set affine vector if provided */ 48349566063dSJacob Faibussowitsch if (b) PetscCall(PetscObjectReference((PetscObject)b)); 48359566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_rhs)); 483685385478SLisandro Dalcin snes->vec_rhs = b; 483785385478SLisandro Dalcin 48385f80ce2aSJacob 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"); 48395f80ce2aSJacob Faibussowitsch PetscCheck(snes->vec_func != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be function vector"); 4840dd8e379bSPierre Jolivet PetscCheck(snes->vec_rhs != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be right-hand side vector"); 4841aa624791SPierre Jolivet if (!snes->vec_sol_update /* && snes->vec_sol */) PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_sol_update)); 48429566063dSJacob Faibussowitsch PetscCall(DMShellSetGlobalVector(dm, snes->vec_sol)); 48439566063dSJacob Faibussowitsch PetscCall(SNESSetUp(snes)); 48443f149594SLisandro Dalcin 48457eee914bSBarry Smith if (!grid) { 48469927e4dfSBarry Smith if (snes->ops->computeinitialguess) PetscCallBack("SNES callback compute initial guess", (*snes->ops->computeinitialguess)(snes, snes->vec_sol, snes->initialguessP)); 4847dd568438SSatish Balay } 4848d25893d9SBarry Smith 4849abc0a331SBarry Smith if (snes->conv_hist_reset) snes->conv_hist_len = 0; 485012b1dd1aSStefano Zampini PetscCall(SNESResetCounters(snes)); 48512d157150SStefano Zampini snes->reason = SNES_CONVERGED_ITERATING; 48529566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_Solve, snes, 0, 0, 0)); 4853dbbe0bcdSBarry Smith PetscUseTypeMethod(snes, solve); 48549566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_Solve, snes, 0, 0, 0)); 48552d157150SStefano Zampini PetscCheck(snes->reason, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error, solver %s returned without setting converged reason", ((PetscObject)snes)->type_name); 4856422a814eSBarry Smith snes->domainerror = PETSC_FALSE; /* clear the flag if it has been set */ 48573f149594SLisandro Dalcin 485837ec4e1aSPeter Brune if (snes->lagjac_persist) snes->jac_iter += snes->iter; 485937ec4e1aSPeter Brune if (snes->lagpre_persist) snes->pre_iter += snes->iter; 486037ec4e1aSPeter Brune 4861648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_test_local_min", NULL, NULL, &flg)); 48629566063dSJacob Faibussowitsch if (flg && !PetscPreLoadingOn) PetscCall(SNESTestLocalMin(snes)); 4863c4421ceaSFande Kong /* Call converged reason views. This may involve user-provided viewers as well */ 48649566063dSJacob Faibussowitsch PetscCall(SNESConvergedReasonViewFromOptions(snes)); 48655968eb51SBarry Smith 48665f80ce2aSJacob Faibussowitsch if (snes->errorifnotconverged) PetscCheck(snes->reason >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_NOT_CONVERGED, "SNESSolve has not converged"); 48679c8e83a9SBarry Smith if (snes->reason < 0) break; 4868efd51863SBarry Smith if (grid < snes->gridsequence) { 4869efd51863SBarry Smith DM fine; 4870efd51863SBarry Smith Vec xnew; 4871efd51863SBarry Smith Mat interp; 4872efd51863SBarry Smith 48739566063dSJacob Faibussowitsch PetscCall(DMRefine(snes->dm, PetscObjectComm((PetscObject)snes), &fine)); 48745f80ce2aSJacob Faibussowitsch PetscCheck(fine, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_INCOMP, "DMRefine() did not perform any refinement, cannot continue grid sequencing"); 48752eace19aSMatthew G. Knepley PetscCall(DMGetCoordinatesLocalSetUp(fine)); 48769566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(snes->dm, fine, &interp, NULL)); 48779566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(fine, &xnew)); 48789566063dSJacob Faibussowitsch PetscCall(MatInterpolate(interp, x, xnew)); 48799566063dSJacob Faibussowitsch PetscCall(DMInterpolate(snes->dm, interp, fine)); 48809566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interp)); 4881efd51863SBarry Smith x = xnew; 4882efd51863SBarry Smith 48839566063dSJacob Faibussowitsch PetscCall(SNESReset(snes)); 48849566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes, fine)); 48859566063dSJacob Faibussowitsch PetscCall(SNESResetFromOptions(snes)); 48869566063dSJacob Faibussowitsch PetscCall(DMDestroy(&fine)); 48879566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)))); 4888efd51863SBarry Smith } 4889efd51863SBarry Smith } 48909566063dSJacob Faibussowitsch PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view")); 48919566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(snes->vec_sol, (PetscObject)snes, "-snes_view_solution")); 48929566063dSJacob Faibussowitsch PetscCall(DMMonitor(snes->dm)); 48939566063dSJacob Faibussowitsch PetscCall(SNESMonitorPauseFinal_Internal(snes)); 48943f7e2da0SPeter Brune 48959566063dSJacob Faibussowitsch PetscCall(VecDestroy(&xcreated)); 48969566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsBlock((PetscObject)snes)); 48973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 48989b94acceSBarry Smith } 48999b94acceSBarry Smith 49009b94acceSBarry Smith /* --------- Internal routines for SNES Package --------- */ 49019b94acceSBarry Smith 4902cc4c1da9SBarry Smith /*@ 49030b4b7b1cSBarry Smith SNESSetType - Sets the algorithm/method to be used to solve the nonlinear system with the given `SNES` 49049b94acceSBarry Smith 4905c3339decSBarry Smith Collective 4906fee21e36SBarry Smith 4907c7afd0dbSLois Curfman McInnes Input Parameters: 4908f6dfbefdSBarry Smith + snes - the `SNES` context 4909454a90a3SBarry Smith - type - a known method 4910c7afd0dbSLois Curfman McInnes 4911c7afd0dbSLois Curfman McInnes Options Database Key: 4912454a90a3SBarry Smith . -snes_type <type> - Sets the method; use -help for a list 491304d7464bSBarry Smith of available methods (for instance, newtonls or newtontr) 4914ae12b187SLois Curfman McInnes 4915dc4c0fb0SBarry Smith Level: intermediate 4916dc4c0fb0SBarry Smith 49179b94acceSBarry Smith Notes: 49180b4b7b1cSBarry Smith See `SNESType` for available methods (for instance) 4919f6dfbefdSBarry Smith + `SNESNEWTONLS` - Newton's method with line search 4920c7afd0dbSLois Curfman McInnes (systems of nonlinear equations) 49214a221d59SStefano Zampini - `SNESNEWTONTR` - Newton's method with trust region 4922c7afd0dbSLois Curfman McInnes (systems of nonlinear equations) 49239b94acceSBarry Smith 4924f6dfbefdSBarry Smith Normally, it is best to use the `SNESSetFromOptions()` command and then 4925f6dfbefdSBarry Smith set the `SNES` solver type from the options database rather than by using 4926ae12b187SLois Curfman McInnes this routine. Using the options database provides the user with 4927ae12b187SLois Curfman McInnes maximum flexibility in evaluating the many nonlinear solvers. 4928f6dfbefdSBarry Smith The `SNESSetType()` routine is provided for those situations where it 4929ae12b187SLois Curfman McInnes is necessary to set the nonlinear solver independently of the command 4930ae12b187SLois Curfman McInnes line or options database. This might be the case, for example, when 4931ae12b187SLois Curfman McInnes the choice of solver changes during the execution of the program, 4932ae12b187SLois Curfman McInnes and the user's application is taking responsibility for choosing the 4933b0a32e0cSBarry Smith appropriate method. 493436851e7fSLois Curfman McInnes 4935420bcc1bSBarry Smith Developer Note: 4936f6dfbefdSBarry Smith `SNESRegister()` adds a constructor for a new `SNESType` to `SNESList`, `SNESSetType()` locates 4937f6dfbefdSBarry Smith the constructor in that list and calls it to create the specific object. 49388f6c3df8SBarry Smith 49391cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESType`, `SNESCreate()`, `SNESDestroy()`, `SNESGetType()`, `SNESSetFromOptions()` 49409b94acceSBarry Smith @*/ 4941d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetType(SNES snes, SNESType type) 4942d71ae5a4SJacob Faibussowitsch { 4943ace3abfcSBarry Smith PetscBool match; 49445f80ce2aSJacob Faibussowitsch PetscErrorCode (*r)(SNES); 49453a40ed3dSBarry Smith 49463a40ed3dSBarry Smith PetscFunctionBegin; 49470700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 49484f572ea9SToby Isaac PetscAssertPointer(type, 2); 494982bf6240SBarry Smith 49509566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes, type, &match)); 49513ba16761SJacob Faibussowitsch if (match) PetscFunctionReturn(PETSC_SUCCESS); 495292ff6ae8SBarry Smith 49539566063dSJacob Faibussowitsch PetscCall(PetscFunctionListFind(SNESList, type, &r)); 49546adde796SStefano Zampini PetscCheck(r, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested SNES type %s", type); 495575396ef9SLisandro Dalcin /* Destroy the previous private SNES context */ 4956dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, destroy); 495743547594SStefano Zampini /* Reinitialize type-specific function pointers in SNESOps structure */ 495843547594SStefano Zampini snes->ops->reset = NULL; 49599e5d0892SLisandro Dalcin snes->ops->setup = NULL; 49609e5d0892SLisandro Dalcin snes->ops->solve = NULL; 49619e5d0892SLisandro Dalcin snes->ops->view = NULL; 49629e5d0892SLisandro Dalcin snes->ops->setfromoptions = NULL; 49639e5d0892SLisandro Dalcin snes->ops->destroy = NULL; 49647fe760d5SStefano Zampini 49657fe760d5SStefano Zampini /* It may happen the user has customized the line search before calling SNESSetType */ 49669566063dSJacob Faibussowitsch if (((PetscObject)snes)->type_name) PetscCall(SNESLineSearchDestroy(&snes->linesearch)); 49677fe760d5SStefano Zampini 496875396ef9SLisandro Dalcin /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */ 496975396ef9SLisandro Dalcin snes->setupcalled = PETSC_FALSE; 4970f5af7f23SKarl Rupp 49719566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)snes, type)); 49729566063dSJacob Faibussowitsch PetscCall((*r)(snes)); 49733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49749b94acceSBarry Smith } 49759b94acceSBarry Smith 4976cc4c1da9SBarry Smith /*@ 4977f6dfbefdSBarry Smith SNESGetType - Gets the `SNES` method type and name (as a string). 49789b94acceSBarry Smith 4979c7afd0dbSLois Curfman McInnes Not Collective 4980c7afd0dbSLois Curfman McInnes 49819b94acceSBarry Smith Input Parameter: 49824b0e389bSBarry Smith . snes - nonlinear solver context 49839b94acceSBarry Smith 49849b94acceSBarry Smith Output Parameter: 4985f6dfbefdSBarry Smith . type - `SNES` method (a character string) 49869b94acceSBarry Smith 498736851e7fSLois Curfman McInnes Level: intermediate 498836851e7fSLois Curfman McInnes 49891cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetType()`, `SNESType`, `SNESSetFromOptions()`, `SNES` 49909b94acceSBarry Smith @*/ 4991d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetType(SNES snes, SNESType *type) 4992d71ae5a4SJacob Faibussowitsch { 49933a40ed3dSBarry Smith PetscFunctionBegin; 49940700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 49954f572ea9SToby Isaac PetscAssertPointer(type, 2); 49967adad957SLisandro Dalcin *type = ((PetscObject)snes)->type_name; 49973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49989b94acceSBarry Smith } 49999b94acceSBarry Smith 50003cd8a7caSMatthew G. Knepley /*@ 5001f6dfbefdSBarry Smith SNESSetSolution - Sets the solution vector for use by the `SNES` routines. 50023cd8a7caSMatthew G. Knepley 5003c3339decSBarry Smith Logically Collective 50043cd8a7caSMatthew G. Knepley 50053cd8a7caSMatthew G. Knepley Input Parameters: 5006f6dfbefdSBarry Smith + snes - the `SNES` context obtained from `SNESCreate()` 50073cd8a7caSMatthew G. Knepley - u - the solution vector 50083cd8a7caSMatthew G. Knepley 50093cd8a7caSMatthew G. Knepley Level: beginner 50103cd8a7caSMatthew G. Knepley 50111cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetSolution()`, `Vec` 50123cd8a7caSMatthew G. Knepley @*/ 5013d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetSolution(SNES snes, Vec u) 5014d71ae5a4SJacob Faibussowitsch { 50153cd8a7caSMatthew G. Knepley DM dm; 50163cd8a7caSMatthew G. Knepley 50173cd8a7caSMatthew G. Knepley PetscFunctionBegin; 50183cd8a7caSMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 50193cd8a7caSMatthew G. Knepley PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 50209566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)u)); 50219566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol)); 50223cd8a7caSMatthew G. Knepley 50233cd8a7caSMatthew G. Knepley snes->vec_sol = u; 50243cd8a7caSMatthew G. Knepley 50259566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 50269566063dSJacob Faibussowitsch PetscCall(DMShellSetGlobalVector(dm, u)); 50273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50283cd8a7caSMatthew G. Knepley } 50293cd8a7caSMatthew G. Knepley 503052baeb72SSatish Balay /*@ 50319b94acceSBarry Smith SNESGetSolution - Returns the vector where the approximate solution is 5032f6dfbefdSBarry Smith stored. This is the fine grid solution when using `SNESSetGridSequence()`. 50339b94acceSBarry Smith 5034420bcc1bSBarry Smith Not Collective, but `x` is parallel if `snes` is parallel 5035c7afd0dbSLois Curfman McInnes 50369b94acceSBarry Smith Input Parameter: 5037f6dfbefdSBarry Smith . snes - the `SNES` context 50389b94acceSBarry Smith 50399b94acceSBarry Smith Output Parameter: 50409b94acceSBarry Smith . x - the solution 50419b94acceSBarry Smith 504270e92668SMatthew Knepley Level: intermediate 504336851e7fSLois Curfman McInnes 50441cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetSolution()`, `SNESSolve()`, `SNES`, `SNESGetSolutionUpdate()`, `SNESGetFunction()` 50459b94acceSBarry Smith @*/ 5046d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolution(SNES snes, Vec *x) 5047d71ae5a4SJacob Faibussowitsch { 50483a40ed3dSBarry Smith PetscFunctionBegin; 50490700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 50504f572ea9SToby Isaac PetscAssertPointer(x, 2); 505185385478SLisandro Dalcin *x = snes->vec_sol; 50523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 505370e92668SMatthew Knepley } 505470e92668SMatthew Knepley 505552baeb72SSatish Balay /*@ 50569b94acceSBarry Smith SNESGetSolutionUpdate - Returns the vector where the solution update is 50579b94acceSBarry Smith stored. 50589b94acceSBarry Smith 5059420bcc1bSBarry Smith Not Collective, but `x` is parallel if `snes` is parallel 5060c7afd0dbSLois Curfman McInnes 50619b94acceSBarry Smith Input Parameter: 5062f6dfbefdSBarry Smith . snes - the `SNES` context 50639b94acceSBarry Smith 50649b94acceSBarry Smith Output Parameter: 50659b94acceSBarry Smith . x - the solution update 50669b94acceSBarry Smith 506736851e7fSLois Curfman McInnes Level: advanced 506836851e7fSLois Curfman McInnes 50691cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()` 50709b94acceSBarry Smith @*/ 5071d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionUpdate(SNES snes, Vec *x) 5072d71ae5a4SJacob Faibussowitsch { 50733a40ed3dSBarry Smith PetscFunctionBegin; 50740700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 50754f572ea9SToby Isaac PetscAssertPointer(x, 2); 507685385478SLisandro Dalcin *x = snes->vec_sol_update; 50773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50789b94acceSBarry Smith } 50799b94acceSBarry Smith 50809b94acceSBarry Smith /*@C 5081f6dfbefdSBarry Smith SNESGetFunction - Returns the function that defines the nonlinear system set with `SNESSetFunction()` 50829b94acceSBarry Smith 5083420bcc1bSBarry Smith Not Collective, but `r` is parallel if `snes` is parallel. Collective if `r` is requested, but has not been created yet. 5084c7afd0dbSLois Curfman McInnes 50859b94acceSBarry Smith Input Parameter: 5086f6dfbefdSBarry Smith . snes - the `SNES` context 50879b94acceSBarry Smith 5088d8d19677SJose E. Roman Output Parameters: 5089dc4c0fb0SBarry Smith + r - the vector that is used to store residuals (or `NULL` if you don't want it) 50908434afd1SBarry Smith . f - the function (or `NULL` if you don't want it); for calling sequence see `SNESFunctionFn` 5091dc4c0fb0SBarry Smith - ctx - the function context (or `NULL` if you don't want it) 50929b94acceSBarry Smith 509336851e7fSLois Curfman McInnes Level: advanced 509436851e7fSLois Curfman McInnes 5095f6dfbefdSBarry Smith Note: 5096dc4c0fb0SBarry Smith The vector `r` DOES NOT, in general, contain the current value of the `SNES` nonlinear function 509704edfde5SBarry Smith 50988434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetSolution()`, `SNESFunctionFn` 50999b94acceSBarry Smith @*/ 51008434afd1SBarry Smith PetscErrorCode SNESGetFunction(SNES snes, Vec *r, SNESFunctionFn **f, void **ctx) 5101d71ae5a4SJacob Faibussowitsch { 51026cab3a1bSJed Brown DM dm; 5103a63bb30eSJed Brown 51043a40ed3dSBarry Smith PetscFunctionBegin; 51050700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5106a63bb30eSJed Brown if (r) { 5107a63bb30eSJed Brown if (!snes->vec_func) { 5108a63bb30eSJed Brown if (snes->vec_rhs) { 51099566063dSJacob Faibussowitsch PetscCall(VecDuplicate(snes->vec_rhs, &snes->vec_func)); 5110a63bb30eSJed Brown } else if (snes->vec_sol) { 51119566063dSJacob Faibussowitsch PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_func)); 5112a63bb30eSJed Brown } else if (snes->dm) { 51139566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(snes->dm, &snes->vec_func)); 5114a63bb30eSJed Brown } 5115a63bb30eSJed Brown } 5116a63bb30eSJed Brown *r = snes->vec_func; 5117a63bb30eSJed Brown } 51189566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 51199566063dSJacob Faibussowitsch PetscCall(DMSNESGetFunction(dm, f, ctx)); 51203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 51219b94acceSBarry Smith } 51229b94acceSBarry Smith 5123c79ef259SPeter Brune /*@C 512437fdd005SBarry Smith SNESGetNGS - Returns the function and context set with `SNESSetNGS()` 5125c79ef259SPeter Brune 5126c79ef259SPeter Brune Input Parameter: 5127f6dfbefdSBarry Smith . snes - the `SNES` context 5128c79ef259SPeter Brune 5129d8d19677SJose E. Roman Output Parameters: 51308434afd1SBarry Smith + f - the function (or `NULL`) see `SNESNGSFn` for calling sequence 5131dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`) 5132c79ef259SPeter Brune 5133c79ef259SPeter Brune Level: advanced 5134c79ef259SPeter Brune 51358434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetNGS()`, `SNESGetFunction()`, `SNESNGSFn` 5136c79ef259SPeter Brune @*/ 51378434afd1SBarry Smith PetscErrorCode SNESGetNGS(SNES snes, SNESNGSFn **f, void **ctx) 5138d71ae5a4SJacob Faibussowitsch { 51396cab3a1bSJed Brown DM dm; 51406cab3a1bSJed Brown 5141646217ecSPeter Brune PetscFunctionBegin; 5142646217ecSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 51439566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 51449566063dSJacob Faibussowitsch PetscCall(DMSNESGetNGS(dm, f, ctx)); 51453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5146646217ecSPeter Brune } 5147646217ecSPeter Brune 5148cc4c1da9SBarry Smith /*@ 51493c7409f5SSatish Balay SNESSetOptionsPrefix - Sets the prefix used for searching for all 5150f6dfbefdSBarry Smith `SNES` options in the database. 51513c7409f5SSatish Balay 5152c3339decSBarry Smith Logically Collective 5153fee21e36SBarry Smith 5154d8d19677SJose E. Roman Input Parameters: 5155f6dfbefdSBarry Smith + snes - the `SNES` context 5156c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names 5157c7afd0dbSLois Curfman McInnes 5158dc4c0fb0SBarry Smith Level: advanced 5159dc4c0fb0SBarry Smith 5160f6dfbefdSBarry Smith Note: 5161a83b1b31SSatish Balay A hyphen (-) must NOT be given at the beginning of the prefix name. 5162c7afd0dbSLois Curfman McInnes The first character of all runtime options is AUTOMATICALLY the hyphen. 5163d850072dSLois Curfman McInnes 51641cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESAppendOptionsPrefix()` 51653c7409f5SSatish Balay @*/ 5166d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetOptionsPrefix(SNES snes, const char prefix[]) 5167d71ae5a4SJacob Faibussowitsch { 51683a40ed3dSBarry Smith PetscFunctionBegin; 51690700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 51709566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes, prefix)); 51719566063dSJacob Faibussowitsch if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 517235f5d045SPeter Brune if (snes->linesearch) { 51739566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 51749566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch, prefix)); 517535f5d045SPeter Brune } 51769566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(snes->ksp, prefix)); 51773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 51783c7409f5SSatish Balay } 51793c7409f5SSatish Balay 5180cc4c1da9SBarry Smith /*@ 5181f525115eSLois Curfman McInnes SNESAppendOptionsPrefix - Appends to the prefix used for searching for all 5182f6dfbefdSBarry Smith `SNES` options in the database. 51833c7409f5SSatish Balay 5184c3339decSBarry Smith Logically Collective 5185fee21e36SBarry Smith 5186c7afd0dbSLois Curfman McInnes Input Parameters: 5187f6dfbefdSBarry Smith + snes - the `SNES` context 5188c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names 5189c7afd0dbSLois Curfman McInnes 5190dc4c0fb0SBarry Smith Level: advanced 5191dc4c0fb0SBarry Smith 5192f6dfbefdSBarry Smith Note: 5193a83b1b31SSatish Balay A hyphen (-) must NOT be given at the beginning of the prefix name. 5194c7afd0dbSLois Curfman McInnes The first character of all runtime options is AUTOMATICALLY the hyphen. 5195d850072dSLois Curfman McInnes 51961cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetOptionsPrefix()`, `SNESSetOptionsPrefix()` 51973c7409f5SSatish Balay @*/ 5198d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESAppendOptionsPrefix(SNES snes, const char prefix[]) 5199d71ae5a4SJacob Faibussowitsch { 52003a40ed3dSBarry Smith PetscFunctionBegin; 52010700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 52029566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes, prefix)); 52039566063dSJacob Faibussowitsch if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 520435f5d045SPeter Brune if (snes->linesearch) { 52059566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 52069566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch, prefix)); 520735f5d045SPeter Brune } 52089566063dSJacob Faibussowitsch PetscCall(KSPAppendOptionsPrefix(snes->ksp, prefix)); 52093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 52103c7409f5SSatish Balay } 52113c7409f5SSatish Balay 5212cc4c1da9SBarry Smith /*@ 5213f6dfbefdSBarry Smith SNESGetOptionsPrefix - Gets the prefix used for searching for all 5214f6dfbefdSBarry Smith `SNES` options in the database. 52153c7409f5SSatish Balay 5216c7afd0dbSLois Curfman McInnes Not Collective 5217c7afd0dbSLois Curfman McInnes 52183c7409f5SSatish Balay Input Parameter: 5219f6dfbefdSBarry Smith . snes - the `SNES` context 52203c7409f5SSatish Balay 52213c7409f5SSatish Balay Output Parameter: 52223c7409f5SSatish Balay . prefix - pointer to the prefix string used 52233c7409f5SSatish Balay 522436851e7fSLois Curfman McInnes Level: advanced 522536851e7fSLois Curfman McInnes 52261cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetOptionsPrefix()`, `SNESAppendOptionsPrefix()` 52273c7409f5SSatish Balay @*/ 5228d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetOptionsPrefix(SNES snes, const char *prefix[]) 5229d71ae5a4SJacob Faibussowitsch { 52303a40ed3dSBarry Smith PetscFunctionBegin; 52310700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 52329566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)snes, prefix)); 52333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 52343c7409f5SSatish Balay } 52353c7409f5SSatish Balay 52363cea93caSBarry Smith /*@C 52371c84c290SBarry Smith SNESRegister - Adds a method to the nonlinear solver package. 52381c84c290SBarry Smith 523920f4b53cSBarry Smith Not Collective 52401c84c290SBarry Smith 52411c84c290SBarry Smith Input Parameters: 524220f4b53cSBarry Smith + sname - name of a new user-defined solver 524320f4b53cSBarry Smith - function - routine to create method context 52441c84c290SBarry Smith 5245dc4c0fb0SBarry Smith Level: advanced 5246dc4c0fb0SBarry Smith 5247f6dfbefdSBarry Smith Note: 5248f6dfbefdSBarry Smith `SNESRegister()` may be called multiple times to add several user-defined solvers. 52491c84c290SBarry Smith 5250e4094ef1SJacob Faibussowitsch Example Usage: 52511c84c290SBarry Smith .vb 5252bdf89e91SBarry Smith SNESRegister("my_solver", MySolverCreate); 52531c84c290SBarry Smith .ve 52541c84c290SBarry Smith 52551c84c290SBarry Smith Then, your solver can be chosen with the procedural interface via 5256b44f4de4SBarry Smith .vb 5257b44f4de4SBarry Smith SNESSetType(snes, "my_solver") 5258b44f4de4SBarry Smith .ve 52591c84c290SBarry Smith or at runtime via the option 5260b44f4de4SBarry Smith .vb 5261b44f4de4SBarry Smith -snes_type my_solver 5262b44f4de4SBarry Smith .ve 52631c84c290SBarry Smith 52641cc06b55SBarry Smith .seealso: [](ch_snes), `SNESRegisterAll()`, `SNESRegisterDestroy()` 52653cea93caSBarry Smith @*/ 5266d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESRegister(const char sname[], PetscErrorCode (*function)(SNES)) 5267d71ae5a4SJacob Faibussowitsch { 5268b2002411SLois Curfman McInnes PetscFunctionBegin; 52699566063dSJacob Faibussowitsch PetscCall(SNESInitializePackage()); 52709566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&SNESList, sname, function)); 52713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5272b2002411SLois Curfman McInnes } 5273da9b6338SBarry Smith 5274d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestLocalMin(SNES snes) 5275d71ae5a4SJacob Faibussowitsch { 527677431f27SBarry Smith PetscInt N, i, j; 5277da9b6338SBarry Smith Vec u, uh, fh; 5278da9b6338SBarry Smith PetscScalar value; 5279da9b6338SBarry Smith PetscReal norm; 5280da9b6338SBarry Smith 5281da9b6338SBarry Smith PetscFunctionBegin; 52829566063dSJacob Faibussowitsch PetscCall(SNESGetSolution(snes, &u)); 52839566063dSJacob Faibussowitsch PetscCall(VecDuplicate(u, &uh)); 52849566063dSJacob Faibussowitsch PetscCall(VecDuplicate(u, &fh)); 5285da9b6338SBarry Smith 5286da9b6338SBarry Smith /* currently only works for sequential */ 52879566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Testing FormFunction() for local min\n")); 52889566063dSJacob Faibussowitsch PetscCall(VecGetSize(u, &N)); 5289da9b6338SBarry Smith for (i = 0; i < N; i++) { 52909566063dSJacob Faibussowitsch PetscCall(VecCopy(u, uh)); 529163a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "i = %" PetscInt_FMT "\n", i)); 5292da9b6338SBarry Smith for (j = -10; j < 11; j++) { 52938b49ba18SBarry Smith value = PetscSign(j) * PetscExpReal(PetscAbs(j) - 10.0); 52949566063dSJacob Faibussowitsch PetscCall(VecSetValue(uh, i, value, ADD_VALUES)); 52959566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, uh, fh)); 52969566063dSJacob Faibussowitsch PetscCall(VecNorm(fh, NORM_2, &norm)); 529763a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), " j norm %" PetscInt_FMT " %18.16e\n", j, (double)norm)); 5298da9b6338SBarry Smith value = -value; 52999566063dSJacob Faibussowitsch PetscCall(VecSetValue(uh, i, value, ADD_VALUES)); 5300da9b6338SBarry Smith } 5301da9b6338SBarry Smith } 53029566063dSJacob Faibussowitsch PetscCall(VecDestroy(&uh)); 53039566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fh)); 53043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5305da9b6338SBarry Smith } 530671f87433Sdalcinl 530771f87433Sdalcinl /*@ 5308f6dfbefdSBarry Smith SNESKSPSetUseEW - Sets `SNES` to the use Eisenstat-Walker method for 530971f87433Sdalcinl computing relative tolerance for linear solvers within an inexact 531071f87433Sdalcinl Newton method. 531171f87433Sdalcinl 5312c3339decSBarry Smith Logically Collective 531371f87433Sdalcinl 531471f87433Sdalcinl Input Parameters: 5315f6dfbefdSBarry Smith + snes - `SNES` context 5316f6dfbefdSBarry Smith - flag - `PETSC_TRUE` or `PETSC_FALSE` 531771f87433Sdalcinl 5318f6dfbefdSBarry Smith Options Database Keys: 531964ba62caSBarry Smith + -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence 532064ba62caSBarry Smith . -snes_ksp_ew_version ver - version of Eisenstat-Walker method 532164ba62caSBarry Smith . -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0 532264ba62caSBarry Smith . -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax 532364ba62caSBarry Smith . -snes_ksp_ew_gamma <gamma> - Sets gamma 532464ba62caSBarry Smith . -snes_ksp_ew_alpha <alpha> - Sets alpha 532564ba62caSBarry Smith . -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2 532664ba62caSBarry Smith - -snes_ksp_ew_threshold <threshold> - Sets threshold 532764ba62caSBarry Smith 5328dc4c0fb0SBarry Smith Level: advanced 5329dc4c0fb0SBarry Smith 5330f6dfbefdSBarry Smith Note: 5331f6dfbefdSBarry Smith The default is to use a constant relative tolerance for 533271f87433Sdalcinl the inner linear solvers. Alternatively, one can use the 53331d27aa22SBarry Smith Eisenstat-Walker method {cite}`ew96`, where the relative convergence tolerance 533471f87433Sdalcinl is reset at each Newton iteration according progress of the nonlinear 533571f87433Sdalcinl solver. 533671f87433Sdalcinl 53371cc06b55SBarry Smith .seealso: [](ch_snes), `KSP`, `SNES`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()` 533871f87433Sdalcinl @*/ 5339d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetUseEW(SNES snes, PetscBool flag) 5340d71ae5a4SJacob Faibussowitsch { 534171f87433Sdalcinl PetscFunctionBegin; 53420700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5343acfcf0e5SJed Brown PetscValidLogicalCollectiveBool(snes, flag, 2); 534471f87433Sdalcinl snes->ksp_ewconv = flag; 53453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 534671f87433Sdalcinl } 534771f87433Sdalcinl 534871f87433Sdalcinl /*@ 5349f6dfbefdSBarry Smith SNESKSPGetUseEW - Gets if `SNES` is using Eisenstat-Walker method 535071f87433Sdalcinl for computing relative tolerance for linear solvers within an 535171f87433Sdalcinl inexact Newton method. 535271f87433Sdalcinl 535371f87433Sdalcinl Not Collective 535471f87433Sdalcinl 535571f87433Sdalcinl Input Parameter: 5356f6dfbefdSBarry Smith . snes - `SNES` context 535771f87433Sdalcinl 535871f87433Sdalcinl Output Parameter: 5359f6dfbefdSBarry Smith . flag - `PETSC_TRUE` or `PETSC_FALSE` 536071f87433Sdalcinl 536171f87433Sdalcinl Level: advanced 536271f87433Sdalcinl 53631cc06b55SBarry Smith .seealso: [](ch_snes), `SNESKSPSetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()` 536471f87433Sdalcinl @*/ 5365d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag) 5366d71ae5a4SJacob Faibussowitsch { 536771f87433Sdalcinl PetscFunctionBegin; 53680700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 53694f572ea9SToby Isaac PetscAssertPointer(flag, 2); 537071f87433Sdalcinl *flag = snes->ksp_ewconv; 53713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 537271f87433Sdalcinl } 537371f87433Sdalcinl 537471f87433Sdalcinl /*@ 5375fa9f3622SBarry Smith SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker 537671f87433Sdalcinl convergence criteria for the linear solvers within an inexact 537771f87433Sdalcinl Newton method. 537871f87433Sdalcinl 5379c3339decSBarry Smith Logically Collective 538071f87433Sdalcinl 538171f87433Sdalcinl Input Parameters: 5382f6dfbefdSBarry Smith + snes - `SNES` context 53830f0abf79SStefano Zampini . version - version 1, 2 (default is 2), 3 or 4 538471f87433Sdalcinl . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 538571f87433Sdalcinl . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 538671f87433Sdalcinl . gamma - multiplicative factor for version 2 rtol computation 538771f87433Sdalcinl (0 <= gamma2 <= 1) 538871f87433Sdalcinl . alpha - power for version 2 rtol computation (1 < alpha <= 2) 538971f87433Sdalcinl . alpha2 - power for safeguard 539071f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1) 539171f87433Sdalcinl 5392dc4c0fb0SBarry Smith Level: advanced 5393dc4c0fb0SBarry Smith 5394f6dfbefdSBarry Smith Notes: 539571f87433Sdalcinl Version 3 was contributed by Luis Chacon, June 2006. 539671f87433Sdalcinl 539777e5a1f9SBarry Smith Use `PETSC_CURRENT` to retain the default for any of the parameters. 539871f87433Sdalcinl 53991cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()` 540071f87433Sdalcinl @*/ 5401d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetParametersEW(SNES snes, PetscInt version, PetscReal rtol_0, PetscReal rtol_max, PetscReal gamma, PetscReal alpha, PetscReal alpha2, PetscReal threshold) 5402d71ae5a4SJacob Faibussowitsch { 5403fa9f3622SBarry Smith SNESKSPEW *kctx; 54045fd66863SKarl Rupp 540571f87433Sdalcinl PetscFunctionBegin; 54060700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5407fa9f3622SBarry Smith kctx = (SNESKSPEW *)snes->kspconvctx; 54085f80ce2aSJacob Faibussowitsch PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing"); 5409c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, version, 2); 5410c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, rtol_0, 3); 5411c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, rtol_max, 4); 5412c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, gamma, 5); 5413c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, alpha, 6); 5414c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, alpha2, 7); 5415c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, threshold, 8); 541671f87433Sdalcinl 541777e5a1f9SBarry Smith if (version != PETSC_CURRENT) kctx->version = version; 541877e5a1f9SBarry Smith if (rtol_0 != (PetscReal)PETSC_CURRENT) kctx->rtol_0 = rtol_0; 541977e5a1f9SBarry Smith if (rtol_max != (PetscReal)PETSC_CURRENT) kctx->rtol_max = rtol_max; 542077e5a1f9SBarry Smith if (gamma != (PetscReal)PETSC_CURRENT) kctx->gamma = gamma; 542177e5a1f9SBarry Smith if (alpha != (PetscReal)PETSC_CURRENT) kctx->alpha = alpha; 542277e5a1f9SBarry Smith if (alpha2 != (PetscReal)PETSC_CURRENT) kctx->alpha2 = alpha2; 542377e5a1f9SBarry Smith if (threshold != (PetscReal)PETSC_CURRENT) kctx->threshold = threshold; 542471f87433Sdalcinl 54250f0abf79SStefano 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); 54260b121fc5SBarry 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); 54270b121fc5SBarry 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); 54280b121fc5SBarry 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); 54290b121fc5SBarry 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); 54300b121fc5SBarry 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); 54313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 543271f87433Sdalcinl } 543371f87433Sdalcinl 543471f87433Sdalcinl /*@ 5435fa9f3622SBarry Smith SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker 543671f87433Sdalcinl convergence criteria for the linear solvers within an inexact 543771f87433Sdalcinl Newton method. 543871f87433Sdalcinl 543971f87433Sdalcinl Not Collective 544071f87433Sdalcinl 544197bb3fdcSJose E. Roman Input Parameter: 5442f6dfbefdSBarry Smith . snes - `SNES` context 544371f87433Sdalcinl 544471f87433Sdalcinl Output Parameters: 54450f0abf79SStefano Zampini + version - version 1, 2 (default is 2), 3 or 4 544671f87433Sdalcinl . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 544771f87433Sdalcinl . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 5448bf388a1fSBarry Smith . gamma - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1) 544971f87433Sdalcinl . alpha - power for version 2 rtol computation (1 < alpha <= 2) 545071f87433Sdalcinl . alpha2 - power for safeguard 545171f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1) 545271f87433Sdalcinl 545371f87433Sdalcinl Level: advanced 545471f87433Sdalcinl 54551cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPSetParametersEW()` 545671f87433Sdalcinl @*/ 5457d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetParametersEW(SNES snes, PetscInt *version, PetscReal *rtol_0, PetscReal *rtol_max, PetscReal *gamma, PetscReal *alpha, PetscReal *alpha2, PetscReal *threshold) 5458d71ae5a4SJacob Faibussowitsch { 5459fa9f3622SBarry Smith SNESKSPEW *kctx; 54605fd66863SKarl Rupp 546171f87433Sdalcinl PetscFunctionBegin; 54620700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5463fa9f3622SBarry Smith kctx = (SNESKSPEW *)snes->kspconvctx; 54645f80ce2aSJacob Faibussowitsch PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing"); 546571f87433Sdalcinl if (version) *version = kctx->version; 546671f87433Sdalcinl if (rtol_0) *rtol_0 = kctx->rtol_0; 546771f87433Sdalcinl if (rtol_max) *rtol_max = kctx->rtol_max; 546871f87433Sdalcinl if (gamma) *gamma = kctx->gamma; 546971f87433Sdalcinl if (alpha) *alpha = kctx->alpha; 547071f87433Sdalcinl if (alpha2) *alpha2 = kctx->alpha2; 547171f87433Sdalcinl if (threshold) *threshold = kctx->threshold; 54723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 547371f87433Sdalcinl } 547471f87433Sdalcinl 54755c0db29aSPierre Jolivet PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx) 5476d71ae5a4SJacob Faibussowitsch { 54775c0db29aSPierre Jolivet SNES snes = (SNES)ctx; 5478fa9f3622SBarry Smith SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx; 547977e5a1f9SBarry Smith PetscReal rtol = PETSC_CURRENT, stol; 548071f87433Sdalcinl 548171f87433Sdalcinl PetscFunctionBegin; 54823ba16761SJacob Faibussowitsch if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS); 548330058271SDmitry Karpeev if (!snes->iter) { 548430058271SDmitry Karpeev rtol = kctx->rtol_0; /* first time in, so use the original user rtol */ 54859566063dSJacob Faibussowitsch PetscCall(VecNorm(snes->vec_func, NORM_2, &kctx->norm_first)); 54860f0abf79SStefano Zampini } else { 54870fdf79fbSJacob 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); 548871f87433Sdalcinl if (kctx->version == 1) { 54890f0abf79SStefano Zampini rtol = PetscAbsReal(snes->norm - kctx->lresid_last) / kctx->norm_last; 549085ec1a3cSBarry Smith stol = PetscPowReal(kctx->rtol_last, kctx->alpha2); 549171f87433Sdalcinl if (stol > kctx->threshold) rtol = PetscMax(rtol, stol); 549271f87433Sdalcinl } else if (kctx->version == 2) { 549385ec1a3cSBarry Smith rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha); 549485ec1a3cSBarry Smith stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha); 549571f87433Sdalcinl if (stol > kctx->threshold) rtol = PetscMax(rtol, stol); 549671f87433Sdalcinl } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */ 549785ec1a3cSBarry Smith rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha); 549871f87433Sdalcinl /* safeguard: avoid sharp decrease of rtol */ 549985ec1a3cSBarry Smith stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha); 550071f87433Sdalcinl stol = PetscMax(rtol, stol); 550171f87433Sdalcinl rtol = PetscMin(kctx->rtol_0, stol); 550271f87433Sdalcinl /* safeguard: avoid oversolving */ 550330058271SDmitry Karpeev stol = kctx->gamma * (kctx->norm_first * snes->rtol) / snes->norm; 550471f87433Sdalcinl stol = PetscMax(rtol, stol); 550571f87433Sdalcinl rtol = PetscMin(kctx->rtol_0, stol); 55060fdf79fbSJacob Faibussowitsch } else /* if (kctx->version == 4) */ { 55070fdf79fbSJacob Faibussowitsch /* H.-B. An et al. Journal of Computational and Applied Mathematics 200 (2007) 47-60 */ 55080f0abf79SStefano Zampini PetscReal ared = PetscAbsReal(kctx->norm_last - snes->norm); 55090f0abf79SStefano Zampini PetscReal pred = PetscAbsReal(kctx->norm_last - kctx->lresid_last); 55100f0abf79SStefano Zampini PetscReal rk = ared / pred; 55110f0abf79SStefano Zampini if (rk < kctx->v4_p1) rtol = 1. - 2. * kctx->v4_p1; 55120f0abf79SStefano Zampini else if (rk < kctx->v4_p2) rtol = kctx->rtol_last; 55130f0abf79SStefano Zampini else if (rk < kctx->v4_p3) rtol = kctx->v4_m1 * kctx->rtol_last; 55140f0abf79SStefano Zampini else rtol = kctx->v4_m2 * kctx->rtol_last; 55150f0abf79SStefano Zampini 5516a4598233SStefano 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; 55170f0abf79SStefano Zampini kctx->rtol_last_2 = kctx->rtol_last; 55180f0abf79SStefano Zampini kctx->rk_last_2 = kctx->rk_last; 55190f0abf79SStefano Zampini kctx->rk_last = rk; 55200fdf79fbSJacob Faibussowitsch } 55210f0abf79SStefano Zampini } 55220f0abf79SStefano Zampini /* safeguard: avoid rtol greater than rtol_max */ 552371f87433Sdalcinl rtol = PetscMin(rtol, kctx->rtol_max); 552477e5a1f9SBarry Smith PetscCall(KSPSetTolerances(ksp, rtol, PETSC_CURRENT, PETSC_CURRENT, PETSC_CURRENT)); 552563a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "iter %" PetscInt_FMT ", Eisenstat-Walker (version %" PetscInt_FMT ") KSP rtol=%g\n", snes->iter, kctx->version, (double)rtol)); 55263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 552771f87433Sdalcinl } 552871f87433Sdalcinl 55295c0db29aSPierre Jolivet PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx) 5530d71ae5a4SJacob Faibussowitsch { 55315c0db29aSPierre Jolivet SNES snes = (SNES)ctx; 5532fa9f3622SBarry Smith SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx; 553371f87433Sdalcinl PCSide pcside; 553471f87433Sdalcinl Vec lres; 553571f87433Sdalcinl 553671f87433Sdalcinl PetscFunctionBegin; 55373ba16761SJacob Faibussowitsch if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS); 55389566063dSJacob Faibussowitsch PetscCall(KSPGetTolerances(ksp, &kctx->rtol_last, NULL, NULL, NULL)); 553971dbe336SPeter Brune kctx->norm_last = snes->norm; 55400f0abf79SStefano Zampini if (kctx->version == 1 || kctx->version == 4) { 55414f00ce20SMatthew G. Knepley PC pc; 55420f0abf79SStefano Zampini PetscBool getRes; 55434f00ce20SMatthew G. Knepley 55449566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksp, &pc)); 55450f0abf79SStefano Zampini PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &getRes)); 55460f0abf79SStefano Zampini if (!getRes) { 55470f0abf79SStefano Zampini KSPNormType normtype; 55480f0abf79SStefano Zampini 55490f0abf79SStefano Zampini PetscCall(KSPGetNormType(ksp, &normtype)); 55500f0abf79SStefano Zampini getRes = (PetscBool)(normtype == KSP_NORM_UNPRECONDITIONED); 55510f0abf79SStefano Zampini } 55529566063dSJacob Faibussowitsch PetscCall(KSPGetPCSide(ksp, &pcside)); 55530f0abf79SStefano Zampini if (pcside == PC_RIGHT || getRes) { /* KSP residual is true linear residual */ 55549566063dSJacob Faibussowitsch PetscCall(KSPGetResidualNorm(ksp, &kctx->lresid_last)); 555571f87433Sdalcinl } else { 555671f87433Sdalcinl /* KSP residual is preconditioned residual */ 555771f87433Sdalcinl /* compute true linear residual norm */ 55580f0abf79SStefano Zampini Mat J; 55590f0abf79SStefano Zampini PetscCall(KSPGetOperators(ksp, &J, NULL)); 55609566063dSJacob Faibussowitsch PetscCall(VecDuplicate(b, &lres)); 55610f0abf79SStefano Zampini PetscCall(MatMult(J, x, lres)); 55629566063dSJacob Faibussowitsch PetscCall(VecAYPX(lres, -1.0, b)); 55639566063dSJacob Faibussowitsch PetscCall(VecNorm(lres, NORM_2, &kctx->lresid_last)); 55649566063dSJacob Faibussowitsch PetscCall(VecDestroy(&lres)); 556571f87433Sdalcinl } 556671f87433Sdalcinl } 55673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 556871f87433Sdalcinl } 556971f87433Sdalcinl 5570d4211eb9SBarry Smith /*@ 5571f6dfbefdSBarry Smith SNESGetKSP - Returns the `KSP` context for a `SNES` solver. 5572d4211eb9SBarry Smith 5573420bcc1bSBarry Smith Not Collective, but if `snes` is parallel, then `ksp` is parallel 5574d4211eb9SBarry Smith 5575d4211eb9SBarry Smith Input Parameter: 5576f6dfbefdSBarry Smith . snes - the `SNES` context 5577d4211eb9SBarry Smith 5578d4211eb9SBarry Smith Output Parameter: 5579f6dfbefdSBarry Smith . ksp - the `KSP` context 5580d4211eb9SBarry Smith 5581dc4c0fb0SBarry Smith Level: beginner 5582dc4c0fb0SBarry Smith 5583d4211eb9SBarry Smith Notes: 5584f6dfbefdSBarry Smith The user can then directly manipulate the `KSP` context to set various 5585d4211eb9SBarry Smith options, etc. Likewise, the user can then extract and manipulate the 5586f6dfbefdSBarry Smith `PC` contexts as well. 5587f6dfbefdSBarry Smith 55880b4b7b1cSBarry Smith Some `SNESType`s do not use a `KSP` but a `KSP` is still returned by this function, changes to that `KSP` will have no effect. 5589d4211eb9SBarry Smith 55901cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSP`, `PC`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()` 5591d4211eb9SBarry Smith @*/ 5592d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetKSP(SNES snes, KSP *ksp) 5593d71ae5a4SJacob Faibussowitsch { 559471f87433Sdalcinl PetscFunctionBegin; 5595d4211eb9SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 55964f572ea9SToby Isaac PetscAssertPointer(ksp, 2); 5597d4211eb9SBarry Smith 5598d4211eb9SBarry Smith if (!snes->ksp) { 55999566063dSJacob Faibussowitsch PetscCall(KSPCreate(PetscObjectComm((PetscObject)snes), &snes->ksp)); 56009566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->ksp, (PetscObject)snes, 1)); 5601d4211eb9SBarry Smith 56025c0db29aSPierre Jolivet PetscCall(KSPSetPreSolve(snes->ksp, KSPPreSolve_SNESEW, snes)); 56035c0db29aSPierre Jolivet PetscCall(KSPSetPostSolve(snes->ksp, KSPPostSolve_SNESEW, snes)); 5604a5c2985bSBarry Smith 56059566063dSJacob Faibussowitsch PetscCall(KSPMonitorSetFromOptions(snes->ksp, "-snes_monitor_ksp", "snes_preconditioned_residual", snes)); 56069566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptions((PetscObject)snes->ksp, ((PetscObject)snes)->options)); 5607d4211eb9SBarry Smith } 5608d4211eb9SBarry Smith *ksp = snes->ksp; 56093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 561071f87433Sdalcinl } 56116c699258SBarry Smith 5612af0996ceSBarry Smith #include <petsc/private/dmimpl.h> 56136c699258SBarry Smith /*@ 56140b4b7b1cSBarry Smith SNESSetDM - Sets the `DM` that may be used by some `SNES` nonlinear solvers or their underlying preconditioners 56156c699258SBarry Smith 5616c3339decSBarry Smith Logically Collective 56176c699258SBarry Smith 56186c699258SBarry Smith Input Parameters: 56192a808120SBarry Smith + snes - the nonlinear solver context 5620420bcc1bSBarry Smith - dm - the `DM`, cannot be `NULL` 5621dc4c0fb0SBarry Smith 5622dc4c0fb0SBarry Smith Level: intermediate 56236c699258SBarry Smith 5624f6dfbefdSBarry Smith Note: 5625f6dfbefdSBarry Smith A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`, 5626f6dfbefdSBarry Smith even when not using interfaces like `DMSNESSetFunction()`. Use `DMClone()` to get a distinct `DM` when solving different 5627e03a659cSJed Brown problems using the same function space. 5628e03a659cSJed Brown 5629420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()` 56306c699258SBarry Smith @*/ 5631d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDM(SNES snes, DM dm) 5632d71ae5a4SJacob Faibussowitsch { 5633345fed2cSBarry Smith KSP ksp; 5634942e3340SBarry Smith DMSNES sdm; 56356c699258SBarry Smith 56366c699258SBarry Smith PetscFunctionBegin; 56370700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 56382a808120SBarry Smith PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 56399566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 5640942e3340SBarry Smith if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */ 564151f4b3c7SToby Isaac if (snes->dm->dmsnes && !dm->dmsnes) { 56429566063dSJacob Faibussowitsch PetscCall(DMCopyDMSNES(snes->dm, dm)); 56439566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(snes->dm, &sdm)); 5644f5af7f23SKarl Rupp if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */ 56456cab3a1bSJed Brown } 56469566063dSJacob Faibussowitsch PetscCall(DMCoarsenHookRemove(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes)); 56479566063dSJacob Faibussowitsch PetscCall(DMDestroy(&snes->dm)); 56486cab3a1bSJed Brown } 56496c699258SBarry Smith snes->dm = dm; 5650116d1032SJed Brown snes->dmAuto = PETSC_FALSE; 5651f5af7f23SKarl Rupp 56529566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 56539566063dSJacob Faibussowitsch PetscCall(KSPSetDM(ksp, dm)); 56549566063dSJacob Faibussowitsch PetscCall(KSPSetDMActive(ksp, PETSC_FALSE)); 5655efd4aadfSBarry Smith if (snes->npc) { 56569566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes->npc, snes->dm)); 56579566063dSJacob Faibussowitsch PetscCall(SNESSetNPCSide(snes, snes->npcside)); 56582c155ee1SBarry Smith } 56593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 56606c699258SBarry Smith } 56616c699258SBarry Smith 56626c699258SBarry Smith /*@ 56630b4b7b1cSBarry Smith SNESGetDM - Gets the `DM` that may be used by some `SNES` nonlinear solvers/preconditioners 56646c699258SBarry Smith 56650b4b7b1cSBarry Smith Not Collective but `dm` obtained is parallel on `snes` 56666c699258SBarry Smith 56676c699258SBarry Smith Input Parameter: 5668420bcc1bSBarry Smith . snes - the `SNES` context 56696c699258SBarry Smith 56706c699258SBarry Smith Output Parameter: 5671420bcc1bSBarry Smith . dm - the `DM` 56726c699258SBarry Smith 56736c699258SBarry Smith Level: intermediate 56746c699258SBarry Smith 5675420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESSetDM()`, `KSPSetDM()`, `KSPGetDM()` 56766c699258SBarry Smith @*/ 5677d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDM(SNES snes, DM *dm) 5678d71ae5a4SJacob Faibussowitsch { 56796c699258SBarry Smith PetscFunctionBegin; 56800700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 56816cab3a1bSJed Brown if (!snes->dm) { 56829566063dSJacob Faibussowitsch PetscCall(DMShellCreate(PetscObjectComm((PetscObject)snes), &snes->dm)); 5683116d1032SJed Brown snes->dmAuto = PETSC_TRUE; 56846cab3a1bSJed Brown } 56856c699258SBarry Smith *dm = snes->dm; 56863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 56876c699258SBarry Smith } 56880807856dSBarry Smith 568931823bd8SMatthew G Knepley /*@ 5690be95d8f1SBarry Smith SNESSetNPC - Sets the nonlinear preconditioner to be used. 569131823bd8SMatthew G Knepley 5692c3339decSBarry Smith Collective 569331823bd8SMatthew G Knepley 569431823bd8SMatthew G Knepley Input Parameters: 5695f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 569662842358SBarry Smith - npc - the `SNES` nonlinear preconditioner object 569762842358SBarry Smith 569862842358SBarry Smith Options Database Key: 569962842358SBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner 570031823bd8SMatthew G Knepley 5701dc4c0fb0SBarry Smith Level: developer 5702dc4c0fb0SBarry Smith 570331823bd8SMatthew G Knepley Notes: 570462842358SBarry Smith This is rarely used, rather use `SNESGetNPC()` to retrieve the preconditioner and configure it using the API. 570531823bd8SMatthew G Knepley 5706f6dfbefdSBarry Smith Only some `SNESType` can use a nonlinear preconditioner 5707f6dfbefdSBarry Smith 5708420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNGS`, `SNESFAS`, `SNESGetNPC()`, `SNESHasNPC()` 570931823bd8SMatthew G Knepley @*/ 5710d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPC(SNES snes, SNES npc) 5711d71ae5a4SJacob Faibussowitsch { 571231823bd8SMatthew G Knepley PetscFunctionBegin; 571331823bd8SMatthew G Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5714f6dfbefdSBarry Smith PetscValidHeaderSpecific(npc, SNES_CLASSID, 2); 5715f6dfbefdSBarry Smith PetscCheckSameComm(snes, 1, npc, 2); 5716f6dfbefdSBarry Smith PetscCall(PetscObjectReference((PetscObject)npc)); 57179566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&snes->npc)); 5718f6dfbefdSBarry Smith snes->npc = npc; 57193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 572031823bd8SMatthew G Knepley } 572131823bd8SMatthew G Knepley 572231823bd8SMatthew G Knepley /*@ 5723f6dfbefdSBarry Smith SNESGetNPC - Gets a nonlinear preconditioning solver SNES` to be used to precondition the original nonlinear solver. 572431823bd8SMatthew G Knepley 57250b4b7b1cSBarry Smith Not Collective; but any changes to the obtained the `pc` object must be applied collectively 572631823bd8SMatthew G Knepley 572731823bd8SMatthew G Knepley Input Parameter: 5728f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 572931823bd8SMatthew G Knepley 573031823bd8SMatthew G Knepley Output Parameter: 573162842358SBarry Smith . pc - the `SNES` preconditioner context 573231823bd8SMatthew G Knepley 5733f6dfbefdSBarry Smith Options Database Key: 5734f6dfbefdSBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner 5735b5badacbSBarry Smith 57360b4b7b1cSBarry Smith Level: advanced 5737dc4c0fb0SBarry Smith 573895452b02SPatrick Sanan Notes: 57390b4b7b1cSBarry Smith If a `SNES` was previously set with `SNESSetNPC()` then that value is returned, otherwise a new `SNES` object is created that will 57400b4b7b1cSBarry Smith be used as the nonlinear preconditioner for the current `SNES`. 5741be95d8f1SBarry Smith 5742f6dfbefdSBarry Smith The (preconditioner) `SNES` returned automatically inherits the same nonlinear function and Jacobian supplied to the original 574362842358SBarry Smith `SNES`. These may be overwritten if needed. 574462842358SBarry Smith 574562842358SBarry Smith Use the options database prefixes `-npc_snes`, `-npc_ksp`, etc., to control the configuration of the nonlinear preconditioner 5746951fe5abSBarry Smith 57471cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESHasNPC()`, `SNES`, `SNESCreate()` 574831823bd8SMatthew G Knepley @*/ 5749d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPC(SNES snes, SNES *pc) 5750d71ae5a4SJacob Faibussowitsch { 5751a64e098fSPeter Brune const char *optionsprefix; 575231823bd8SMatthew G Knepley 575331823bd8SMatthew G Knepley PetscFunctionBegin; 575431823bd8SMatthew G Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 57554f572ea9SToby Isaac PetscAssertPointer(pc, 2); 5756efd4aadfSBarry Smith if (!snes->npc) { 5757ec785e5bSStefano Zampini void *ctx; 5758ec785e5bSStefano Zampini 57599566063dSJacob Faibussowitsch PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &snes->npc)); 57609566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->npc, (PetscObject)snes, 1)); 57619566063dSJacob Faibussowitsch PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 57629566063dSJacob Faibussowitsch PetscCall(SNESSetOptionsPrefix(snes->npc, optionsprefix)); 57639566063dSJacob Faibussowitsch PetscCall(SNESAppendOptionsPrefix(snes->npc, "npc_")); 5764fb87a551SStefano Zampini if (snes->ops->usercompute) { 576549abdd8aSBarry Smith PetscCall(SNESSetComputeApplicationContext(snes, snes->ops->usercompute, snes->ops->ctxdestroy)); 5766fb87a551SStefano Zampini } else { 5767ec785e5bSStefano Zampini PetscCall(SNESGetApplicationContext(snes, &ctx)); 5768ec785e5bSStefano Zampini PetscCall(SNESSetApplicationContext(snes->npc, ctx)); 5769fb87a551SStefano Zampini } 57709566063dSJacob Faibussowitsch PetscCall(SNESSetCountersReset(snes->npc, PETSC_FALSE)); 577131823bd8SMatthew G Knepley } 5772efd4aadfSBarry Smith *pc = snes->npc; 57733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 577431823bd8SMatthew G Knepley } 577531823bd8SMatthew G Knepley 57763ad1a0b9SPatrick Farrell /*@ 57770b4b7b1cSBarry Smith SNESHasNPC - Returns whether a nonlinear preconditioner is associated with the given `SNES` 57783ad1a0b9SPatrick Farrell 57793ad1a0b9SPatrick Farrell Not Collective 57803ad1a0b9SPatrick Farrell 57813ad1a0b9SPatrick Farrell Input Parameter: 5782f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 57833ad1a0b9SPatrick Farrell 57843ad1a0b9SPatrick Farrell Output Parameter: 5785420bcc1bSBarry Smith . has_npc - whether the `SNES` has a nonlinear preconditioner or not 57863ad1a0b9SPatrick Farrell 57873ad1a0b9SPatrick Farrell Level: developer 57883ad1a0b9SPatrick Farrell 57891cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESGetNPC()` 57903ad1a0b9SPatrick Farrell @*/ 5791d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc) 5792d71ae5a4SJacob Faibussowitsch { 57933ad1a0b9SPatrick Farrell PetscFunctionBegin; 57943ad1a0b9SPatrick Farrell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5795835f2295SStefano Zampini PetscAssertPointer(has_npc, 2); 5796835f2295SStefano Zampini *has_npc = snes->npc ? PETSC_TRUE : PETSC_FALSE; 57973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 57983ad1a0b9SPatrick Farrell } 57993ad1a0b9SPatrick Farrell 5800c40d0f55SPeter Brune /*@ 580162842358SBarry Smith SNESSetNPCSide - Sets the nonlinear preconditioning side used by the nonlinear preconditioner inside `SNES`. 5802c40d0f55SPeter Brune 5803c3339decSBarry Smith Logically Collective 5804c40d0f55SPeter Brune 5805c40d0f55SPeter Brune Input Parameter: 5806f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 5807c40d0f55SPeter Brune 5808c40d0f55SPeter Brune Output Parameter: 5809c40d0f55SPeter Brune . side - the preconditioning side, where side is one of 5810c40d0f55SPeter Brune .vb 58112d547940SBarry Smith PC_LEFT - left preconditioning 58122d547940SBarry Smith PC_RIGHT - right preconditioning (default for most nonlinear solvers) 5813c40d0f55SPeter Brune .ve 5814c40d0f55SPeter Brune 5815f6dfbefdSBarry Smith Options Database Key: 581667b8a455SSatish Balay . -snes_npc_side <right,left> - nonlinear preconditioner side 5817c40d0f55SPeter Brune 5818dc4c0fb0SBarry Smith Level: intermediate 5819dc4c0fb0SBarry Smith 5820f6dfbefdSBarry Smith Note: 5821f6dfbefdSBarry Smith `SNESNRICHARDSON` and `SNESNCG` only support left preconditioning. 58222d547940SBarry Smith 582362842358SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNPC()`, `SNESNRICHARDSON`, `SNESNCG`, `SNESType`, `SNESGetNPCSide()`, `KSPSetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide` 5824c40d0f55SPeter Brune @*/ 5825d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPCSide(SNES snes, PCSide side) 5826d71ae5a4SJacob Faibussowitsch { 5827c40d0f55SPeter Brune PetscFunctionBegin; 5828c40d0f55SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5829c40d0f55SPeter Brune PetscValidLogicalCollectiveEnum(snes, side, 2); 5830b552625fSStefano Zampini if (side == PC_SIDE_DEFAULT) side = PC_RIGHT; 583154c59aa7SJacob Faibussowitsch PetscCheck((side == PC_LEFT) || (side == PC_RIGHT), PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Only PC_LEFT and PC_RIGHT are supported"); 5832efd4aadfSBarry Smith snes->npcside = side; 58333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5834c40d0f55SPeter Brune } 5835c40d0f55SPeter Brune 5836c40d0f55SPeter Brune /*@ 583762842358SBarry Smith SNESGetNPCSide - Gets the preconditioning side used by the nonlinear preconditioner inside `SNES`. 5838c40d0f55SPeter Brune 5839c40d0f55SPeter Brune Not Collective 5840c40d0f55SPeter Brune 5841c40d0f55SPeter Brune Input Parameter: 5842f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 5843c40d0f55SPeter Brune 5844c40d0f55SPeter Brune Output Parameter: 5845c40d0f55SPeter Brune . side - the preconditioning side, where side is one of 5846c40d0f55SPeter Brune .vb 5847f6dfbefdSBarry Smith `PC_LEFT` - left preconditioning 5848f6dfbefdSBarry Smith `PC_RIGHT` - right preconditioning (default for most nonlinear solvers) 5849c40d0f55SPeter Brune .ve 5850c40d0f55SPeter Brune 5851c40d0f55SPeter Brune Level: intermediate 5852c40d0f55SPeter Brune 585362842358SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNPC()`, `SNESSetNPCSide()`, `KSPGetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide` 5854c40d0f55SPeter Brune @*/ 5855d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPCSide(SNES snes, PCSide *side) 5856d71ae5a4SJacob Faibussowitsch { 5857c40d0f55SPeter Brune PetscFunctionBegin; 5858c40d0f55SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 58594f572ea9SToby Isaac PetscAssertPointer(side, 2); 5860efd4aadfSBarry Smith *side = snes->npcside; 58613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5862c40d0f55SPeter Brune } 5863c40d0f55SPeter Brune 58649e764e56SPeter Brune /*@ 58650b4b7b1cSBarry Smith SNESSetLineSearch - Sets the `SNESLineSearch` to be used for a given `SNES` 58669e764e56SPeter Brune 5867c3339decSBarry Smith Collective 58689e764e56SPeter Brune 58699e764e56SPeter Brune Input Parameters: 5870f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 58719e764e56SPeter Brune - linesearch - the linesearch object 58729e764e56SPeter Brune 5873dc4c0fb0SBarry Smith Level: developer 5874dc4c0fb0SBarry Smith 5875f6dfbefdSBarry Smith Note: 5876420bcc1bSBarry Smith This is almost never used, rather one uses `SNESGetLineSearch()` to retrieve the line search and set options on it 58779e764e56SPeter Brune to configure it using the API). 58789e764e56SPeter Brune 5879420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()` 58809e764e56SPeter Brune @*/ 5881d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch) 5882d71ae5a4SJacob Faibussowitsch { 58839e764e56SPeter Brune PetscFunctionBegin; 58849e764e56SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5885f1c6b773SPeter Brune PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 2); 58869e764e56SPeter Brune PetscCheckSameComm(snes, 1, linesearch, 2); 58879566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)linesearch)); 58889566063dSJacob Faibussowitsch PetscCall(SNESLineSearchDestroy(&snes->linesearch)); 5889f5af7f23SKarl Rupp 58909e764e56SPeter Brune snes->linesearch = linesearch; 58913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 58929e764e56SPeter Brune } 58939e764e56SPeter Brune 5894a34ceb2aSJed Brown /*@ 589562842358SBarry Smith SNESGetLineSearch - Returns the line search associated with the `SNES`. 58969e764e56SPeter Brune 58979e764e56SPeter Brune Not Collective 58989e764e56SPeter Brune 58999e764e56SPeter Brune Input Parameter: 5900f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 59019e764e56SPeter Brune 59029e764e56SPeter Brune Output Parameter: 59039e764e56SPeter Brune . linesearch - linesearch context 59049e764e56SPeter Brune 5905162e0bf5SPeter Brune Level: beginner 59069e764e56SPeter Brune 590762842358SBarry Smith Notes: 590862842358SBarry Smith It creates a default line search instance which can be configured as needed in case it has not been already set with `SNESSetLineSearch()`. 590962842358SBarry Smith 591062842358SBarry Smith You can also use the options database keys `-snes_linesearch_*` to configure the line search. See `SNESLineSearchSetFromOptions()` for the possible options. 591162842358SBarry Smith 591262842358SBarry Smith .seealso: [](ch_snes), `SNESLineSearch`, `SNESSetLineSearch()`, `SNESLineSearchCreate()`, `SNESLineSearchSetFromOptions()` 59139e764e56SPeter Brune @*/ 5914d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch) 5915d71ae5a4SJacob Faibussowitsch { 59169e764e56SPeter Brune const char *optionsprefix; 59179e764e56SPeter Brune 59189e764e56SPeter Brune PetscFunctionBegin; 59199e764e56SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 59204f572ea9SToby Isaac PetscAssertPointer(linesearch, 2); 59219e764e56SPeter Brune if (!snes->linesearch) { 59229566063dSJacob Faibussowitsch PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 59239566063dSJacob Faibussowitsch PetscCall(SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch)); 59249566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetSNES(snes->linesearch, snes)); 59259566063dSJacob Faibussowitsch PetscCall(SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix)); 59269566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->linesearch, (PetscObject)snes, 1)); 59279e764e56SPeter Brune } 59289e764e56SPeter Brune *linesearch = snes->linesearch; 59293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 59309e764e56SPeter Brune } 5931