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 808d6acfc2dSPierre Jolivet PETSC_SINGLE_LIBRARY_INTERN 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 1125*1dfd7622SMatthew Knepley PetscCall(PetscOptionsName("-snes_test_function", "Compare hand-coded and finite difference functions", "None", &snes->testFunc)); 1126*1dfd7622SMatthew Knepley PetscCall(PetscOptionsName("-snes_test_jacobian", "Compare hand-coded and finite difference Jacobians", "None", &snes->testJac)); 1127*1dfd7622SMatthew Knepley 1128c40d0f55SPeter Brune flg = PETSC_FALSE; 11299566063dSJacob Faibussowitsch PetscCall(SNESGetNPCSide(snes, &pcside)); 11309566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-snes_npc_side", "SNES nonlinear preconditioner side", "SNESSetNPCSide", PCSides, (PetscEnum)pcside, (PetscEnum *)&pcside, &flg)); 11319566063dSJacob Faibussowitsch if (flg) PetscCall(SNESSetNPCSide(snes, pcside)); 1132c40d0f55SPeter Brune 1133e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS) 11348a70d858SHong Zhang /* 11358a70d858SHong Zhang Publish convergence information using SAWs 11368a70d858SHong Zhang */ 11378a70d858SHong Zhang flg = PETSC_FALSE; 11389566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_monitor_saws", "Publish SNES progress using SAWs", "SNESMonitorSet", flg, &flg, NULL)); 11398a70d858SHong Zhang if (flg) { 11408a70d858SHong Zhang void *ctx; 11419566063dSJacob Faibussowitsch PetscCall(SNESMonitorSAWsCreate(snes, &ctx)); 11429566063dSJacob Faibussowitsch PetscCall(SNESMonitorSet(snes, SNESMonitorSAWs, ctx, SNESMonitorSAWsDestroy)); 11438a70d858SHong Zhang } 11448a70d858SHong Zhang #endif 11458a70d858SHong Zhang #if defined(PETSC_HAVE_SAWS) 1146b90c6cbeSBarry Smith { 1147b90c6cbeSBarry Smith PetscBool set; 1148b90c6cbeSBarry Smith flg = PETSC_FALSE; 11499566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_saws_block", "Block for SAWs at end of SNESSolve", "PetscObjectSAWsBlock", ((PetscObject)snes)->amspublishblock, &flg, &set)); 11501baa6e33SBarry Smith if (set) PetscCall(PetscObjectSAWsSetBlock((PetscObject)snes, flg)); 1151b90c6cbeSBarry Smith } 1152b90c6cbeSBarry Smith #endif 1153b90c6cbeSBarry Smith 115448a46eb9SPierre Jolivet for (i = 0; i < numberofsetfromoptions; i++) PetscCall((*othersetfromoptions[i])(snes)); 115576b2cf59SMatthew Knepley 1156dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, setfromoptions, PetscOptionsObject); 11575d973c19SBarry Smith 11585d973c19SBarry Smith /* process any options handlers added with PetscObjectAddOptionsHandler() */ 1159dbbe0bcdSBarry Smith PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)snes, PetscOptionsObject)); 1160d0609cedSBarry Smith PetscOptionsEnd(); 11614bbc92c1SBarry Smith 1162d8d34be6SBarry Smith if (snes->linesearch) { 11639566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 11649566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetFromOptions(snes->linesearch)); 1165d8d34be6SBarry Smith } 11669e764e56SPeter Brune 11676aa5e7e9SBarry Smith if (snes->usesksp) { 11689566063dSJacob Faibussowitsch if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 11699566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(snes->ksp, snes->jacobian, snes->jacobian_pre)); 11709566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(snes->ksp)); 11716aa5e7e9SBarry Smith } 11726991f827SBarry Smith 1173b5badacbSBarry Smith /* if user has set the SNES NPC type via options database, create it. */ 11749566063dSJacob Faibussowitsch PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 11759566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)snes)->options, optionsprefix, "-npc_snes_type", &pcset)); 117648a46eb9SPierre Jolivet if (pcset && (!snes->npc)) PetscCall(SNESGetNPC(snes, &snes->npc)); 11771baa6e33SBarry Smith if (snes->npc) PetscCall(SNESSetFromOptions(snes->npc)); 1178b3cd9a81SMatthew G. Knepley snes->setfromoptionscalled++; 11793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1180b3cd9a81SMatthew G. Knepley } 1181b3cd9a81SMatthew G. Knepley 1182b3cd9a81SMatthew G. Knepley /*@ 1183420bcc1bSBarry Smith SNESResetFromOptions - Sets various `SNES` and `KSP` parameters from user options ONLY if the `SNESSetFromOptions()` was previously called 1184b3cd9a81SMatthew G. Knepley 1185c3339decSBarry Smith Collective 1186b3cd9a81SMatthew G. Knepley 1187b3cd9a81SMatthew G. Knepley Input Parameter: 1188f6dfbefdSBarry Smith . snes - the `SNES` context 1189b3cd9a81SMatthew G. Knepley 1190420bcc1bSBarry Smith Level: advanced 1191b3cd9a81SMatthew G. Knepley 11921cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESSetOptionsPrefix()` 1193b3cd9a81SMatthew G. Knepley @*/ 1194d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESResetFromOptions(SNES snes) 1195d71ae5a4SJacob Faibussowitsch { 1196b3cd9a81SMatthew G. Knepley PetscFunctionBegin; 11979566063dSJacob Faibussowitsch if (snes->setfromoptionscalled) PetscCall(SNESSetFromOptions(snes)); 11983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11999b94acceSBarry Smith } 12009b94acceSBarry Smith 1201bb9467b5SJed Brown /*@C 1202d25893d9SBarry Smith SNESSetComputeApplicationContext - Sets an optional function to compute a user-defined context for 1203d25893d9SBarry Smith the nonlinear solvers. 1204d25893d9SBarry Smith 1205dc4c0fb0SBarry Smith Logically Collective; No Fortran Support 1206d25893d9SBarry Smith 1207d25893d9SBarry Smith Input Parameters: 1208f6dfbefdSBarry Smith + snes - the `SNES` context 1209d25893d9SBarry Smith . compute - function to compute the context 121049abdd8aSBarry Smith - destroy - function to destroy the context, see `PetscCtxDestroyFn` for the calling sequence 1211d25893d9SBarry Smith 1212420bcc1bSBarry Smith Calling sequence of `compute`: 1213420bcc1bSBarry Smith + snes - the `SNES` context 1214420bcc1bSBarry Smith - ctx - context to be computed 1215420bcc1bSBarry Smith 1216d25893d9SBarry Smith Level: intermediate 1217d25893d9SBarry Smith 1218f6dfbefdSBarry Smith Note: 1219f6dfbefdSBarry Smith This routine is useful if you are performing grid sequencing or using `SNESFAS` and need the appropriate context generated for each level. 1220f6dfbefdSBarry Smith 1221f6dfbefdSBarry Smith Use `SNESSetApplicationContext()` to see the context immediately 1222f6dfbefdSBarry Smith 122349abdd8aSBarry Smith .seealso: [](ch_snes), `SNESGetApplicationContext()`, `SNESSetApplicationContext()`, `PetscCtxDestroyFn` 1224d25893d9SBarry Smith @*/ 122549abdd8aSBarry Smith PetscErrorCode SNESSetComputeApplicationContext(SNES snes, PetscErrorCode (*compute)(SNES snes, void **ctx), PetscCtxDestroyFn *destroy) 1226d71ae5a4SJacob Faibussowitsch { 1227d25893d9SBarry Smith PetscFunctionBegin; 1228d25893d9SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1229d25893d9SBarry Smith snes->ops->usercompute = compute; 123049abdd8aSBarry Smith snes->ops->ctxdestroy = destroy; 12313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1232d25893d9SBarry Smith } 1233a847f771SSatish Balay 1234b07ff414SBarry Smith /*@ 1235f6dfbefdSBarry Smith SNESSetApplicationContext - Sets the optional user-defined context for the nonlinear solvers. 12369b94acceSBarry Smith 1237c3339decSBarry Smith Logically Collective 1238fee21e36SBarry Smith 1239c7afd0dbSLois Curfman McInnes Input Parameters: 1240f6dfbefdSBarry Smith + snes - the `SNES` context 1241ce78bad3SBarry Smith - ctx - the user context 1242c7afd0dbSLois Curfman McInnes 124336851e7fSLois Curfman McInnes Level: intermediate 124436851e7fSLois Curfman McInnes 1245f6dfbefdSBarry Smith Notes: 1246ce78bad3SBarry Smith Users can provide a context when constructing the `SNES` options and then access it inside their function, Jacobian computation, or other evaluation function 1247f6dfbefdSBarry Smith with `SNESGetApplicationContext()` 1248f6dfbefdSBarry Smith 1249f6dfbefdSBarry Smith To provide a function that computes the context for you use `SNESSetComputeApplicationContext()` 1250f6dfbefdSBarry Smith 1251420bcc1bSBarry Smith Fortran Note: 1252ce78bad3SBarry 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 1253ce78bad3SBarry Smith function that tells the Fortran compiler the derived data type that is passed in as the `ctx` argument. See `SNESGetApplicationContext()` for 1254ce78bad3SBarry Smith an example. 1255daf670e6SBarry Smith 12561cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetComputeApplicationContext()`, `SNESGetApplicationContext()` 12579b94acceSBarry Smith @*/ 125849abdd8aSBarry Smith PetscErrorCode SNESSetApplicationContext(SNES snes, void *ctx) 1259d71ae5a4SJacob Faibussowitsch { 1260b07ff414SBarry Smith KSP ksp; 12611b2093e4SBarry Smith 12623a40ed3dSBarry Smith PetscFunctionBegin; 12630700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 12649566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 126549abdd8aSBarry Smith PetscCall(KSPSetApplicationContext(ksp, ctx)); 126649abdd8aSBarry Smith snes->ctx = ctx; 12673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12689b94acceSBarry Smith } 126974679c65SBarry Smith 1270b07ff414SBarry Smith /*@ 12719b94acceSBarry Smith SNESGetApplicationContext - Gets the user-defined context for the 1272420bcc1bSBarry Smith nonlinear solvers set with `SNESGetApplicationContext()` or `SNESSetComputeApplicationContext()` 12739b94acceSBarry Smith 1274c7afd0dbSLois Curfman McInnes Not Collective 1275c7afd0dbSLois Curfman McInnes 12769b94acceSBarry Smith Input Parameter: 1277f6dfbefdSBarry Smith . snes - `SNES` context 12789b94acceSBarry Smith 12799b94acceSBarry Smith Output Parameter: 128049abdd8aSBarry Smith . ctx - user context 12819b94acceSBarry Smith 128236851e7fSLois Curfman McInnes Level: intermediate 128336851e7fSLois Curfman McInnes 1284ce78bad3SBarry Smith Fortran Notes: 1285ce78bad3SBarry 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 1286ce78bad3SBarry Smith function that tells the Fortran compiler the derived data type that is returned as the `ctx` argument. For example, 1287ce78bad3SBarry Smith .vb 1288ce78bad3SBarry Smith Interface SNESGetApplicationContext 1289ce78bad3SBarry Smith Subroutine SNESGetApplicationContext(snes,ctx,ierr) 1290ce78bad3SBarry Smith #include <petsc/finclude/petscsnes.h> 1291ce78bad3SBarry Smith use petscsnes 1292ce78bad3SBarry Smith SNES snes 1293ce78bad3SBarry Smith type(tUsertype), pointer :: ctx 1294ce78bad3SBarry Smith PetscErrorCode ierr 1295ce78bad3SBarry Smith End Subroutine 1296ce78bad3SBarry Smith End Interface SNESGetApplicationContext 1297ce78bad3SBarry Smith .ve 1298ce78bad3SBarry Smith 1299bfe80ac4SPierre Jolivet The prototype for `ctx` must be 1300ce78bad3SBarry Smith .vb 1301ce78bad3SBarry Smith type(tUsertype), pointer :: ctx 1302ce78bad3SBarry Smith .ve 1303dc4c0fb0SBarry Smith 1304420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESSetApplicationContext()`, `SNESSetComputeApplicationContext()` 13059b94acceSBarry Smith @*/ 1306ce78bad3SBarry Smith PetscErrorCode SNESGetApplicationContext(SNES snes, PeCtx ctx) 1307d71ae5a4SJacob Faibussowitsch { 13083a40ed3dSBarry Smith PetscFunctionBegin; 13090700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 131049abdd8aSBarry Smith *(void **)ctx = snes->ctx; 13113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13129b94acceSBarry Smith } 131374679c65SBarry Smith 13149b94acceSBarry Smith /*@ 1315420bcc1bSBarry Smith SNESSetUseMatrixFree - indicates that `SNES` should use matrix-free finite difference matrix-vector products to apply the Jacobian. 13163565c898SBarry Smith 1317dc4c0fb0SBarry Smith Logically Collective 13183565c898SBarry Smith 13193565c898SBarry Smith Input Parameters: 1320f6dfbefdSBarry Smith + snes - `SNES` context 1321f6dfbefdSBarry Smith . mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used 1322f6dfbefdSBarry 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 1323420bcc1bSBarry Smith this option no matrix-element based preconditioners can be used in the linear solve since the matrix won't be explicitly available 13243565c898SBarry Smith 1325f6dfbefdSBarry Smith Options Database Keys: 132601c1178eSBarry Smith + -snes_mf_operator - use matrix-free only for the mat operator 1327f6dfbefdSBarry Smith . -snes_mf - use matrix-free for both the mat and pmat operator 1328ec5066bdSBarry Smith . -snes_fd_color - compute the Jacobian via coloring and finite differences. 1329ec5066bdSBarry Smith - -snes_fd - compute the Jacobian via finite differences (slow) 13303565c898SBarry Smith 13313565c898SBarry Smith Level: intermediate 13323565c898SBarry Smith 1333f6dfbefdSBarry Smith Note: 1334420bcc1bSBarry Smith `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`, 1335420bcc1bSBarry Smith and computing explicitly with 1336f6dfbefdSBarry Smith finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object. 1337ec5066bdSBarry Smith 1338420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetUseMatrixFree()`, `MatCreateSNESMF()`, `SNESComputeJacobianDefaultColor()`, `MatFDColoring` 13393565c898SBarry Smith @*/ 1340d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUseMatrixFree(SNES snes, PetscBool mf_operator, PetscBool mf) 1341d71ae5a4SJacob Faibussowitsch { 13423565c898SBarry Smith PetscFunctionBegin; 13433565c898SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 134488b4c220SStefano Zampini PetscValidLogicalCollectiveBool(snes, mf_operator, 2); 134588b4c220SStefano Zampini PetscValidLogicalCollectiveBool(snes, mf, 3); 13464ddffce6SLisandro Dalcin snes->mf = mf_operator ? PETSC_TRUE : mf; 13473565c898SBarry Smith snes->mf_operator = mf_operator; 13483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13493565c898SBarry Smith } 13503565c898SBarry Smith 13513565c898SBarry Smith /*@ 1352dc4c0fb0SBarry Smith SNESGetUseMatrixFree - indicates if the `SNES` uses matrix-free finite difference matrix vector products to apply the Jacobian. 13533565c898SBarry Smith 1354420bcc1bSBarry Smith Not Collective, but the resulting flags will be the same on all MPI processes 13553565c898SBarry Smith 13563565c898SBarry Smith Input Parameter: 1357f6dfbefdSBarry Smith . snes - `SNES` context 13583565c898SBarry Smith 13593565c898SBarry Smith Output Parameters: 1360f6dfbefdSBarry Smith + mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used 1361f6dfbefdSBarry 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 13623565c898SBarry Smith 13633565c898SBarry Smith Level: intermediate 13643565c898SBarry Smith 13651cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUseMatrixFree()`, `MatCreateSNESMF()` 13663565c898SBarry Smith @*/ 1367d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUseMatrixFree(SNES snes, PetscBool *mf_operator, PetscBool *mf) 1368d71ae5a4SJacob Faibussowitsch { 13693565c898SBarry Smith PetscFunctionBegin; 13703565c898SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 13713565c898SBarry Smith if (mf) *mf = snes->mf; 13723565c898SBarry Smith if (mf_operator) *mf_operator = snes->mf_operator; 13733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13743565c898SBarry Smith } 13753565c898SBarry Smith 13763565c898SBarry Smith /*@ 1377420bcc1bSBarry Smith SNESGetIterationNumber - Gets the number of nonlinear iterations completed in the current or most recent `SNESSolve()` 13789b94acceSBarry Smith 1379c7afd0dbSLois Curfman McInnes Not Collective 1380c7afd0dbSLois Curfman McInnes 13819b94acceSBarry Smith Input Parameter: 1382f6dfbefdSBarry Smith . snes - `SNES` context 13839b94acceSBarry Smith 13849b94acceSBarry Smith Output Parameter: 13859b94acceSBarry Smith . iter - iteration number 13869b94acceSBarry Smith 1387dc4c0fb0SBarry Smith Level: intermediate 1388dc4c0fb0SBarry Smith 1389c8228a4eSBarry Smith Notes: 1390c8228a4eSBarry Smith For example, during the computation of iteration 2 this would return 1. 1391c8228a4eSBarry Smith 1392c8228a4eSBarry Smith This is useful for using lagged Jacobians (where one does not recompute the 1393f6dfbefdSBarry Smith Jacobian at each `SNES` iteration). For example, the code 139408405cd6SLois Curfman McInnes .vb 139508405cd6SLois Curfman McInnes ierr = SNESGetIterationNumber(snes,&it); 139608405cd6SLois Curfman McInnes if (!(it % 2)) { 139708405cd6SLois Curfman McInnes [compute Jacobian here] 139808405cd6SLois Curfman McInnes } 139908405cd6SLois Curfman McInnes .ve 1400f6dfbefdSBarry Smith can be used in your function that computes the Jacobian to cause the Jacobian to be 1401f6dfbefdSBarry Smith recomputed every second `SNES` iteration. See also `SNESSetLagJacobian()` 1402c8228a4eSBarry Smith 1403f6dfbefdSBarry Smith After the `SNES` solve is complete this will return the number of nonlinear iterations used. 1404c04deec6SBarry Smith 1405420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetLagJacobian()`, `SNESGetLinearSolveIterations()`, `SNESSetMonitor()` 14069b94acceSBarry Smith @*/ 1407d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetIterationNumber(SNES snes, PetscInt *iter) 1408d71ae5a4SJacob Faibussowitsch { 14093a40ed3dSBarry Smith PetscFunctionBegin; 14100700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 14114f572ea9SToby Isaac PetscAssertPointer(iter, 2); 14129b94acceSBarry Smith *iter = snes->iter; 14133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14149b94acceSBarry Smith } 141574679c65SBarry Smith 1416360c497dSPeter Brune /*@ 1417360c497dSPeter Brune SNESSetIterationNumber - Sets the current iteration number. 1418360c497dSPeter Brune 1419360c497dSPeter Brune Not Collective 1420360c497dSPeter Brune 1421d8d19677SJose E. Roman Input Parameters: 1422f6dfbefdSBarry Smith + snes - `SNES` context 1423a2b725a8SWilliam Gropp - iter - iteration number 1424360c497dSPeter Brune 1425360c497dSPeter Brune Level: developer 1426360c497dSPeter Brune 1427420bcc1bSBarry Smith Note: 1428420bcc1bSBarry Smith This should only be called inside a `SNES` nonlinear solver. 1429420bcc1bSBarry Smith 14301cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetLinearSolveIterations()` 1431360c497dSPeter Brune @*/ 1432d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetIterationNumber(SNES snes, PetscInt iter) 1433d71ae5a4SJacob Faibussowitsch { 1434360c497dSPeter Brune PetscFunctionBegin; 1435360c497dSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 14369566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes)); 1437360c497dSPeter Brune snes->iter = iter; 14389566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes)); 14393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1440360c497dSPeter Brune } 1441360c497dSPeter Brune 14429b94acceSBarry Smith /*@ 1443b850b91aSLisandro Dalcin SNESGetNonlinearStepFailures - Gets the number of unsuccessful steps 1444420bcc1bSBarry Smith attempted by the nonlinear solver in the current or most recent `SNESSolve()` . 14459b94acceSBarry Smith 1446c7afd0dbSLois Curfman McInnes Not Collective 1447c7afd0dbSLois Curfman McInnes 14489b94acceSBarry Smith Input Parameter: 1449f6dfbefdSBarry Smith . snes - `SNES` context 14509b94acceSBarry Smith 14519b94acceSBarry Smith Output Parameter: 14529b94acceSBarry Smith . nfails - number of unsuccessful steps attempted 14539b94acceSBarry Smith 1454dc4c0fb0SBarry Smith Level: intermediate 1455dc4c0fb0SBarry Smith 1456f6dfbefdSBarry Smith Note: 1457f6dfbefdSBarry Smith This counter is reset to zero for each successive call to `SNESSolve()`. 1458c96a6f78SLois Curfman McInnes 14591cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, 1460db781477SPatrick Sanan `SNESSetMaxNonlinearStepFailures()`, `SNESGetMaxNonlinearStepFailures()` 14619b94acceSBarry Smith @*/ 1462d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNonlinearStepFailures(SNES snes, PetscInt *nfails) 1463d71ae5a4SJacob Faibussowitsch { 14643a40ed3dSBarry Smith PetscFunctionBegin; 14650700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 14664f572ea9SToby Isaac PetscAssertPointer(nfails, 2); 146750ffb88aSMatthew Knepley *nfails = snes->numFailures; 14683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 146950ffb88aSMatthew Knepley } 147050ffb88aSMatthew Knepley 147150ffb88aSMatthew Knepley /*@ 1472b850b91aSLisandro Dalcin SNESSetMaxNonlinearStepFailures - Sets the maximum number of unsuccessful steps 1473420bcc1bSBarry Smith attempted by the nonlinear solver before it gives up and returns unconverged or generates an error 147450ffb88aSMatthew Knepley 147550ffb88aSMatthew Knepley Not Collective 147650ffb88aSMatthew Knepley 147750ffb88aSMatthew Knepley Input Parameters: 1478f6dfbefdSBarry Smith + snes - `SNES` context 147977e5a1f9SBarry Smith - maxFails - maximum of unsuccessful steps allowed, use `PETSC_UNLIMITED` to have no limit on the number of failures 148050ffb88aSMatthew Knepley 1481420bcc1bSBarry Smith Options Database Key: 1482420bcc1bSBarry Smith . -snes_max_fail <n> - maximum number of unsuccessful steps allowed 1483420bcc1bSBarry Smith 148450ffb88aSMatthew Knepley Level: intermediate 148550ffb88aSMatthew Knepley 1486420bcc1bSBarry Smith Developer Note: 1487420bcc1bSBarry Smith The options database key is wrong for this function name 1488420bcc1bSBarry Smith 14891cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, 1490db781477SPatrick Sanan `SNESGetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()` 149150ffb88aSMatthew Knepley @*/ 1492d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxNonlinearStepFailures(SNES snes, PetscInt maxFails) 1493d71ae5a4SJacob Faibussowitsch { 149450ffb88aSMatthew Knepley PetscFunctionBegin; 14950700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 149677e5a1f9SBarry Smith 149777e5a1f9SBarry Smith if (maxFails == PETSC_UNLIMITED) { 14981690c2aeSBarry Smith snes->maxFailures = PETSC_INT_MAX; 149977e5a1f9SBarry Smith } else { 150077e5a1f9SBarry Smith PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures"); 150150ffb88aSMatthew Knepley snes->maxFailures = maxFails; 150277e5a1f9SBarry Smith } 15033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 150450ffb88aSMatthew Knepley } 150550ffb88aSMatthew Knepley 150650ffb88aSMatthew Knepley /*@ 1507b850b91aSLisandro Dalcin SNESGetMaxNonlinearStepFailures - Gets the maximum number of unsuccessful steps 1508420bcc1bSBarry Smith attempted by the nonlinear solver before it gives up and returns unconverged or generates an error 150950ffb88aSMatthew Knepley 151050ffb88aSMatthew Knepley Not Collective 151150ffb88aSMatthew Knepley 151250ffb88aSMatthew Knepley Input Parameter: 151320f4b53cSBarry Smith . snes - `SNES` context 151450ffb88aSMatthew Knepley 151550ffb88aSMatthew Knepley Output Parameter: 151650ffb88aSMatthew Knepley . maxFails - maximum of unsuccessful steps 151750ffb88aSMatthew Knepley 151850ffb88aSMatthew Knepley Level: intermediate 151950ffb88aSMatthew Knepley 15201cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, 1521db781477SPatrick Sanan `SNESSetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()` 152250ffb88aSMatthew Knepley @*/ 1523d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxNonlinearStepFailures(SNES snes, PetscInt *maxFails) 1524d71ae5a4SJacob Faibussowitsch { 152550ffb88aSMatthew Knepley PetscFunctionBegin; 15260700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 15274f572ea9SToby Isaac PetscAssertPointer(maxFails, 2); 152850ffb88aSMatthew Knepley *maxFails = snes->maxFailures; 15293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15309b94acceSBarry Smith } 1531a847f771SSatish Balay 15322541af92SBarry Smith /*@ 15332541af92SBarry Smith SNESGetNumberFunctionEvals - Gets the number of user provided function evaluations 1534420bcc1bSBarry Smith done by the `SNES` object in the current or most recent `SNESSolve()` 15352541af92SBarry Smith 15362541af92SBarry Smith Not Collective 15372541af92SBarry Smith 15382541af92SBarry Smith Input Parameter: 1539f6dfbefdSBarry Smith . snes - `SNES` context 15402541af92SBarry Smith 15412541af92SBarry Smith Output Parameter: 15422541af92SBarry Smith . nfuncs - number of evaluations 15432541af92SBarry Smith 15442541af92SBarry Smith Level: intermediate 15452541af92SBarry Smith 1546f6dfbefdSBarry Smith Note: 1547f6dfbefdSBarry Smith Reset every time `SNESSolve()` is called unless `SNESSetCountersReset()` is used. 1548971e163fSPeter Brune 15491cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, `SNESSetCountersReset()` 15502541af92SBarry Smith @*/ 1551d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNumberFunctionEvals(SNES snes, PetscInt *nfuncs) 1552d71ae5a4SJacob Faibussowitsch { 15532541af92SBarry Smith PetscFunctionBegin; 15540700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 15554f572ea9SToby Isaac PetscAssertPointer(nfuncs, 2); 15562541af92SBarry Smith *nfuncs = snes->nfuncs; 15573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15582541af92SBarry Smith } 15592541af92SBarry Smith 15603d4c4710SBarry Smith /*@ 15613d4c4710SBarry Smith SNESGetLinearSolveFailures - Gets the number of failed (non-converged) 1562420bcc1bSBarry Smith linear solvers in the current or most recent `SNESSolve()` 15633d4c4710SBarry Smith 15643d4c4710SBarry Smith Not Collective 15653d4c4710SBarry Smith 15663d4c4710SBarry Smith Input Parameter: 1567f6dfbefdSBarry Smith . snes - `SNES` context 15683d4c4710SBarry Smith 15693d4c4710SBarry Smith Output Parameter: 15703d4c4710SBarry Smith . nfails - number of failed solves 15713d4c4710SBarry Smith 1572f6dfbefdSBarry Smith Options Database Key: 15739d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated 15749d85da0cSMatthew G. Knepley 1575f6dfbefdSBarry Smith Level: intermediate 1576f6dfbefdSBarry Smith 1577f6dfbefdSBarry Smith Note: 1578f6dfbefdSBarry Smith This counter is reset to zero for each successive call to `SNESSolve()`. 15793d4c4710SBarry Smith 15801cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()` 15813d4c4710SBarry Smith @*/ 1582d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveFailures(SNES snes, PetscInt *nfails) 1583d71ae5a4SJacob Faibussowitsch { 15843d4c4710SBarry Smith PetscFunctionBegin; 15850700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 15864f572ea9SToby Isaac PetscAssertPointer(nfails, 2); 15873d4c4710SBarry Smith *nfails = snes->numLinearSolveFailures; 15883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15893d4c4710SBarry Smith } 15903d4c4710SBarry Smith 15913d4c4710SBarry Smith /*@ 15923d4c4710SBarry Smith SNESSetMaxLinearSolveFailures - the number of failed linear solve attempts 1593f6dfbefdSBarry Smith allowed before `SNES` returns with a diverged reason of `SNES_DIVERGED_LINEAR_SOLVE` 15943d4c4710SBarry Smith 1595c3339decSBarry Smith Logically Collective 15963d4c4710SBarry Smith 15973d4c4710SBarry Smith Input Parameters: 1598f6dfbefdSBarry Smith + snes - `SNES` context 159977e5a1f9SBarry Smith - maxFails - maximum allowed linear solve failures, use `PETSC_UNLIMITED` to have no limit on the number of failures 16003d4c4710SBarry Smith 1601f6dfbefdSBarry Smith Options Database Key: 16029d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated 16039d85da0cSMatthew G. Knepley 1604dc4c0fb0SBarry Smith Level: intermediate 1605dc4c0fb0SBarry Smith 1606f6dfbefdSBarry Smith Note: 1607f6dfbefdSBarry Smith By default this is 0; that is `SNES` returns on the first failed linear solve 16083d4c4710SBarry Smith 1609420bcc1bSBarry Smith Developer Note: 1610420bcc1bSBarry Smith The options database key is wrong for this function name 1611420bcc1bSBarry Smith 16121cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()` 16133d4c4710SBarry Smith @*/ 1614d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxLinearSolveFailures(SNES snes, PetscInt maxFails) 1615d71ae5a4SJacob Faibussowitsch { 16163d4c4710SBarry Smith PetscFunctionBegin; 16170700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1618c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, maxFails, 2); 161977e5a1f9SBarry Smith 162077e5a1f9SBarry Smith if (maxFails == PETSC_UNLIMITED) { 16211690c2aeSBarry Smith snes->maxLinearSolveFailures = PETSC_INT_MAX; 162277e5a1f9SBarry Smith } else { 162377e5a1f9SBarry Smith PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures"); 16243d4c4710SBarry Smith snes->maxLinearSolveFailures = maxFails; 162577e5a1f9SBarry Smith } 16263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16273d4c4710SBarry Smith } 16283d4c4710SBarry Smith 16293d4c4710SBarry Smith /*@ 16303d4c4710SBarry Smith SNESGetMaxLinearSolveFailures - gets the maximum number of linear solve failures that 1631f6dfbefdSBarry Smith are allowed before `SNES` returns as unsuccessful 16323d4c4710SBarry Smith 16333d4c4710SBarry Smith Not Collective 16343d4c4710SBarry Smith 16353d4c4710SBarry Smith Input Parameter: 1636f6dfbefdSBarry Smith . snes - `SNES` context 16373d4c4710SBarry Smith 16383d4c4710SBarry Smith Output Parameter: 16393d4c4710SBarry Smith . maxFails - maximum of unsuccessful solves allowed 16403d4c4710SBarry Smith 16413d4c4710SBarry Smith Level: intermediate 16423d4c4710SBarry Smith 1643f6dfbefdSBarry Smith Note: 1644f6dfbefdSBarry Smith By default this is 1; that is `SNES` returns on the first failed linear solve 16453d4c4710SBarry Smith 16461cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, 16473d4c4710SBarry Smith @*/ 1648d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxLinearSolveFailures(SNES snes, PetscInt *maxFails) 1649d71ae5a4SJacob Faibussowitsch { 16503d4c4710SBarry Smith PetscFunctionBegin; 16510700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 16524f572ea9SToby Isaac PetscAssertPointer(maxFails, 2); 16533d4c4710SBarry Smith *maxFails = snes->maxLinearSolveFailures; 16543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16553d4c4710SBarry Smith } 16563d4c4710SBarry Smith 1657c96a6f78SLois Curfman McInnes /*@ 1658b850b91aSLisandro Dalcin SNESGetLinearSolveIterations - Gets the total number of linear iterations 1659420bcc1bSBarry Smith used by the nonlinear solver in the most recent `SNESSolve()` 1660c96a6f78SLois Curfman McInnes 1661c7afd0dbSLois Curfman McInnes Not Collective 1662c7afd0dbSLois Curfman McInnes 1663c96a6f78SLois Curfman McInnes Input Parameter: 1664f6dfbefdSBarry Smith . snes - `SNES` context 1665c96a6f78SLois Curfman McInnes 1666c96a6f78SLois Curfman McInnes Output Parameter: 1667c96a6f78SLois Curfman McInnes . lits - number of linear iterations 1668c96a6f78SLois Curfman McInnes 1669dc4c0fb0SBarry Smith Level: intermediate 1670dc4c0fb0SBarry Smith 1671c96a6f78SLois Curfman McInnes Notes: 1672f6dfbefdSBarry Smith This counter is reset to zero for each successive call to `SNESSolve()` unless `SNESSetCountersReset()` is used. 1673c96a6f78SLois Curfman McInnes 1674f6dfbefdSBarry 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 1675f6dfbefdSBarry Smith then call `KSPGetIterationNumber()` after the failed solve. 1676010be392SBarry Smith 16771cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetIterationNumber()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESSetCountersReset()` 1678c96a6f78SLois Curfman McInnes @*/ 1679d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveIterations(SNES snes, PetscInt *lits) 1680d71ae5a4SJacob Faibussowitsch { 16813a40ed3dSBarry Smith PetscFunctionBegin; 16820700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 16834f572ea9SToby Isaac PetscAssertPointer(lits, 2); 1684c96a6f78SLois Curfman McInnes *lits = snes->linear_its; 16853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1686c96a6f78SLois Curfman McInnes } 1687c96a6f78SLois Curfman McInnes 1688971e163fSPeter Brune /*@ 1689971e163fSPeter Brune SNESSetCountersReset - Sets whether or not the counters for linear iterations and function evaluations 1690f6dfbefdSBarry Smith are reset every time `SNESSolve()` is called. 1691971e163fSPeter Brune 1692c3339decSBarry Smith Logically Collective 1693971e163fSPeter Brune 1694d8d19677SJose E. Roman Input Parameters: 1695f6dfbefdSBarry Smith + snes - `SNES` context 1696f6dfbefdSBarry Smith - reset - whether to reset the counters or not, defaults to `PETSC_TRUE` 1697971e163fSPeter Brune 1698971e163fSPeter Brune Level: developer 1699971e163fSPeter Brune 17001cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()` 1701971e163fSPeter Brune @*/ 1702d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCountersReset(SNES snes, PetscBool reset) 1703d71ae5a4SJacob Faibussowitsch { 1704971e163fSPeter Brune PetscFunctionBegin; 1705971e163fSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1706971e163fSPeter Brune PetscValidLogicalCollectiveBool(snes, reset, 2); 1707971e163fSPeter Brune snes->counters_reset = reset; 17083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1709971e163fSPeter Brune } 1710971e163fSPeter Brune 17112999313aSBarry Smith /*@ 171212b1dd1aSStefano Zampini SNESResetCounters - Reset counters for linear iterations and function evaluations. 171312b1dd1aSStefano Zampini 171412b1dd1aSStefano Zampini Logically Collective 171512b1dd1aSStefano Zampini 171612b1dd1aSStefano Zampini Input Parameters: 171712b1dd1aSStefano Zampini . snes - `SNES` context 171812b1dd1aSStefano Zampini 171912b1dd1aSStefano Zampini Level: developer 172012b1dd1aSStefano Zampini 172112b1dd1aSStefano Zampini Note: 172212b1dd1aSStefano Zampini It honors the flag set with `SNESSetCountersReset()` 172312b1dd1aSStefano Zampini 172412b1dd1aSStefano Zampini .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()` 172512b1dd1aSStefano Zampini @*/ 172612b1dd1aSStefano Zampini PetscErrorCode SNESResetCounters(SNES snes) 172712b1dd1aSStefano Zampini { 172812b1dd1aSStefano Zampini PetscFunctionBegin; 172912b1dd1aSStefano Zampini PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 173012b1dd1aSStefano Zampini if (snes->counters_reset) { 173112b1dd1aSStefano Zampini snes->nfuncs = 0; 173212b1dd1aSStefano Zampini snes->linear_its = 0; 173312b1dd1aSStefano Zampini snes->numFailures = 0; 173412b1dd1aSStefano Zampini } 173512b1dd1aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 173612b1dd1aSStefano Zampini } 173712b1dd1aSStefano Zampini 173812b1dd1aSStefano Zampini /*@ 1739f6dfbefdSBarry Smith SNESSetKSP - Sets a `KSP` context for the `SNES` object to use 17402999313aSBarry Smith 1741420bcc1bSBarry Smith Not Collective, but the `SNES` and `KSP` objects must live on the same `MPI_Comm` 17422999313aSBarry Smith 17432999313aSBarry Smith Input Parameters: 1744f6dfbefdSBarry Smith + snes - the `SNES` context 1745f6dfbefdSBarry Smith - ksp - the `KSP` context 17462999313aSBarry Smith 1747dc4c0fb0SBarry Smith Level: developer 1748dc4c0fb0SBarry Smith 17492999313aSBarry Smith Notes: 1750f6dfbefdSBarry Smith The `SNES` object already has its `KSP` object, you can obtain with `SNESGetKSP()` 17512999313aSBarry Smith so this routine is rarely needed. 17522999313aSBarry Smith 1753f6dfbefdSBarry Smith The `KSP` object that is already in the `SNES` object has its reference count 1754420bcc1bSBarry Smith decreased by one when this is called. 17552999313aSBarry Smith 175642747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `KSP`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()` 17572999313aSBarry Smith @*/ 1758d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetKSP(SNES snes, KSP ksp) 1759d71ae5a4SJacob Faibussowitsch { 17602999313aSBarry Smith PetscFunctionBegin; 17610700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 17620700a824SBarry Smith PetscValidHeaderSpecific(ksp, KSP_CLASSID, 2); 17632999313aSBarry Smith PetscCheckSameComm(snes, 1, ksp, 2); 17649566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)ksp)); 17659566063dSJacob Faibussowitsch if (snes->ksp) PetscCall(PetscObjectDereference((PetscObject)snes->ksp)); 17662999313aSBarry Smith snes->ksp = ksp; 17673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17682999313aSBarry Smith } 17692999313aSBarry Smith 177052baeb72SSatish Balay /*@ 177177e5a1f9SBarry Smith SNESParametersInitialize - Sets all the parameters in `snes` to their default value (when `SNESCreate()` was called) if they 177277e5a1f9SBarry Smith currently contain default values 177377e5a1f9SBarry Smith 177477e5a1f9SBarry Smith Collective 177577e5a1f9SBarry Smith 177677e5a1f9SBarry Smith Input Parameter: 177777e5a1f9SBarry Smith . snes - the `SNES` object 177877e5a1f9SBarry Smith 177977e5a1f9SBarry Smith Level: developer 178077e5a1f9SBarry Smith 178177e5a1f9SBarry Smith Developer Note: 178277e5a1f9SBarry Smith This is called by all the `SNESCreate_XXX()` routines. 178377e5a1f9SBarry Smith 178477e5a1f9SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`, 178577e5a1f9SBarry Smith `PetscObjectParameterSetDefault()` 178677e5a1f9SBarry Smith @*/ 178777e5a1f9SBarry Smith PetscErrorCode SNESParametersInitialize(SNES snes) 178877e5a1f9SBarry Smith { 178977e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, max_its, 50); 179077e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, max_funcs, 10000); 179177e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, rtol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8); 179277e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, abstol, PetscDefined(USE_REAL_SINGLE) ? 1.e-25 : 1.e-50); 179377e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, stol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8); 179477e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, divtol, 1.e4); 179577e5a1f9SBarry Smith return PETSC_SUCCESS; 179677e5a1f9SBarry Smith } 179777e5a1f9SBarry Smith 179877e5a1f9SBarry Smith /*@ 1799dc4c0fb0SBarry Smith SNESCreate - Creates a nonlinear solver context used to manage a set of nonlinear solves 18009b94acceSBarry Smith 1801d083f849SBarry Smith Collective 1802c7afd0dbSLois Curfman McInnes 1803f6dfbefdSBarry Smith Input Parameter: 1804906ed7ccSBarry Smith . comm - MPI communicator 18059b94acceSBarry Smith 18069b94acceSBarry Smith Output Parameter: 180720f4b53cSBarry Smith . outsnes - the new `SNES` context 18089b94acceSBarry Smith 1809c7afd0dbSLois Curfman McInnes Options Database Keys: 18107addb90fSBarry Smith + -snes_mf - Activates default matrix-free Jacobian-vector products, and no matrix to construct a preconditioner 18117addb90fSBarry Smith . -snes_mf_operator - Activates default matrix-free Jacobian-vector products, and a user-provided matrix as set by `SNESSetJacobian()` 1812dc4c0fb0SBarry Smith . -snes_fd_coloring - uses a relative fast computation of the Jacobian using finite differences and a graph coloring 1813c7afd0dbSLois Curfman McInnes - -snes_fd - Uses (slow!) finite differences to compute Jacobian 1814c1f60f51SBarry Smith 181536851e7fSLois Curfman McInnes Level: beginner 181636851e7fSLois Curfman McInnes 181795452b02SPatrick Sanan Developer Notes: 1818f6dfbefdSBarry Smith `SNES` always creates a `KSP` object even though many `SNES` methods do not use it. This is 1819efd4aadfSBarry Smith unfortunate and should be fixed at some point. The flag snes->usesksp indicates if the 1820f6dfbefdSBarry Smith particular method does use `KSP` and regulates if the information about the `KSP` is printed 1821f6dfbefdSBarry Smith in `SNESView()`. 1822efd4aadfSBarry Smith 1823f6dfbefdSBarry Smith `TSSetFromOptions()` does call `SNESSetFromOptions()` which can lead to users being confused 1824f6dfbefdSBarry Smith by help messages about meaningless `SNES` options. 1825f6dfbefdSBarry Smith 18267addb90fSBarry Smith `SNES` always creates the `snes->kspconvctx` even though it is used by only one type. This should be fixed. 1827efd4aadfSBarry Smith 1828e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()` 18299b94acceSBarry Smith @*/ 1830d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESCreate(MPI_Comm comm, SNES *outsnes) 1831d71ae5a4SJacob Faibussowitsch { 18329b94acceSBarry Smith SNES snes; 1833fa9f3622SBarry Smith SNESKSPEW *kctx; 183437fcc0dbSBarry Smith 18353a40ed3dSBarry Smith PetscFunctionBegin; 18364f572ea9SToby Isaac PetscAssertPointer(outsnes, 2); 18379566063dSJacob Faibussowitsch PetscCall(SNESInitializePackage()); 18388ba1e511SMatthew Knepley 18399566063dSJacob Faibussowitsch PetscCall(PetscHeaderCreate(snes, SNES_CLASSID, "SNES", "Nonlinear solver", "SNES", comm, SNESDestroy, SNESView)); 18408d359177SBarry Smith snes->ops->converged = SNESConvergedDefault; 18412c155ee1SBarry Smith snes->usesksp = PETSC_TRUE; 18429b94acceSBarry Smith snes->norm = 0.0; 1843c1e67a49SFande Kong snes->xnorm = 0.0; 1844c1e67a49SFande Kong snes->ynorm = 0.0; 1845365a6726SPeter Brune snes->normschedule = SNES_NORM_ALWAYS; 18466c67d002SPeter Brune snes->functype = SNES_FUNCTION_DEFAULT; 1847b4874afaSBarry Smith snes->ttol = 0.0; 184877e5a1f9SBarry Smith 1849e37c518bSBarry Smith snes->rnorm0 = 0; 18509b94acceSBarry Smith snes->nfuncs = 0; 185150ffb88aSMatthew Knepley snes->numFailures = 0; 185250ffb88aSMatthew Knepley snes->maxFailures = 1; 18537a00f4a9SLois Curfman McInnes snes->linear_its = 0; 1854e35cf81dSBarry Smith snes->lagjacobian = 1; 185537ec4e1aSPeter Brune snes->jac_iter = 0; 185637ec4e1aSPeter Brune snes->lagjac_persist = PETSC_FALSE; 1857a8054027SBarry Smith snes->lagpreconditioner = 1; 185837ec4e1aSPeter Brune snes->pre_iter = 0; 185937ec4e1aSPeter Brune snes->lagpre_persist = PETSC_FALSE; 1860639f9d9dSBarry Smith snes->numbermonitors = 0; 1861c4421ceaSFande Kong snes->numberreasonviews = 0; 18629e5d0892SLisandro Dalcin snes->data = NULL; 18634dc4c822SBarry Smith snes->setupcalled = PETSC_FALSE; 1864186905e3SBarry Smith snes->ksp_ewconv = PETSC_FALSE; 18656f24a144SLois Curfman McInnes snes->nwork = 0; 18669e5d0892SLisandro Dalcin snes->work = NULL; 186758c9b817SLisandro Dalcin snes->nvwork = 0; 18689e5d0892SLisandro Dalcin snes->vwork = NULL; 1869758f92a0SBarry Smith snes->conv_hist_len = 0; 1870758f92a0SBarry Smith snes->conv_hist_max = 0; 18710298fd71SBarry Smith snes->conv_hist = NULL; 18720298fd71SBarry Smith snes->conv_hist_its = NULL; 1873758f92a0SBarry Smith snes->conv_hist_reset = PETSC_TRUE; 1874971e163fSPeter Brune snes->counters_reset = PETSC_TRUE; 1875e4ed7901SPeter Brune snes->vec_func_init_set = PETSC_FALSE; 1876184914b5SBarry Smith snes->reason = SNES_CONVERGED_ITERATING; 1877efd4aadfSBarry Smith snes->npcside = PC_RIGHT; 1878b3cd9a81SMatthew G. Knepley snes->setfromoptionscalled = 0; 1879c40d0f55SPeter Brune 1880d8f46077SPeter Brune snes->mf = PETSC_FALSE; 1881d8f46077SPeter Brune snes->mf_operator = PETSC_FALSE; 1882d8f46077SPeter Brune snes->mf_version = 1; 1883d8f46077SPeter Brune 18843d4c4710SBarry Smith snes->numLinearSolveFailures = 0; 18853d4c4710SBarry Smith snes->maxLinearSolveFailures = 1; 18863d4c4710SBarry Smith 1887349187a7SBarry Smith snes->vizerotolerance = 1.e-8; 188876bd3646SJed Brown snes->checkjacdomainerror = PetscDefined(USE_DEBUG) ? PETSC_TRUE : PETSC_FALSE; 1889349187a7SBarry Smith 18904fc747eaSLawrence Mitchell /* Set this to true if the implementation of SNESSolve_XXX does compute the residual at the final solution. */ 18914fc747eaSLawrence Mitchell snes->alwayscomputesfinalresidual = PETSC_FALSE; 18924fc747eaSLawrence Mitchell 18939b94acceSBarry Smith /* Create context to compute Eisenstat-Walker relative tolerance for KSP */ 18944dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&kctx)); 1895f5af7f23SKarl Rupp 1896835f2295SStefano Zampini snes->kspconvctx = kctx; 18979b94acceSBarry Smith kctx->version = 2; 18980f0abf79SStefano Zampini kctx->rtol_0 = 0.3; /* Eisenstat and Walker suggest rtol_0=.5, but 18999b94acceSBarry Smith this was too large for some test cases */ 190075567043SBarry Smith kctx->rtol_last = 0.0; 19010f0abf79SStefano Zampini kctx->rtol_max = 0.9; 19029b94acceSBarry Smith kctx->gamma = 1.0; 19030f0abf79SStefano Zampini kctx->alpha = 0.5 * (1.0 + PetscSqrtReal(5.0)); 190471f87433Sdalcinl kctx->alpha2 = kctx->alpha; 19050f0abf79SStefano Zampini kctx->threshold = 0.1; 190675567043SBarry Smith kctx->lresid_last = 0.0; 190775567043SBarry Smith kctx->norm_last = 0.0; 19089b94acceSBarry Smith 19090f0abf79SStefano Zampini kctx->rk_last = 0.0; 19100f0abf79SStefano Zampini kctx->rk_last_2 = 0.0; 19110f0abf79SStefano Zampini kctx->rtol_last_2 = 0.0; 19120f0abf79SStefano Zampini kctx->v4_p1 = 0.1; 19130f0abf79SStefano Zampini kctx->v4_p2 = 0.4; 19140f0abf79SStefano Zampini kctx->v4_p3 = 0.7; 19150f0abf79SStefano Zampini kctx->v4_m1 = 0.8; 19160f0abf79SStefano Zampini kctx->v4_m2 = 0.5; 19170f0abf79SStefano Zampini kctx->v4_m3 = 0.1; 19180f0abf79SStefano Zampini kctx->v4_m4 = 0.5; 19190f0abf79SStefano Zampini 1920b50c806fSBarry Smith PetscCall(SNESParametersInitialize(snes)); 19219b94acceSBarry Smith *outsnes = snes; 19223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19239b94acceSBarry Smith } 19249b94acceSBarry Smith 19259b94acceSBarry Smith /*@C 19269b94acceSBarry Smith SNESSetFunction - Sets the function evaluation routine and function 1927f6dfbefdSBarry Smith vector for use by the `SNES` routines in solving systems of nonlinear 19289b94acceSBarry Smith equations. 19299b94acceSBarry Smith 1930c3339decSBarry Smith Logically Collective 1931fee21e36SBarry Smith 1932c7afd0dbSLois Curfman McInnes Input Parameters: 1933f6dfbefdSBarry Smith + snes - the `SNES` context 1934dc4c0fb0SBarry Smith . r - vector to store function values, may be `NULL` 19358434afd1SBarry Smith . f - function evaluation routine; for calling sequence see `SNESFunctionFn` 1936c7afd0dbSLois Curfman McInnes - ctx - [optional] user-defined context for private data for the 1937dc4c0fb0SBarry Smith function evaluation routine (may be `NULL`) 19389b94acceSBarry Smith 193936851e7fSLois Curfman McInnes Level: beginner 194036851e7fSLois Curfman McInnes 19418434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetPicard()`, `SNESFunctionFn` 19429b94acceSBarry Smith @*/ 19438434afd1SBarry Smith PetscErrorCode SNESSetFunction(SNES snes, Vec r, SNESFunctionFn *f, void *ctx) 1944d71ae5a4SJacob Faibussowitsch { 19456cab3a1bSJed Brown DM dm; 19466cab3a1bSJed Brown 19473a40ed3dSBarry Smith PetscFunctionBegin; 19480700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1949d2a683ecSLisandro Dalcin if (r) { 1950d2a683ecSLisandro Dalcin PetscValidHeaderSpecific(r, VEC_CLASSID, 2); 1951d2a683ecSLisandro Dalcin PetscCheckSameComm(snes, 1, r, 2); 19529566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)r)); 19539566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_func)); 195485385478SLisandro Dalcin snes->vec_func = r; 1955d2a683ecSLisandro Dalcin } 19569566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 19579566063dSJacob Faibussowitsch PetscCall(DMSNESSetFunction(dm, f, ctx)); 195848a46eb9SPierre Jolivet if (f == SNESPicardComputeFunction) PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx)); 19593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19609b94acceSBarry Smith } 19619b94acceSBarry Smith 1962e4ed7901SPeter Brune /*@C 19630b4db180SJacob Faibussowitsch SNESSetInitialFunction - Set an already computed function evaluation at the initial guess to be reused by `SNESSolve()`. 1964e4ed7901SPeter Brune 1965c3339decSBarry Smith Logically Collective 1966e4ed7901SPeter Brune 1967e4ed7901SPeter Brune Input Parameters: 1968f6dfbefdSBarry Smith + snes - the `SNES` context 1969e4ed7901SPeter Brune - f - vector to store function value 1970e4ed7901SPeter Brune 1971dc4c0fb0SBarry Smith Level: developer 1972dc4c0fb0SBarry Smith 1973e4ed7901SPeter Brune Notes: 1974e4ed7901SPeter Brune This should not be modified during the solution procedure. 1975e4ed7901SPeter Brune 1976f6dfbefdSBarry Smith This is used extensively in the `SNESFAS` hierarchy and in nonlinear preconditioning. 1977e4ed7901SPeter Brune 19781cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetInitialFunctionNorm()` 1979e4ed7901SPeter Brune @*/ 1980d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetInitialFunction(SNES snes, Vec f) 1981d71ae5a4SJacob Faibussowitsch { 1982e4ed7901SPeter Brune Vec vec_func; 1983e4ed7901SPeter Brune 1984e4ed7901SPeter Brune PetscFunctionBegin; 1985e4ed7901SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1986e4ed7901SPeter Brune PetscValidHeaderSpecific(f, VEC_CLASSID, 2); 1987e4ed7901SPeter Brune PetscCheckSameComm(snes, 1, f, 2); 1988efd4aadfSBarry Smith if (snes->npcside == PC_LEFT && snes->functype == SNES_FUNCTION_PRECONDITIONED) { 1989902f982fSPeter Brune snes->vec_func_init_set = PETSC_FALSE; 19903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1991902f982fSPeter Brune } 19929566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &vec_func, NULL, NULL)); 19939566063dSJacob Faibussowitsch PetscCall(VecCopy(f, vec_func)); 1994f5af7f23SKarl Rupp 1995217b9c2eSPeter Brune snes->vec_func_init_set = PETSC_TRUE; 19963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1997e4ed7901SPeter Brune } 1998e4ed7901SPeter Brune 1999534ebe21SPeter Brune /*@ 2000f6dfbefdSBarry Smith SNESSetNormSchedule - Sets the `SNESNormSchedule` used in convergence and monitoring 2001f6dfbefdSBarry Smith of the `SNES` method, when norms are computed in the solving process 2002534ebe21SPeter Brune 2003c3339decSBarry Smith Logically Collective 2004534ebe21SPeter Brune 2005534ebe21SPeter Brune Input Parameters: 2006f6dfbefdSBarry Smith + snes - the `SNES` context 2007365a6726SPeter Brune - normschedule - the frequency of norm computation 2008534ebe21SPeter Brune 2009517f1916SMatthew G. Knepley Options Database Key: 201067b8a455SSatish Balay . -snes_norm_schedule <none, always, initialonly, finalonly, initialfinalonly> - set the schedule 2011517f1916SMatthew G. Knepley 2012dc4c0fb0SBarry Smith Level: advanced 2013dc4c0fb0SBarry Smith 2014534ebe21SPeter Brune Notes: 2015f6dfbefdSBarry Smith Only certain `SNES` methods support certain `SNESNormSchedules`. Most require evaluation 2016534ebe21SPeter Brune of the nonlinear function and the taking of its norm at every iteration to 2017534ebe21SPeter Brune even ensure convergence at all. However, methods such as custom Gauss-Seidel methods 2018f6dfbefdSBarry Smith `SNESNGS` and the like do not require the norm of the function to be computed, and therefore 2019534ebe21SPeter Brune may either be monitored for convergence or not. As these are often used as nonlinear 2020534ebe21SPeter Brune preconditioners, monitoring the norm of their error is not a useful enterprise within 2021534ebe21SPeter Brune their solution. 2022534ebe21SPeter Brune 2023e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNESNormSchedule`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()` 2024534ebe21SPeter Brune @*/ 2025d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNormSchedule(SNES snes, SNESNormSchedule normschedule) 2026d71ae5a4SJacob Faibussowitsch { 2027534ebe21SPeter Brune PetscFunctionBegin; 2028534ebe21SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2029365a6726SPeter Brune snes->normschedule = normschedule; 20303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2031534ebe21SPeter Brune } 2032534ebe21SPeter Brune 2033534ebe21SPeter Brune /*@ 2034f6dfbefdSBarry Smith SNESGetNormSchedule - Gets the `SNESNormSchedule` used in convergence and monitoring 2035f6dfbefdSBarry Smith of the `SNES` method. 2036534ebe21SPeter Brune 2037c3339decSBarry Smith Logically Collective 2038534ebe21SPeter Brune 2039534ebe21SPeter Brune Input Parameters: 2040f6dfbefdSBarry Smith + snes - the `SNES` context 2041365a6726SPeter Brune - normschedule - the type of the norm used 2042534ebe21SPeter Brune 2043534ebe21SPeter Brune Level: advanced 2044534ebe21SPeter Brune 20451cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 2046534ebe21SPeter Brune @*/ 2047d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNormSchedule(SNES snes, SNESNormSchedule *normschedule) 2048d71ae5a4SJacob Faibussowitsch { 2049534ebe21SPeter Brune PetscFunctionBegin; 2050534ebe21SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2051365a6726SPeter Brune *normschedule = snes->normschedule; 20523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2053534ebe21SPeter Brune } 2054534ebe21SPeter Brune 2055c5ce4427SMatthew G. Knepley /*@ 2056c5ce4427SMatthew G. Knepley SNESSetFunctionNorm - Sets the last computed residual norm. 2057c5ce4427SMatthew G. Knepley 2058c3339decSBarry Smith Logically Collective 2059c5ce4427SMatthew G. Knepley 2060c5ce4427SMatthew G. Knepley Input Parameters: 2061f6dfbefdSBarry Smith + snes - the `SNES` context 2062f6dfbefdSBarry Smith - norm - the value of the norm 2063c5ce4427SMatthew G. Knepley 2064c5ce4427SMatthew G. Knepley Level: developer 2065c5ce4427SMatthew G. Knepley 20661cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 2067c5ce4427SMatthew G. Knepley @*/ 2068d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionNorm(SNES snes, PetscReal norm) 2069d71ae5a4SJacob Faibussowitsch { 2070c5ce4427SMatthew G. Knepley PetscFunctionBegin; 2071c5ce4427SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2072c5ce4427SMatthew G. Knepley snes->norm = norm; 20733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2074c5ce4427SMatthew G. Knepley } 2075c5ce4427SMatthew G. Knepley 2076c5ce4427SMatthew G. Knepley /*@ 2077c5ce4427SMatthew G. Knepley SNESGetFunctionNorm - Gets the last computed norm of the residual 2078c5ce4427SMatthew G. Knepley 2079c5ce4427SMatthew G. Knepley Not Collective 2080c5ce4427SMatthew G. Knepley 2081c5ce4427SMatthew G. Knepley Input Parameter: 2082f6dfbefdSBarry Smith . snes - the `SNES` context 2083c5ce4427SMatthew G. Knepley 2084c5ce4427SMatthew G. Knepley Output Parameter: 2085c5ce4427SMatthew G. Knepley . norm - the last computed residual norm 2086c5ce4427SMatthew G. Knepley 2087c5ce4427SMatthew G. Knepley Level: developer 2088c5ce4427SMatthew G. Knepley 20891cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 2090c5ce4427SMatthew G. Knepley @*/ 2091d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionNorm(SNES snes, PetscReal *norm) 2092d71ae5a4SJacob Faibussowitsch { 2093c5ce4427SMatthew G. Knepley PetscFunctionBegin; 2094c5ce4427SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 20954f572ea9SToby Isaac PetscAssertPointer(norm, 2); 2096c5ce4427SMatthew G. Knepley *norm = snes->norm; 20973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2098c5ce4427SMatthew G. Knepley } 2099c5ce4427SMatthew G. Knepley 2100c1e67a49SFande Kong /*@ 2101f6dfbefdSBarry Smith SNESGetUpdateNorm - Gets the last computed norm of the solution update 2102c1e67a49SFande Kong 2103c1e67a49SFande Kong Not Collective 2104c1e67a49SFande Kong 2105c1e67a49SFande Kong Input Parameter: 2106f6dfbefdSBarry Smith . snes - the `SNES` context 2107c1e67a49SFande Kong 2108c1e67a49SFande Kong Output Parameter: 2109c1e67a49SFande Kong . ynorm - the last computed update norm 2110c1e67a49SFande Kong 2111c1e67a49SFande Kong Level: developer 2112c1e67a49SFande Kong 2113f6dfbefdSBarry Smith Note: 2114f6dfbefdSBarry Smith The new solution is the current solution plus the update, so this norm is an indication of the size of the update 2115f6dfbefdSBarry Smith 21161cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()` 2117c1e67a49SFande Kong @*/ 2118d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUpdateNorm(SNES snes, PetscReal *ynorm) 2119d71ae5a4SJacob Faibussowitsch { 2120c1e67a49SFande Kong PetscFunctionBegin; 2121c1e67a49SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 21224f572ea9SToby Isaac PetscAssertPointer(ynorm, 2); 2123c1e67a49SFande Kong *ynorm = snes->ynorm; 21243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2125c1e67a49SFande Kong } 2126c1e67a49SFande Kong 2127c1e67a49SFande Kong /*@ 21284591eaf2SFande Kong SNESGetSolutionNorm - Gets the last computed norm of the solution 2129c1e67a49SFande Kong 2130c1e67a49SFande Kong Not Collective 2131c1e67a49SFande Kong 2132c1e67a49SFande Kong Input Parameter: 2133f6dfbefdSBarry Smith . snes - the `SNES` context 2134c1e67a49SFande Kong 2135c1e67a49SFande Kong Output Parameter: 2136c1e67a49SFande Kong . xnorm - the last computed solution norm 2137c1e67a49SFande Kong 2138c1e67a49SFande Kong Level: developer 2139c1e67a49SFande Kong 21401cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`, `SNESGetUpdateNorm()` 2141c1e67a49SFande Kong @*/ 2142d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionNorm(SNES snes, PetscReal *xnorm) 2143d71ae5a4SJacob Faibussowitsch { 2144c1e67a49SFande Kong PetscFunctionBegin; 2145c1e67a49SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 21464f572ea9SToby Isaac PetscAssertPointer(xnorm, 2); 2147c1e67a49SFande Kong *xnorm = snes->xnorm; 21483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2149c1e67a49SFande Kong } 2150c1e67a49SFande Kong 2151cc4c1da9SBarry Smith /*@ 2152f6dfbefdSBarry Smith SNESSetFunctionType - Sets the `SNESFunctionType` 2153f6dfbefdSBarry Smith of the `SNES` method. 215447073ea2SPeter Brune 2155c3339decSBarry Smith Logically Collective 215647073ea2SPeter Brune 215747073ea2SPeter Brune Input Parameters: 2158f6dfbefdSBarry Smith + snes - the `SNES` context 2159f6dfbefdSBarry Smith - type - the function type 216047073ea2SPeter Brune 216147073ea2SPeter Brune Level: developer 216247073ea2SPeter Brune 2163420bcc1bSBarry Smith Values of the function type\: 2164f6dfbefdSBarry Smith + `SNES_FUNCTION_DEFAULT` - the default for the given `SNESType` 2165f6dfbefdSBarry Smith . `SNES_FUNCTION_UNPRECONDITIONED` - an unpreconditioned function evaluation (this is the function provided with `SNESSetFunction()` 2166f6dfbefdSBarry Smith - `SNES_FUNCTION_PRECONDITIONED` - a transformation of the function provided with `SNESSetFunction()` 2167f6dfbefdSBarry Smith 2168420bcc1bSBarry Smith Note: 2169f6dfbefdSBarry Smith Different `SNESType`s use this value in different ways 2170f6dfbefdSBarry Smith 21711cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFunctionType`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 217247073ea2SPeter Brune @*/ 2173d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionType(SNES snes, SNESFunctionType type) 2174d71ae5a4SJacob Faibussowitsch { 217547073ea2SPeter Brune PetscFunctionBegin; 217647073ea2SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 217747073ea2SPeter Brune snes->functype = type; 21783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 217947073ea2SPeter Brune } 218047073ea2SPeter Brune 2181cc4c1da9SBarry Smith /*@ 2182f6dfbefdSBarry Smith SNESGetFunctionType - Gets the `SNESFunctionType` used in convergence and monitoring set with `SNESSetFunctionType()` 218347073ea2SPeter Brune of the SNES method. 218447073ea2SPeter Brune 2185c3339decSBarry Smith Logically Collective 218647073ea2SPeter Brune 218747073ea2SPeter Brune Input Parameters: 2188f6dfbefdSBarry Smith + snes - the `SNES` context 2189f6dfbefdSBarry Smith - type - the type of the function evaluation, see `SNESSetFunctionType()` 219047073ea2SPeter Brune 219147073ea2SPeter Brune Level: advanced 219247073ea2SPeter Brune 21931cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetFunctionType()`, `SNESFunctionType`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 219447073ea2SPeter Brune @*/ 2195d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionType(SNES snes, SNESFunctionType *type) 2196d71ae5a4SJacob Faibussowitsch { 219747073ea2SPeter Brune PetscFunctionBegin; 219847073ea2SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 219947073ea2SPeter Brune *type = snes->functype; 22003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2201534ebe21SPeter Brune } 2202534ebe21SPeter Brune 2203c79ef259SPeter Brune /*@C 2204be95d8f1SBarry Smith SNESSetNGS - Sets the user nonlinear Gauss-Seidel routine for 2205c79ef259SPeter Brune use with composed nonlinear solvers. 2206c79ef259SPeter Brune 2207c79ef259SPeter Brune Input Parameters: 22089bcc50f1SBarry Smith + snes - the `SNES` context, usually of the `SNESType` `SNESNGS` 22098434afd1SBarry Smith . f - function evaluation routine to apply Gauss-Seidel, see `SNESNGSFn` for calling sequence 221077e5a1f9SBarry Smith - ctx - [optional] user-defined context for private data for the smoother evaluation routine (may be `NULL`) 2211c79ef259SPeter Brune 2212dc4c0fb0SBarry Smith Level: intermediate 2213dc4c0fb0SBarry Smith 2214f6dfbefdSBarry Smith Note: 2215f6dfbefdSBarry Smith The `SNESNGS` routines are used by the composed nonlinear solver to generate 2216f6dfbefdSBarry Smith a problem appropriate update to the solution, particularly `SNESFAS`. 2217c79ef259SPeter Brune 22188434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGS`, `SNESGetNGS()`, `SNESNCG`, `SNESGetFunction()`, `SNESComputeNGS()`, `SNESNGSFn` 2219c79ef259SPeter Brune @*/ 22208434afd1SBarry Smith PetscErrorCode SNESSetNGS(SNES snes, SNESNGSFn *f, void *ctx) 2221d71ae5a4SJacob Faibussowitsch { 22226cab3a1bSJed Brown DM dm; 22236cab3a1bSJed Brown 2224646217ecSPeter Brune PetscFunctionBegin; 22256cab3a1bSJed Brown PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 22269566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 22279566063dSJacob Faibussowitsch PetscCall(DMSNESSetNGS(dm, f, ctx)); 22283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2229646217ecSPeter Brune } 2230646217ecSPeter Brune 2231bbc1464cSBarry Smith /* 2232bbc1464cSBarry Smith This is used for -snes_mf_operator; it uses a duplicate of snes->jacobian_pre because snes->jacobian_pre cannot be 2233bbc1464cSBarry Smith changed during the KSPSolve() 2234bbc1464cSBarry Smith */ 2235d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeMFFunction(SNES snes, Vec x, Vec f, void *ctx) 2236d71ae5a4SJacob Faibussowitsch { 2237bbc1464cSBarry Smith DM dm; 2238bbc1464cSBarry Smith DMSNES sdm; 2239bbc1464cSBarry Smith 2240bbc1464cSBarry Smith PetscFunctionBegin; 22419566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 22429566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 2243bbc1464cSBarry Smith /* A(x)*x - b(x) */ 2244bbc1464cSBarry Smith if (sdm->ops->computepfunction) { 2245792fecdfSBarry Smith PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx)); 22469566063dSJacob Faibussowitsch PetscCall(VecScale(f, -1.0)); 22470df40c35SBarry Smith /* Cannot share nonzero pattern because of the possible use of SNESComputeJacobianDefault() */ 2248ef1023bdSBarry Smith if (!snes->picard) PetscCall(MatDuplicate(snes->jacobian_pre, MAT_DO_NOT_COPY_VALUES, &snes->picard)); 2249792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx)); 22509566063dSJacob Faibussowitsch PetscCall(MatMultAdd(snes->picard, x, f, f)); 2251bbc1464cSBarry Smith } else { 2252792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx)); 22539566063dSJacob Faibussowitsch PetscCall(MatMult(snes->picard, x, f)); 2254bbc1464cSBarry Smith } 22553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2256bbc1464cSBarry Smith } 2257bbc1464cSBarry Smith 2258d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeFunction(SNES snes, Vec x, Vec f, void *ctx) 2259d71ae5a4SJacob Faibussowitsch { 2260e03ab78fSPeter Brune DM dm; 2261942e3340SBarry Smith DMSNES sdm; 22626cab3a1bSJed Brown 22638b0a5094SBarry Smith PetscFunctionBegin; 22649566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 22659566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 22668b0a5094SBarry Smith /* A(x)*x - b(x) */ 2267bbc1464cSBarry Smith if (sdm->ops->computepfunction) { 2268792fecdfSBarry Smith PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx)); 22699566063dSJacob Faibussowitsch PetscCall(VecScale(f, -1.0)); 2270792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx)); 22719566063dSJacob Faibussowitsch PetscCall(MatMultAdd(snes->jacobian_pre, x, f, f)); 2272bbc1464cSBarry Smith } else { 2273792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx)); 22749566063dSJacob Faibussowitsch PetscCall(MatMult(snes->jacobian_pre, x, f)); 2275bbc1464cSBarry Smith } 22763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22778b0a5094SBarry Smith } 22788b0a5094SBarry Smith 2279d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeJacobian(SNES snes, Vec x1, Mat J, Mat B, void *ctx) 2280d71ae5a4SJacob Faibussowitsch { 22818b0a5094SBarry Smith PetscFunctionBegin; 2282e03ab78fSPeter Brune /* the jacobian matrix should be pre-filled in SNESPicardComputeFunction */ 2283bbc1464cSBarry Smith /* must assembly if matrix-free to get the last SNES solution */ 22849566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 22859566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 22863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22878b0a5094SBarry Smith } 22888b0a5094SBarry Smith 22898b0a5094SBarry Smith /*@C 22901d27aa22SBarry Smith SNESSetPicard - Use `SNES` to solve the system $A(x) x = bp(x) + b $ via a Picard type iteration (Picard linearization) 22918b0a5094SBarry Smith 2292c3339decSBarry Smith Logically Collective 22938b0a5094SBarry Smith 22948b0a5094SBarry Smith Input Parameters: 2295f6dfbefdSBarry Smith + snes - the `SNES` context 2296dc4c0fb0SBarry Smith . r - vector to store function values, may be `NULL` 22978434afd1SBarry Smith . bp - function evaluation routine, may be `NULL`, for the calling sequence see `SNESFunctionFn` 229826a11704SBarry Smith . Amat - matrix with which $A(x) x - bp(x) - b$ is to be computed 2299dc4c0fb0SBarry Smith . Pmat - matrix from which preconditioner is computed (usually the same as `Amat`) 23008434afd1SBarry Smith . J - function to compute matrix values, for the calling sequence see `SNESJacobianFn` 2301dc4c0fb0SBarry Smith - ctx - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`) 2302dc4c0fb0SBarry Smith 2303dc4c0fb0SBarry Smith Level: intermediate 23048b0a5094SBarry Smith 23058b0a5094SBarry Smith Notes: 230626a11704SBarry Smith It is often better to provide the nonlinear function $F()$ and some approximation to its Jacobian directly and use 2307f450aa47SBarry 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. 2308f450aa47SBarry Smith 2309f6dfbefdSBarry Smith One can call `SNESSetPicard()` or `SNESSetFunction()` (and possibly `SNESSetJacobian()`) but cannot call both 23108b0a5094SBarry Smith 23111d27aa22SBarry 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}$. 23121d27aa22SBarry Smith When an exact solver is used this corresponds to the "classic" Picard $A(x^{n}) x^{n+1} = bp(x^{n}) + b$ iteration. 23138b0a5094SBarry Smith 231426a11704SBarry Smith Run with `-snes_mf_operator` to solve the system with Newton's method using $A(x^{n})$ to construct the preconditioner. 23158b0a5094SBarry Smith 23160d04baf8SBarry Smith We implement the defect correction form of the Picard iteration because it converges much more generally when inexact linear solvers are used then 23171d27aa22SBarry Smith the direct Picard iteration $A(x^n) x^{n+1} = bp(x^n) + b$ 23188b0a5094SBarry Smith 23198b0a5094SBarry 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 23201d27aa22SBarry 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 23211d27aa22SBarry Smith different please contact us at petsc-dev@mcs.anl.gov and we'll have an entirely new argument \:-). 23228b0a5094SBarry Smith 23231d27aa22SBarry 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 232426a11704SBarry Smith $A(x^{n})$ is used to build the preconditioner 23256b7fb656SBarry Smith 232615229ffcSPierre 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. 23276b7fb656SBarry Smith 2328dc4c0fb0SBarry 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 232926a11704SBarry 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 233026a11704SBarry 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`. 2331aaa8cc7dSPierre Jolivet See the comment in src/snes/tutorials/ex15.c. 2332bbc1464cSBarry Smith 23339bcc50f1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESGetPicard()`, `SNESLineSearchPreCheckPicard()`, 23348434afd1SBarry Smith `SNESFunctionFn`, `SNESJacobianFn` 23358b0a5094SBarry Smith @*/ 23368434afd1SBarry Smith PetscErrorCode SNESSetPicard(SNES snes, Vec r, SNESFunctionFn *bp, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx) 2337d71ae5a4SJacob Faibussowitsch { 2338e03ab78fSPeter Brune DM dm; 2339e03ab78fSPeter Brune 23408b0a5094SBarry Smith PetscFunctionBegin; 23418b0a5094SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 23429566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 23439566063dSJacob Faibussowitsch PetscCall(DMSNESSetPicard(dm, bp, J, ctx)); 23449566063dSJacob Faibussowitsch PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx)); 23459566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes, r, SNESPicardComputeFunction, ctx)); 23469566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESPicardComputeJacobian, ctx)); 23473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23488b0a5094SBarry Smith } 23498b0a5094SBarry Smith 23507971a8bfSPeter Brune /*@C 23517971a8bfSPeter Brune SNESGetPicard - Returns the context for the Picard iteration 23527971a8bfSPeter Brune 2353f6dfbefdSBarry Smith Not Collective, but `Vec` is parallel if `SNES` is parallel. Collective if `Vec` is requested, but has not been created yet. 23547971a8bfSPeter Brune 23557971a8bfSPeter Brune Input Parameter: 2356f6dfbefdSBarry Smith . snes - the `SNES` context 23577971a8bfSPeter Brune 2358d8d19677SJose E. Roman Output Parameters: 2359dc4c0fb0SBarry Smith + r - the function (or `NULL`) 23608434afd1SBarry Smith . f - the function (or `NULL`); for calling sequence see `SNESFunctionFn` 2361dc4c0fb0SBarry Smith . Amat - the matrix used to defined the operation A(x) x - b(x) (or `NULL`) 2362dc4c0fb0SBarry Smith . Pmat - the matrix from which the preconditioner will be constructed (or `NULL`) 23638434afd1SBarry Smith . J - the function for matrix evaluation (or `NULL`); for calling sequence see `SNESJacobianFn` 2364dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`) 23657971a8bfSPeter Brune 23667971a8bfSPeter Brune Level: advanced 23677971a8bfSPeter Brune 23688434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetFunction()`, `SNESSetPicard()`, `SNESGetFunction()`, `SNESGetJacobian()`, `SNESGetDM()`, `SNESFunctionFn`, `SNESJacobianFn` 23697971a8bfSPeter Brune @*/ 23708434afd1SBarry Smith PetscErrorCode SNESGetPicard(SNES snes, Vec *r, SNESFunctionFn **f, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx) 2371d71ae5a4SJacob Faibussowitsch { 23727971a8bfSPeter Brune DM dm; 23737971a8bfSPeter Brune 23747971a8bfSPeter Brune PetscFunctionBegin; 23757971a8bfSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 23769566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, r, NULL, NULL)); 23779566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL)); 23789566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 23799566063dSJacob Faibussowitsch PetscCall(DMSNESGetPicard(dm, f, J, ctx)); 23803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23817971a8bfSPeter Brune } 23827971a8bfSPeter Brune 2383d25893d9SBarry Smith /*@C 2384dc4c0fb0SBarry Smith SNESSetComputeInitialGuess - Sets a routine used to compute an initial guess for the nonlinear problem 2385d25893d9SBarry Smith 2386c3339decSBarry Smith Logically Collective 2387d25893d9SBarry Smith 2388d25893d9SBarry Smith Input Parameters: 2389f6dfbefdSBarry Smith + snes - the `SNES` context 23908434afd1SBarry Smith . func - function evaluation routine, see `SNESInitialGuessFn` for the calling sequence 2391d25893d9SBarry Smith - ctx - [optional] user-defined context for private data for the 2392dc4c0fb0SBarry Smith function evaluation routine (may be `NULL`) 2393d25893d9SBarry Smith 2394d25893d9SBarry Smith Level: intermediate 2395d25893d9SBarry Smith 23968434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESInitialGuessFn` 2397d25893d9SBarry Smith @*/ 23988434afd1SBarry Smith PetscErrorCode SNESSetComputeInitialGuess(SNES snes, SNESInitialGuessFn *func, void *ctx) 2399d71ae5a4SJacob Faibussowitsch { 2400d25893d9SBarry Smith PetscFunctionBegin; 2401d25893d9SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2402d25893d9SBarry Smith if (func) snes->ops->computeinitialguess = func; 2403d25893d9SBarry Smith if (ctx) snes->initialguessP = ctx; 24043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2405d25893d9SBarry Smith } 2406d25893d9SBarry Smith 24071096aae1SMatthew Knepley /*@C 2408dc4c0fb0SBarry Smith SNESGetRhs - Gets the vector for solving F(x) = `rhs`. If `rhs` is not set 2409dd8e379bSPierre Jolivet it assumes a zero right-hand side. 24101096aae1SMatthew Knepley 2411c3339decSBarry Smith Logically Collective 24121096aae1SMatthew Knepley 24131096aae1SMatthew Knepley Input Parameter: 2414f6dfbefdSBarry Smith . snes - the `SNES` context 24151096aae1SMatthew Knepley 24161096aae1SMatthew Knepley Output Parameter: 2417dd8e379bSPierre Jolivet . rhs - the right-hand side vector or `NULL` if there is no right-hand side vector 24181096aae1SMatthew Knepley 24191096aae1SMatthew Knepley Level: intermediate 24201096aae1SMatthew Knepley 24211cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetFunction()` 24221096aae1SMatthew Knepley @*/ 2423d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetRhs(SNES snes, Vec *rhs) 2424d71ae5a4SJacob Faibussowitsch { 24251096aae1SMatthew Knepley PetscFunctionBegin; 24260700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 24274f572ea9SToby Isaac PetscAssertPointer(rhs, 2); 242885385478SLisandro Dalcin *rhs = snes->vec_rhs; 24293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24301096aae1SMatthew Knepley } 24311096aae1SMatthew Knepley 24329b94acceSBarry Smith /*@ 2433f6dfbefdSBarry Smith SNESComputeFunction - Calls the function that has been set with `SNESSetFunction()`. 24349b94acceSBarry Smith 2435c3339decSBarry Smith Collective 2436c7afd0dbSLois Curfman McInnes 24379b94acceSBarry Smith Input Parameters: 2438f6dfbefdSBarry Smith + snes - the `SNES` context 2439c7afd0dbSLois Curfman McInnes - x - input vector 24409b94acceSBarry Smith 24419b94acceSBarry Smith Output Parameter: 2442f6dfbefdSBarry Smith . y - function vector, as set by `SNESSetFunction()` 24439b94acceSBarry Smith 2444dc4c0fb0SBarry Smith Level: developer 2445dc4c0fb0SBarry Smith 244600677de2SStefano Zampini Notes: 2447f6dfbefdSBarry Smith `SNESComputeFunction()` is typically used within nonlinear solvers 2448bbc1464cSBarry Smith implementations, so users would not generally call this routine themselves. 244936851e7fSLois Curfman McInnes 245000677de2SStefano Zampini When solving for $F(x) = b$, this routine computes $y = F(x) - b$. 245100677de2SStefano Zampini 24521cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeMFFunction()` 24539b94acceSBarry Smith @*/ 2454d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeFunction(SNES snes, Vec x, Vec y) 2455d71ae5a4SJacob Faibussowitsch { 24566cab3a1bSJed Brown DM dm; 2457942e3340SBarry Smith DMSNES sdm; 24589b94acceSBarry Smith 24593a40ed3dSBarry Smith PetscFunctionBegin; 24600700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 24610700a824SBarry Smith PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 24620700a824SBarry Smith PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2463c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, x, 2); 2464c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, y, 3); 2465e0f629ddSJacob Faibussowitsch PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2466184914b5SBarry Smith 24679566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 24689566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 24690fdf79fbSJacob 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()."); 247032f3f7c2SPeter Brune if (sdm->ops->computefunction) { 247148a46eb9SPierre Jolivet if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0)); 24729566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(x)); 24738ddeebeaSSteve Benbow /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */ 24748ddeebeaSSteve Benbow snes->domainerror = PETSC_FALSE; 2475800f99ffSJeremy L Thompson { 2476800f99ffSJeremy L Thompson void *ctx; 24778434afd1SBarry Smith SNESFunctionFn *computefunction; 2478800f99ffSJeremy L Thompson PetscCall(DMSNESGetFunction(dm, &computefunction, &ctx)); 2479800f99ffSJeremy L Thompson PetscCallBack("SNES callback function", (*computefunction)(snes, x, y, ctx)); 2480800f99ffSJeremy L Thompson } 24819566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(x)); 248248a46eb9SPierre Jolivet if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0)); 24830fdf79fbSJacob Faibussowitsch } else /* if (snes->vec_rhs) */ { 24849566063dSJacob Faibussowitsch PetscCall(MatMult(snes->jacobian, x, y)); 24850fdf79fbSJacob Faibussowitsch } 24861baa6e33SBarry Smith if (snes->vec_rhs) PetscCall(VecAXPY(y, -1.0, snes->vec_rhs)); 2487ae3c334cSLois Curfman McInnes snes->nfuncs++; 2488422a814eSBarry Smith /* 2489422a814eSBarry Smith domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will 2490422a814eSBarry Smith propagate the value to all processes 2491422a814eSBarry Smith */ 2492f480ea8aSBarry Smith PetscCall(VecFlag(y, snes->domainerror)); 24933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24949b94acceSBarry Smith } 24959b94acceSBarry Smith 2496c79ef259SPeter Brune /*@ 24970b4b7b1cSBarry Smith SNESComputeMFFunction - Calls the function that has been set with `DMSNESSetMFFunction()`. 2498bbc1464cSBarry Smith 2499c3339decSBarry Smith Collective 2500bbc1464cSBarry Smith 2501bbc1464cSBarry Smith Input Parameters: 2502f6dfbefdSBarry Smith + snes - the `SNES` context 2503bbc1464cSBarry Smith - x - input vector 2504bbc1464cSBarry Smith 2505bbc1464cSBarry Smith Output Parameter: 25060b4b7b1cSBarry Smith . y - output vector 2507bbc1464cSBarry Smith 2508dc4c0fb0SBarry Smith Level: developer 2509dc4c0fb0SBarry Smith 2510bbc1464cSBarry Smith Notes: 2511420bcc1bSBarry Smith `SNESComputeMFFunction()` is used within the matrix-vector products called by the matrix created with `MatCreateSNESMF()` 2512bbc1464cSBarry Smith so users would not generally call this routine themselves. 2513bbc1464cSBarry Smith 2514dd8e379bSPierre Jolivet Since this function is intended for use with finite differencing it does not subtract the right-hand side vector provided with `SNESSolve()` 2515f6dfbefdSBarry Smith while `SNESComputeFunction()` does. As such, this routine cannot be used with `MatMFFDSetBase()` with a provided F function value even if it applies the 2516dd8e379bSPierre 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. 2517bbc1464cSBarry Smith 25180b4b7b1cSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `MatCreateSNESMF()`, `DMSNESSetMFFunction()` 2519bbc1464cSBarry Smith @*/ 2520d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeMFFunction(SNES snes, Vec x, Vec y) 2521d71ae5a4SJacob Faibussowitsch { 2522bbc1464cSBarry Smith DM dm; 2523bbc1464cSBarry Smith DMSNES sdm; 2524bbc1464cSBarry Smith 2525bbc1464cSBarry Smith PetscFunctionBegin; 2526bbc1464cSBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2527bbc1464cSBarry Smith PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2528bbc1464cSBarry Smith PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2529bbc1464cSBarry Smith PetscCheckSameComm(snes, 1, x, 2); 2530bbc1464cSBarry Smith PetscCheckSameComm(snes, 1, y, 3); 2531e0f629ddSJacob Faibussowitsch PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2532bbc1464cSBarry Smith 25339566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 25349566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 25359566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0)); 25369566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(x)); 2537bbc1464cSBarry Smith /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */ 2538bbc1464cSBarry Smith snes->domainerror = PETSC_FALSE; 2539792fecdfSBarry Smith PetscCallBack("SNES callback function", (*sdm->ops->computemffunction)(snes, x, y, sdm->mffunctionctx)); 25409566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(x)); 25419566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0)); 2542bbc1464cSBarry Smith snes->nfuncs++; 2543bbc1464cSBarry Smith /* 2544bbc1464cSBarry Smith domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will 2545bbc1464cSBarry Smith propagate the value to all processes 2546bbc1464cSBarry Smith */ 2547f480ea8aSBarry Smith PetscCall(VecFlag(y, snes->domainerror)); 25483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2549bbc1464cSBarry Smith } 2550bbc1464cSBarry Smith 2551bbc1464cSBarry Smith /*@ 2552f6dfbefdSBarry Smith SNESComputeNGS - Calls the Gauss-Seidel function that has been set with `SNESSetNGS()`. 2553c79ef259SPeter Brune 2554c3339decSBarry Smith Collective 2555c79ef259SPeter Brune 2556c79ef259SPeter Brune Input Parameters: 2557f6dfbefdSBarry Smith + snes - the `SNES` context 2558c79ef259SPeter Brune . x - input vector 2559c79ef259SPeter Brune - b - rhs vector 2560c79ef259SPeter Brune 2561c79ef259SPeter Brune Output Parameter: 2562c79ef259SPeter Brune . x - new solution vector 2563c79ef259SPeter Brune 2564dc4c0fb0SBarry Smith Level: developer 2565dc4c0fb0SBarry Smith 2566f6dfbefdSBarry Smith Note: 2567f6dfbefdSBarry Smith `SNESComputeNGS()` is typically used within composed nonlinear solver 2568c79ef259SPeter Brune implementations, so most users would not generally call this routine 2569c79ef259SPeter Brune themselves. 2570c79ef259SPeter Brune 25718434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGSFn`, `SNESSetNGS()`, `SNESComputeFunction()`, `SNESNGS` 2572c79ef259SPeter Brune @*/ 2573d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeNGS(SNES snes, Vec b, Vec x) 2574d71ae5a4SJacob Faibussowitsch { 25756cab3a1bSJed Brown DM dm; 2576942e3340SBarry Smith DMSNES sdm; 2577646217ecSPeter Brune 2578646217ecSPeter Brune PetscFunctionBegin; 2579646217ecSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2580064a246eSJacob Faibussowitsch PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 2581064a246eSJacob Faibussowitsch if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 2582064a246eSJacob Faibussowitsch PetscCheckSameComm(snes, 1, x, 3); 2583064a246eSJacob Faibussowitsch if (b) PetscCheckSameComm(snes, 1, b, 2); 2584e0f629ddSJacob Faibussowitsch if (b) PetscCall(VecValidValues_Internal(b, 2, PETSC_TRUE)); 25859566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_NGSEval, snes, x, b, 0)); 25869566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 25879566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 25880fdf79fbSJacob Faibussowitsch PetscCheck(sdm->ops->computegs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetNGS() before SNESComputeNGS(), likely called from SNESSolve()."); 25899566063dSJacob Faibussowitsch if (b) PetscCall(VecLockReadPush(b)); 2590792fecdfSBarry Smith PetscCallBack("SNES callback NGS", (*sdm->ops->computegs)(snes, x, b, sdm->gsctx)); 25919566063dSJacob Faibussowitsch if (b) PetscCall(VecLockReadPop(b)); 25929566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_NGSEval, snes, x, b, 0)); 25933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2594646217ecSPeter Brune } 2595646217ecSPeter Brune 2596494a190aSStefano Zampini static PetscErrorCode SNESComputeFunction_FD(SNES snes, Vec Xin, Vec G) 2597494a190aSStefano Zampini { 2598494a190aSStefano Zampini Vec X; 2599494a190aSStefano Zampini PetscScalar *g; 2600494a190aSStefano Zampini PetscReal f, f2; 2601494a190aSStefano Zampini PetscInt low, high, N, i; 2602494a190aSStefano Zampini PetscBool flg; 2603494a190aSStefano Zampini PetscReal h = .5 * PETSC_SQRT_MACHINE_EPSILON; 2604494a190aSStefano Zampini 2605494a190aSStefano Zampini PetscFunctionBegin; 2606494a190aSStefano Zampini PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_fd_delta", &h, &flg)); 2607494a190aSStefano Zampini PetscCall(VecDuplicate(Xin, &X)); 2608494a190aSStefano Zampini PetscCall(VecCopy(Xin, X)); 2609494a190aSStefano Zampini PetscCall(VecGetSize(X, &N)); 2610494a190aSStefano Zampini PetscCall(VecGetOwnershipRange(X, &low, &high)); 2611494a190aSStefano Zampini PetscCall(VecSetOption(X, VEC_IGNORE_OFF_PROC_ENTRIES, PETSC_TRUE)); 2612494a190aSStefano Zampini PetscCall(VecGetArray(G, &g)); 2613494a190aSStefano Zampini for (i = 0; i < N; i++) { 2614494a190aSStefano Zampini PetscCall(VecSetValue(X, i, -h, ADD_VALUES)); 2615494a190aSStefano Zampini PetscCall(VecAssemblyBegin(X)); 2616494a190aSStefano Zampini PetscCall(VecAssemblyEnd(X)); 2617494a190aSStefano Zampini PetscCall(SNESComputeObjective(snes, X, &f)); 2618494a190aSStefano Zampini PetscCall(VecSetValue(X, i, 2.0 * h, ADD_VALUES)); 2619494a190aSStefano Zampini PetscCall(VecAssemblyBegin(X)); 2620494a190aSStefano Zampini PetscCall(VecAssemblyEnd(X)); 2621494a190aSStefano Zampini PetscCall(SNESComputeObjective(snes, X, &f2)); 2622494a190aSStefano Zampini PetscCall(VecSetValue(X, i, -h, ADD_VALUES)); 2623494a190aSStefano Zampini PetscCall(VecAssemblyBegin(X)); 2624494a190aSStefano Zampini PetscCall(VecAssemblyEnd(X)); 2625494a190aSStefano Zampini if (i >= low && i < high) g[i - low] = (f2 - f) / (2.0 * h); 2626494a190aSStefano Zampini } 2627494a190aSStefano Zampini PetscCall(VecRestoreArray(G, &g)); 2628494a190aSStefano Zampini PetscCall(VecDestroy(&X)); 2629494a190aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2630494a190aSStefano Zampini } 2631494a190aSStefano Zampini 2632*1dfd7622SMatthew Knepley /*@ 2633*1dfd7622SMatthew Knepley SNESTestFunction - Computes the difference between the computed and finite-difference functions 2634*1dfd7622SMatthew Knepley 2635*1dfd7622SMatthew Knepley Collective 2636*1dfd7622SMatthew Knepley 2637*1dfd7622SMatthew Knepley Input Parameters: 2638*1dfd7622SMatthew Knepley . snes - the `SNES` context 2639*1dfd7622SMatthew Knepley 2640*1dfd7622SMatthew Knepley Options Database Keys: 2641*1dfd7622SMatthew Knepley + -snes_test_function - compare the user provided function with one compute via finite differences to check for errors. 2642*1dfd7622SMatthew Knepley - -snes_test_function_view - display the user provided function, the finite difference function and the difference 2643*1dfd7622SMatthew Knepley 2644*1dfd7622SMatthew Knepley Level: developer 2645*1dfd7622SMatthew Knepley 2646*1dfd7622SMatthew Knepley .seealso: [](ch_snes), `SNESTestJacobian()`, `SNESSetFunction()`, `SNESComputeFunction()` 2647*1dfd7622SMatthew Knepley @*/ 2648494a190aSStefano Zampini PetscErrorCode SNESTestFunction(SNES snes) 2649494a190aSStefano Zampini { 2650494a190aSStefano Zampini Vec x, g1, g2, g3; 2651*1dfd7622SMatthew Knepley PetscBool complete_print = PETSC_FALSE; 2652494a190aSStefano Zampini PetscReal hcnorm, fdnorm, hcmax, fdmax, diffmax, diffnorm; 2653494a190aSStefano Zampini PetscScalar dot; 2654494a190aSStefano Zampini MPI_Comm comm; 2655494a190aSStefano Zampini PetscViewer viewer, mviewer; 2656494a190aSStefano Zampini PetscViewerFormat format; 2657494a190aSStefano Zampini PetscInt tabs; 2658494a190aSStefano Zampini static PetscBool directionsprinted = PETSC_FALSE; 26598434afd1SBarry Smith SNESObjectiveFn *objective; 2660494a190aSStefano Zampini 2661494a190aSStefano Zampini PetscFunctionBegin; 2662494a190aSStefano Zampini PetscCall(SNESGetObjective(snes, &objective, NULL)); 2663494a190aSStefano Zampini if (!objective) PetscFunctionReturn(PETSC_SUCCESS); 2664494a190aSStefano Zampini 2665494a190aSStefano Zampini PetscObjectOptionsBegin((PetscObject)snes); 2666494a190aSStefano Zampini PetscCall(PetscOptionsViewer("-snes_test_function_view", "View difference between hand-coded and finite difference function element entries", "None", &mviewer, &format, &complete_print)); 2667494a190aSStefano Zampini PetscOptionsEnd(); 2668494a190aSStefano Zampini 2669494a190aSStefano Zampini PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 2670494a190aSStefano Zampini PetscCall(PetscViewerASCIIGetStdout(comm, &viewer)); 2671494a190aSStefano Zampini PetscCall(PetscViewerASCIIGetTab(viewer, &tabs)); 2672494a190aSStefano Zampini PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel)); 2673494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Function -------------\n")); 2674494a190aSStefano Zampini if (!complete_print && !directionsprinted) { 2675494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Run with -snes_test_function_view and optionally -snes_test_function <threshold> to show difference\n")); 2676494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " of hand-coded and finite difference function entries greater than <threshold>.\n")); 2677494a190aSStefano Zampini } 2678494a190aSStefano Zampini if (!directionsprinted) { 2679494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Testing hand-coded Function, if (for double precision runs) ||F - Ffd||/||F|| is\n")); 2680494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " O(1.e-8), the hand-coded Function is probably correct.\n")); 2681494a190aSStefano Zampini directionsprinted = PETSC_TRUE; 2682494a190aSStefano Zampini } 2683494a190aSStefano Zampini if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format)); 2684494a190aSStefano Zampini 2685494a190aSStefano Zampini PetscCall(SNESGetSolution(snes, &x)); 2686494a190aSStefano Zampini PetscCall(VecDuplicate(x, &g1)); 2687494a190aSStefano Zampini PetscCall(VecDuplicate(x, &g2)); 2688494a190aSStefano Zampini PetscCall(VecDuplicate(x, &g3)); 2689494a190aSStefano Zampini PetscCall(SNESComputeFunction(snes, x, g1)); 2690494a190aSStefano Zampini PetscCall(SNESComputeFunction_FD(snes, x, g2)); 2691494a190aSStefano Zampini 2692494a190aSStefano Zampini PetscCall(VecNorm(g2, NORM_2, &fdnorm)); 2693494a190aSStefano Zampini PetscCall(VecNorm(g1, NORM_2, &hcnorm)); 2694494a190aSStefano Zampini PetscCall(VecNorm(g2, NORM_INFINITY, &fdmax)); 2695494a190aSStefano Zampini PetscCall(VecNorm(g1, NORM_INFINITY, &hcmax)); 2696494a190aSStefano Zampini PetscCall(VecDot(g1, g2, &dot)); 2697494a190aSStefano Zampini PetscCall(VecCopy(g1, g3)); 2698494a190aSStefano Zampini PetscCall(VecAXPY(g3, -1.0, g2)); 2699494a190aSStefano Zampini PetscCall(VecNorm(g3, NORM_2, &diffnorm)); 2700494a190aSStefano Zampini PetscCall(VecNorm(g3, NORM_INFINITY, &diffmax)); 2701494a190aSStefano 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)))); 2702494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " 2-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffnorm / PetscMax(hcnorm, fdnorm)), (double)diffnorm)); 2703494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " max-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffmax / PetscMax(hcmax, fdmax)), (double)diffmax)); 2704494a190aSStefano Zampini 2705494a190aSStefano Zampini if (complete_print) { 2706494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded function ----------\n")); 2707494a190aSStefano Zampini PetscCall(VecView(g1, mviewer)); 2708494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Finite difference function ----------\n")); 2709494a190aSStefano Zampini PetscCall(VecView(g2, mviewer)); 2710494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded minus finite-difference function ----------\n")); 2711494a190aSStefano Zampini PetscCall(VecView(g3, mviewer)); 2712494a190aSStefano Zampini } 2713494a190aSStefano Zampini PetscCall(VecDestroy(&g1)); 2714494a190aSStefano Zampini PetscCall(VecDestroy(&g2)); 2715494a190aSStefano Zampini PetscCall(VecDestroy(&g3)); 2716494a190aSStefano Zampini 2717494a190aSStefano Zampini if (complete_print) { 2718494a190aSStefano Zampini PetscCall(PetscViewerPopFormat(mviewer)); 2719494a190aSStefano Zampini PetscCall(PetscViewerDestroy(&mviewer)); 2720494a190aSStefano Zampini } 2721494a190aSStefano Zampini PetscCall(PetscViewerASCIISetTab(viewer, tabs)); 2722494a190aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2723494a190aSStefano Zampini } 2724494a190aSStefano Zampini 2725cbf8f02cSMatthew G. Knepley /*@ 2726cbf8f02cSMatthew G. Knepley SNESTestJacobian - Computes the difference between the computed and finite-difference Jacobians 2727cbf8f02cSMatthew G. Knepley 2728cbf8f02cSMatthew G. Knepley Collective 2729cbf8f02cSMatthew G. Knepley 2730cbf8f02cSMatthew G. Knepley Input Parameters: 2731cbf8f02cSMatthew G. Knepley . snes - the `SNES` context 2732cbf8f02cSMatthew G. Knepley 2733cbf8f02cSMatthew G. Knepley Output Parameters: 2734*1dfd7622SMatthew Knepley + Jnorm - the Frobenius norm of the computed Jacobian, or `NULL` 2735*1dfd7622SMatthew Knepley - diffNorm - the Frobenius norm of the difference of the computed and finite-difference Jacobians, or `NULL` 2736cbf8f02cSMatthew G. Knepley 2737cbf8f02cSMatthew G. Knepley Options Database Keys: 2738cbf8f02cSMatthew G. Knepley + -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. 2739cbf8f02cSMatthew G. Knepley - -snes_test_jacobian_view - display the user provided Jacobian, the finite difference Jacobian and the difference 2740cbf8f02cSMatthew G. Knepley 2741cbf8f02cSMatthew G. Knepley Level: developer 2742cbf8f02cSMatthew G. Knepley 2743*1dfd7622SMatthew Knepley Note: 2744*1dfd7622SMatthew Knepley Directions and norms are printed to stdout if `diffNorm` is `NULL`. 2745*1dfd7622SMatthew Knepley 2746*1dfd7622SMatthew Knepley .seealso: [](ch_snes), `SNESTestFunction()`, `SNESSetJacobian()`, `SNESComputeJacobian()` 2747cbf8f02cSMatthew G. Knepley @*/ 2748cbf8f02cSMatthew G. Knepley PetscErrorCode SNESTestJacobian(SNES snes, PetscReal *Jnorm, PetscReal *diffNorm) 2749d71ae5a4SJacob Faibussowitsch { 275012837594SBarry Smith Mat A, B, C, D, jacobian; 27514df93895SStefano Zampini Vec x = snes->vec_sol, f; 2752e885f1abSBarry Smith PetscReal nrm, gnorm; 275381e7118cSBarry Smith PetscReal threshold = 1.e-5; 27540e276705SLisandro Dalcin MatType mattype; 2755e885f1abSBarry Smith PetscInt m, n, M, N; 2756e885f1abSBarry Smith void *functx; 2757*1dfd7622SMatthew Knepley PetscBool complete_print = PETSC_FALSE, threshold_print = PETSC_FALSE, flg, istranspose; 2758*1dfd7622SMatthew Knepley PetscBool silent = diffNorm != PETSC_NULLPTR ? PETSC_TRUE : PETSC_FALSE; 27593325ff46SBarry Smith PetscViewer viewer, mviewer; 2760e885f1abSBarry Smith MPI_Comm comm; 2761e885f1abSBarry Smith PetscInt tabs; 276212837594SBarry Smith static PetscBool directionsprinted = PETSC_FALSE; 27633325ff46SBarry Smith PetscViewerFormat format; 2764e885f1abSBarry Smith 2765e885f1abSBarry Smith PetscFunctionBegin; 2766d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)snes); 27679566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-snes_test_jacobian", "Threshold for element difference between hand-coded and finite difference being meaningful", "None", threshold, &threshold, NULL)); 27689566063dSJacob Faibussowitsch PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display", "-snes_test_jacobian_view", "3.13", NULL)); 27694ead3382SBarry Smith PetscCall(PetscOptionsViewer("-snes_test_jacobian_view", "View difference between hand-coded and finite difference Jacobians element entries", "None", &mviewer, &format, &complete_print)); 27709566063dSJacob Faibussowitsch PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display_threshold", "-snes_test_jacobian", "3.13", "-snes_test_jacobian accepts an optional threshold (since v3.10)")); 27719566063dSJacob 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)); 2772d0609cedSBarry Smith PetscOptionsEnd(); 2773e885f1abSBarry Smith 27749566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 27759566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(comm, &viewer)); 27769566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetTab(viewer, &tabs)); 27779566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel)); 2778*1dfd7622SMatthew Knepley if (!silent) PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Jacobian -------------\n")); 2779*1dfd7622SMatthew Knepley if (!complete_print && !silent && !directionsprinted) { 27809566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Run with -snes_test_jacobian_view and optionally -snes_test_jacobian <threshold> to show difference\n")); 27819566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " of hand-coded and finite difference Jacobian entries greater than <threshold>.\n")); 278212837594SBarry Smith } 2783*1dfd7622SMatthew Knepley if (!directionsprinted && !silent) { 27849566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Testing hand-coded Jacobian, if (for double precision runs) ||J - Jfd||_F/||J||_F is\n")); 27859566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " O(1.e-8), the hand-coded Jacobian is probably correct.\n")); 278612837594SBarry Smith directionsprinted = PETSC_TRUE; 2787e885f1abSBarry Smith } 27881baa6e33SBarry Smith if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format)); 2789e885f1abSBarry Smith 27909566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes->jacobian, MATMFFD, &flg)); 279112837594SBarry Smith if (!flg) jacobian = snes->jacobian; 279212837594SBarry Smith else jacobian = snes->jacobian_pre; 279312837594SBarry Smith 27944df93895SStefano Zampini if (!x) PetscCall(MatCreateVecs(jacobian, &x, NULL)); 27954df93895SStefano Zampini else PetscCall(PetscObjectReference((PetscObject)x)); 27969566063dSJacob Faibussowitsch PetscCall(VecDuplicate(x, &f)); 27974df93895SStefano Zampini 2798a82339d0SMatthew G. Knepley /* evaluate the function at this point because SNESComputeJacobianDefault() assumes that the function has been evaluated and put into snes->vec_func */ 27999566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, x, f)); 28009566063dSJacob Faibussowitsch PetscCall(VecDestroy(&f)); 28019566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESKSPTRANSPOSEONLY, &istranspose)); 280212837594SBarry Smith while (jacobian) { 28032cd624f9SStefano Zampini Mat JT = NULL, Jsave = NULL; 28042cd624f9SStefano Zampini 28052cd624f9SStefano Zampini if (istranspose) { 28069566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(jacobian, &JT)); 28072cd624f9SStefano Zampini Jsave = jacobian; 28082cd624f9SStefano Zampini jacobian = JT; 28092cd624f9SStefano Zampini } 28109566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)jacobian, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, "")); 281112837594SBarry Smith if (flg) { 281212837594SBarry Smith A = jacobian; 28139566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 281412837594SBarry Smith } else { 28159566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(jacobian, MATAIJ, &A)); 281612837594SBarry Smith } 2817e885f1abSBarry Smith 28189566063dSJacob Faibussowitsch PetscCall(MatGetType(A, &mattype)); 28199566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &M, &N)); 28209566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &m, &n)); 28219566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B)); 28229566063dSJacob Faibussowitsch PetscCall(MatSetType(B, mattype)); 28239566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, m, n, M, N)); 28249566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(B, A, A)); 28259566063dSJacob Faibussowitsch PetscCall(MatSetUp(B)); 28269566063dSJacob Faibussowitsch PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 2827e885f1abSBarry Smith 28289566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, NULL, &functx)); 28299566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobianDefault(snes, x, B, B, functx)); 283012837594SBarry Smith 28319566063dSJacob Faibussowitsch PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &D)); 28329566063dSJacob Faibussowitsch PetscCall(MatAYPX(D, -1.0, A, DIFFERENT_NONZERO_PATTERN)); 28339566063dSJacob Faibussowitsch PetscCall(MatNorm(D, NORM_FROBENIUS, &nrm)); 28349566063dSJacob Faibussowitsch PetscCall(MatNorm(A, NORM_FROBENIUS, &gnorm)); 28359566063dSJacob Faibussowitsch PetscCall(MatDestroy(&D)); 283612837594SBarry Smith if (!gnorm) gnorm = 1; /* just in case */ 2837*1dfd7622SMatthew Knepley if (!silent) PetscCall(PetscViewerASCIIPrintf(viewer, " ||J - Jfd||_F/||J||_F = %g, ||J - Jfd||_F = %g\n", (double)(nrm / gnorm), (double)nrm)); 2838e885f1abSBarry Smith if (complete_print) { 28399566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded Jacobian ----------\n")); 28409566063dSJacob Faibussowitsch PetscCall(MatView(A, mviewer)); 28419566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Finite difference Jacobian ----------\n")); 28429566063dSJacob Faibussowitsch PetscCall(MatView(B, mviewer)); 2843e885f1abSBarry Smith } 2844e885f1abSBarry Smith 2845df10fb39SFande Kong if (threshold_print || complete_print) { 2846e885f1abSBarry Smith PetscInt Istart, Iend, *ccols, bncols, cncols, j, row; 2847e885f1abSBarry Smith PetscScalar *cvals; 2848e885f1abSBarry Smith const PetscInt *bcols; 2849e885f1abSBarry Smith const PetscScalar *bvals; 2850e885f1abSBarry Smith 28519566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C)); 28529566063dSJacob Faibussowitsch PetscCall(MatSetType(C, mattype)); 28539566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, m, n, M, N)); 28549566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(C, A, A)); 28559566063dSJacob Faibussowitsch PetscCall(MatSetUp(C)); 28569566063dSJacob Faibussowitsch PetscCall(MatSetOption(C, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 28570e276705SLisandro Dalcin 28589566063dSJacob Faibussowitsch PetscCall(MatAYPX(B, -1.0, A, DIFFERENT_NONZERO_PATTERN)); 28599566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(B, &Istart, &Iend)); 2860e885f1abSBarry Smith 2861e885f1abSBarry Smith for (row = Istart; row < Iend; row++) { 28629566063dSJacob Faibussowitsch PetscCall(MatGetRow(B, row, &bncols, &bcols, &bvals)); 28639566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(bncols, &ccols, bncols, &cvals)); 2864e885f1abSBarry Smith for (j = 0, cncols = 0; j < bncols; j++) { 286523a52b1dSBarry Smith if (PetscAbsScalar(bvals[j]) > threshold) { 2866e885f1abSBarry Smith ccols[cncols] = bcols[j]; 2867e885f1abSBarry Smith cvals[cncols] = bvals[j]; 2868e885f1abSBarry Smith cncols += 1; 2869e885f1abSBarry Smith } 2870e885f1abSBarry Smith } 287148a46eb9SPierre Jolivet if (cncols) PetscCall(MatSetValues(C, 1, &row, cncols, ccols, cvals, INSERT_VALUES)); 28729566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(B, row, &bncols, &bcols, &bvals)); 28739566063dSJacob Faibussowitsch PetscCall(PetscFree2(ccols, cvals)); 2874e885f1abSBarry Smith } 28759566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 28769566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 28779566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded minus finite-difference Jacobian with tolerance %g ----------\n", (double)threshold)); 28789566063dSJacob Faibussowitsch PetscCall(MatView(C, complete_print ? mviewer : viewer)); 28799566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C)); 2880e885f1abSBarry Smith } 28819566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A)); 28829566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 28839566063dSJacob Faibussowitsch PetscCall(MatDestroy(&JT)); 28842cd624f9SStefano Zampini if (Jsave) jacobian = Jsave; 288512837594SBarry Smith if (jacobian != snes->jacobian_pre) { 288612837594SBarry Smith jacobian = snes->jacobian_pre; 2887*1dfd7622SMatthew Knepley if (!silent) PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Jacobian for preconditioner -------------\n")); 28889371c9d4SSatish Balay } else jacobian = NULL; 288912837594SBarry Smith } 28909566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); 28911baa6e33SBarry Smith if (complete_print) PetscCall(PetscViewerPopFormat(mviewer)); 2892648c30bcSBarry Smith if (mviewer) PetscCall(PetscViewerDestroy(&mviewer)); 28939566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISetTab(viewer, tabs)); 2894cbf8f02cSMatthew G. Knepley 2895cbf8f02cSMatthew G. Knepley if (Jnorm) *Jnorm = gnorm; 2896cbf8f02cSMatthew G. Knepley if (diffNorm) *diffNorm = nrm; 28973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2898e885f1abSBarry Smith } 2899e885f1abSBarry Smith 290062fef451SLois Curfman McInnes /*@ 2901f6dfbefdSBarry Smith SNESComputeJacobian - Computes the Jacobian matrix that has been set with `SNESSetJacobian()`. 290262fef451SLois Curfman McInnes 2903c3339decSBarry Smith Collective 2904c7afd0dbSLois Curfman McInnes 290562fef451SLois Curfman McInnes Input Parameters: 2906f6dfbefdSBarry Smith + snes - the `SNES` context 2907e4094ef1SJacob Faibussowitsch - X - input vector 290862fef451SLois Curfman McInnes 290962fef451SLois Curfman McInnes Output Parameters: 2910c7afd0dbSLois Curfman McInnes + A - Jacobian matrix 2911420bcc1bSBarry Smith - B - optional matrix for building the preconditioner, usually the same as `A` 2912fee21e36SBarry Smith 2913e35cf81dSBarry Smith Options Database Keys: 291467b8a455SSatish Balay + -snes_lag_preconditioner <lag> - how often to rebuild preconditioner 291567b8a455SSatish Balay . -snes_lag_jacobian <lag> - how often to rebuild Jacobian 2916455a5933SJed 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. 2917455a5933SJed 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 2918693365a8SJed Brown . -snes_compare_explicit - Compare the computed Jacobian to the finite difference Jacobian and output the differences 2919693365a8SJed Brown . -snes_compare_explicit_draw - Compare the computed Jacobian to the finite difference Jacobian and draw the result 2920693365a8SJed Brown . -snes_compare_explicit_contour - Compare the computed Jacobian to the finite difference Jacobian and draw a contour plot with the result 29217addb90fSBarry Smith . -snes_compare_operator - Make the comparison options above use the operator instead of the matrix used to construct the preconditioner 292294d6a431SBarry Smith . -snes_compare_coloring - Compute the finite difference Jacobian using coloring and display norms of difference 2923a5b23f4aSJose E. Roman . -snes_compare_coloring_display - Compute the finite difference Jacobian using coloring and display verbose differences 2924c01495d3SJed Brown . -snes_compare_coloring_threshold - Display only those matrix entries that differ by more than a given threshold 2925dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_atol - Absolute tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold` 2926dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_rtol - Relative tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold` 2927a5b23f4aSJose E. Roman . -snes_compare_coloring_draw - Compute the finite difference Jacobian using coloring and draw differences 2928a5b23f4aSJose E. Roman - -snes_compare_coloring_draw_contour - Compute the finite difference Jacobian using coloring and show contours of matrices and differences 2929c01495d3SJed Brown 2930dc4c0fb0SBarry Smith Level: developer 2931dc4c0fb0SBarry Smith 2932f6dfbefdSBarry Smith Note: 293362fef451SLois Curfman McInnes Most users should not need to explicitly call this routine, as it 293462fef451SLois Curfman McInnes is used internally within the nonlinear solvers. 293562fef451SLois Curfman McInnes 2936420bcc1bSBarry Smith Developer Note: 2937dc4c0fb0SBarry 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 2938420bcc1bSBarry Smith with the `SNESType` of test that has been removed. 2939e885f1abSBarry Smith 29401cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetJacobian()`, `KSPSetOperators()`, `MatStructure`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()` 294162fef451SLois Curfman McInnes @*/ 2942d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeJacobian(SNES snes, Vec X, Mat A, Mat B) 2943d71ae5a4SJacob Faibussowitsch { 2944ace3abfcSBarry Smith PetscBool flag; 29456cab3a1bSJed Brown DM dm; 2946942e3340SBarry Smith DMSNES sdm; 2947e0e3a89bSBarry Smith KSP ksp; 29483a40ed3dSBarry Smith 29493a40ed3dSBarry Smith PetscFunctionBegin; 29500700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 29510700a824SBarry Smith PetscValidHeaderSpecific(X, VEC_CLASSID, 2); 2952c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, X, 2); 2953e0f629ddSJacob Faibussowitsch PetscCall(VecValidValues_Internal(X, 2, PETSC_TRUE)); 29549566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 29559566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 29563232da50SPeter Brune 295701c1178eSBarry Smith /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix-free */ 2958fe3ffe1eSBarry Smith if (snes->lagjacobian == -2) { 2959fe3ffe1eSBarry Smith snes->lagjacobian = -1; 2960f5af7f23SKarl Rupp 29619566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n")); 2962fe3ffe1eSBarry Smith } else if (snes->lagjacobian == -1) { 29639566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is -1\n")); 29649566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag)); 2965ebd3b9afSBarry Smith if (flag) { 29669566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 29679566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 2968ebd3b9afSBarry Smith } 29693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 297037ec4e1aSPeter Brune } else if (snes->lagjacobian > 1 && (snes->iter + snes->jac_iter) % snes->lagjacobian) { 297163a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagjacobian, snes->iter)); 29729566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag)); 2973ebd3b9afSBarry Smith if (flag) { 29749566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 29759566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 2976ebd3b9afSBarry Smith } 29773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2978e35cf81dSBarry Smith } 2979efd4aadfSBarry Smith if (snes->npc && snes->npcside == PC_LEFT) { 29809566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 29819566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 29823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2983d728fb7dSPeter Brune } 2984e35cf81dSBarry Smith 29859566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_JacobianEval, snes, X, A, B)); 29869566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(X)); 2987800f99ffSJeremy L Thompson { 2988800f99ffSJeremy L Thompson void *ctx; 29898434afd1SBarry Smith SNESJacobianFn *J; 2990800f99ffSJeremy L Thompson PetscCall(DMSNESGetJacobian(dm, &J, &ctx)); 2991800f99ffSJeremy L Thompson PetscCallBack("SNES callback Jacobian", (*J)(snes, X, A, B, ctx)); 2992800f99ffSJeremy L Thompson } 29939566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(X)); 29949566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_JacobianEval, snes, X, A, B)); 299528d58a37SPierre Jolivet 29967addb90fSBarry Smith /* attach latest linearization point to the matrix used to construct the preconditioner */ 29979566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)B, "__SNES_latest_X", (PetscObject)X)); 2998a8054027SBarry Smith 2999e0e3a89bSBarry Smith /* the next line ensures that snes->ksp exists */ 30009566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 30013b4f5425SBarry Smith if (snes->lagpreconditioner == -2) { 30029566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Rebuilding preconditioner exactly once since lag is -2\n")); 30039566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE)); 30043b4f5425SBarry Smith snes->lagpreconditioner = -1; 30053b4f5425SBarry Smith } else if (snes->lagpreconditioner == -1) { 30069566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is -1\n")); 30079566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE)); 300837ec4e1aSPeter Brune } else if (snes->lagpreconditioner > 1 && (snes->iter + snes->pre_iter) % snes->lagpreconditioner) { 300963a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagpreconditioner, snes->iter)); 30109566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE)); 3011d1e9a80fSBarry Smith } else { 30129566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Rebuilding preconditioner\n")); 30139566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE)); 3014a8054027SBarry Smith } 3015a8054027SBarry Smith 30164df93895SStefano Zampini /* monkey business to allow testing Jacobians in multilevel solvers. 30174df93895SStefano Zampini This is needed because the SNESTestXXX interface does not accept vectors and matrices */ 30184df93895SStefano Zampini { 30194df93895SStefano Zampini Vec xsave = snes->vec_sol; 30204df93895SStefano Zampini Mat jacobiansave = snes->jacobian; 30214df93895SStefano Zampini Mat jacobian_presave = snes->jacobian_pre; 30224df93895SStefano Zampini 30234df93895SStefano Zampini snes->vec_sol = X; 30244df93895SStefano Zampini snes->jacobian = A; 30254df93895SStefano Zampini snes->jacobian_pre = B; 3026*1dfd7622SMatthew Knepley if (snes->testFunc) PetscCall(SNESTestFunction(snes)); 3027*1dfd7622SMatthew Knepley if (snes->testJac) PetscCall(SNESTestJacobian(snes, NULL, NULL)); 3028494a190aSStefano Zampini 30294df93895SStefano Zampini snes->vec_sol = xsave; 30304df93895SStefano Zampini snes->jacobian = jacobiansave; 30314df93895SStefano Zampini snes->jacobian_pre = jacobian_presave; 30324df93895SStefano Zampini } 30334df93895SStefano Zampini 3034693365a8SJed Brown { 3035693365a8SJed Brown PetscBool flag = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_operator = PETSC_FALSE; 3036648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit", NULL, NULL, &flag)); 3037648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw", NULL, NULL, &flag_draw)); 3038648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw_contour", NULL, NULL, &flag_contour)); 3039648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_operator", NULL, NULL, &flag_operator)); 3040693365a8SJed Brown if (flag || flag_draw || flag_contour) { 30410298fd71SBarry Smith Mat Bexp_mine = NULL, Bexp, FDexp; 3042693365a8SJed Brown PetscViewer vdraw, vstdout; 30436b3a5b13SJed Brown PetscBool flg; 3044693365a8SJed Brown if (flag_operator) { 30459566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(A, MATAIJ, &Bexp_mine)); 3046693365a8SJed Brown Bexp = Bexp_mine; 3047693365a8SJed Brown } else { 30487addb90fSBarry Smith /* See if the matrix used to construct the preconditioner can be viewed and added directly */ 30499566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)B, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPIBAIJ, "")); 305094ab13aaSBarry Smith if (flg) Bexp = B; 3051693365a8SJed Brown else { 3052693365a8SJed Brown /* If the "preconditioning" matrix is itself MATSHELL or some other type without direct support */ 30539566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(B, MATAIJ, &Bexp_mine)); 3054693365a8SJed Brown Bexp = Bexp_mine; 3055693365a8SJed Brown } 3056693365a8SJed Brown } 30579566063dSJacob Faibussowitsch PetscCall(MatConvert(Bexp, MATSAME, MAT_INITIAL_MATRIX, &FDexp)); 30589566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobianDefault(snes, X, FDexp, FDexp, NULL)); 30599566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout)); 3060693365a8SJed Brown if (flag_draw || flag_contour) { 30619566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Explicit Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw)); 30629566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 30630298fd71SBarry Smith } else vdraw = NULL; 30649566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit %s\n", flag_operator ? "Jacobian" : "preconditioning Jacobian")); 30659566063dSJacob Faibussowitsch if (flag) PetscCall(MatView(Bexp, vstdout)); 30669566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(Bexp, vdraw)); 30679566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Finite difference Jacobian\n")); 30689566063dSJacob Faibussowitsch if (flag) PetscCall(MatView(FDexp, vstdout)); 30699566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(FDexp, vdraw)); 30709566063dSJacob Faibussowitsch PetscCall(MatAYPX(FDexp, -1.0, Bexp, SAME_NONZERO_PATTERN)); 30719566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian\n")); 30729566063dSJacob Faibussowitsch if (flag) PetscCall(MatView(FDexp, vstdout)); 3073693365a8SJed Brown if (vdraw) { /* Always use contour for the difference */ 30749566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 30759566063dSJacob Faibussowitsch PetscCall(MatView(FDexp, vdraw)); 30769566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(vdraw)); 3077693365a8SJed Brown } 30789566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw)); 30799566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&vdraw)); 30809566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bexp_mine)); 30819566063dSJacob Faibussowitsch PetscCall(MatDestroy(&FDexp)); 3082693365a8SJed Brown } 3083693365a8SJed Brown } 30844c30e9fbSJed Brown { 30856719d8e4SJed Brown PetscBool flag = PETSC_FALSE, flag_display = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_threshold = PETSC_FALSE; 30866719d8e4SJed Brown PetscReal threshold_atol = PETSC_SQRT_MACHINE_EPSILON, threshold_rtol = 10 * PETSC_SQRT_MACHINE_EPSILON; 3087648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring", NULL, NULL, &flag)); 3088648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_display", NULL, NULL, &flag_display)); 3089648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw", NULL, NULL, &flag_draw)); 3090648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw_contour", NULL, NULL, &flag_contour)); 3091648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold", NULL, NULL, &flag_threshold)); 309227b0f280SBarry Smith if (flag_threshold) { 30939566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_rtol", &threshold_rtol, NULL)); 30949566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_atol", &threshold_atol, NULL)); 309527b0f280SBarry Smith } 30966719d8e4SJed Brown if (flag || flag_display || flag_draw || flag_contour || flag_threshold) { 30974c30e9fbSJed Brown Mat Bfd; 30984c30e9fbSJed Brown PetscViewer vdraw, vstdout; 3099335efc43SPeter Brune MatColoring coloring; 31004c30e9fbSJed Brown ISColoring iscoloring; 31014c30e9fbSJed Brown MatFDColoring matfdcoloring; 31028434afd1SBarry Smith SNESFunctionFn *func; 31034c30e9fbSJed Brown void *funcctx; 31046719d8e4SJed Brown PetscReal norm1, norm2, normmax; 31054c30e9fbSJed Brown 31069566063dSJacob Faibussowitsch PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &Bfd)); 31079566063dSJacob Faibussowitsch PetscCall(MatColoringCreate(Bfd, &coloring)); 31089566063dSJacob Faibussowitsch PetscCall(MatColoringSetType(coloring, MATCOLORINGSL)); 31099566063dSJacob Faibussowitsch PetscCall(MatColoringSetFromOptions(coloring)); 31109566063dSJacob Faibussowitsch PetscCall(MatColoringApply(coloring, &iscoloring)); 31119566063dSJacob Faibussowitsch PetscCall(MatColoringDestroy(&coloring)); 31129566063dSJacob Faibussowitsch PetscCall(MatFDColoringCreate(Bfd, iscoloring, &matfdcoloring)); 31139566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFromOptions(matfdcoloring)); 31149566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetUp(Bfd, iscoloring, matfdcoloring)); 31159566063dSJacob Faibussowitsch PetscCall(ISColoringDestroy(&iscoloring)); 31164c30e9fbSJed Brown 31174c30e9fbSJed Brown /* This method of getting the function is currently unreliable since it doesn't work for DM local functions. */ 31189566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, &func, &funcctx)); 31192ba42892SBarry Smith PetscCall(MatFDColoringSetFunction(matfdcoloring, (MatFDColoringFn *)func, funcctx)); 31209566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)matfdcoloring, ((PetscObject)snes)->prefix)); 31219566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)matfdcoloring, "coloring_")); 31229566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFromOptions(matfdcoloring)); 31239566063dSJacob Faibussowitsch PetscCall(MatFDColoringApply(Bfd, matfdcoloring, X, snes)); 31249566063dSJacob Faibussowitsch PetscCall(MatFDColoringDestroy(&matfdcoloring)); 31254c30e9fbSJed Brown 31269566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout)); 31274c30e9fbSJed Brown if (flag_draw || flag_contour) { 31289566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Colored Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw)); 31299566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 31300298fd71SBarry Smith } else vdraw = NULL; 31319566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit preconditioning Jacobian\n")); 31329566063dSJacob Faibussowitsch if (flag_display) PetscCall(MatView(B, vstdout)); 31339566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(B, vdraw)); 31349566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Colored Finite difference Jacobian\n")); 31359566063dSJacob Faibussowitsch if (flag_display) PetscCall(MatView(Bfd, vstdout)); 31369566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(Bfd, vdraw)); 31379566063dSJacob Faibussowitsch PetscCall(MatAYPX(Bfd, -1.0, B, SAME_NONZERO_PATTERN)); 31389566063dSJacob Faibussowitsch PetscCall(MatNorm(Bfd, NORM_1, &norm1)); 31399566063dSJacob Faibussowitsch PetscCall(MatNorm(Bfd, NORM_FROBENIUS, &norm2)); 31409566063dSJacob Faibussowitsch PetscCall(MatNorm(Bfd, NORM_MAX, &normmax)); 31419566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian, norm1=%g normFrob=%g normmax=%g\n", (double)norm1, (double)norm2, (double)normmax)); 31429566063dSJacob Faibussowitsch if (flag_display) PetscCall(MatView(Bfd, vstdout)); 31434c30e9fbSJed Brown if (vdraw) { /* Always use contour for the difference */ 31449566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 31459566063dSJacob Faibussowitsch PetscCall(MatView(Bfd, vdraw)); 31469566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(vdraw)); 31474c30e9fbSJed Brown } 31489566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw)); 31496719d8e4SJed Brown 31506719d8e4SJed Brown if (flag_threshold) { 31516719d8e4SJed Brown PetscInt bs, rstart, rend, i; 31529566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(B, &bs)); 31539566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(B, &rstart, &rend)); 31546719d8e4SJed Brown for (i = rstart; i < rend; i++) { 31556719d8e4SJed Brown const PetscScalar *ba, *ca; 31566719d8e4SJed Brown const PetscInt *bj, *cj; 31576719d8e4SJed Brown PetscInt bn, cn, j, maxentrycol = -1, maxdiffcol = -1, maxrdiffcol = -1; 31586719d8e4SJed Brown PetscReal maxentry = 0, maxdiff = 0, maxrdiff = 0; 31599566063dSJacob Faibussowitsch PetscCall(MatGetRow(B, i, &bn, &bj, &ba)); 31609566063dSJacob Faibussowitsch PetscCall(MatGetRow(Bfd, i, &cn, &cj, &ca)); 31615f80ce2aSJacob Faibussowitsch PetscCheck(bn == cn, ((PetscObject)A)->comm, PETSC_ERR_PLIB, "Unexpected different nonzero pattern in -snes_compare_coloring_threshold"); 31626719d8e4SJed Brown for (j = 0; j < bn; j++) { 31636719d8e4SJed Brown PetscReal rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j])); 31646719d8e4SJed Brown if (PetscAbsScalar(ba[j]) > PetscAbs(maxentry)) { 31656719d8e4SJed Brown maxentrycol = bj[j]; 31666719d8e4SJed Brown maxentry = PetscRealPart(ba[j]); 31676719d8e4SJed Brown } 31686719d8e4SJed Brown if (PetscAbsScalar(ca[j]) > PetscAbs(maxdiff)) { 31696719d8e4SJed Brown maxdiffcol = bj[j]; 31706719d8e4SJed Brown maxdiff = PetscRealPart(ca[j]); 31716719d8e4SJed Brown } 31726719d8e4SJed Brown if (rdiff > maxrdiff) { 31736719d8e4SJed Brown maxrdiffcol = bj[j]; 31746719d8e4SJed Brown maxrdiff = rdiff; 31756719d8e4SJed Brown } 31766719d8e4SJed Brown } 31776719d8e4SJed Brown if (maxrdiff > 1) { 317863a3b9bcSJacob 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)); 31796719d8e4SJed Brown for (j = 0; j < bn; j++) { 31806719d8e4SJed Brown PetscReal rdiff; 31816719d8e4SJed Brown rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j])); 318248a46eb9SPierre Jolivet if (rdiff > 1) PetscCall(PetscViewerASCIIPrintf(vstdout, " (%" PetscInt_FMT ",%g:%g)", bj[j], (double)PetscRealPart(ba[j]), (double)PetscRealPart(ca[j]))); 31836719d8e4SJed Brown } 318463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "\n")); 31856719d8e4SJed Brown } 31869566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(B, i, &bn, &bj, &ba)); 31879566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(Bfd, i, &cn, &cj, &ca)); 31886719d8e4SJed Brown } 31896719d8e4SJed Brown } 31909566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&vdraw)); 31919566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bfd)); 31924c30e9fbSJed Brown } 31934c30e9fbSJed Brown } 31943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 31959b94acceSBarry Smith } 31969b94acceSBarry Smith 31979b94acceSBarry Smith /*@C 31989b94acceSBarry Smith SNESSetJacobian - Sets the function to compute Jacobian as well as the 3199044dda88SLois Curfman McInnes location to store the matrix. 32009b94acceSBarry Smith 3201c3339decSBarry Smith Logically Collective 3202c7afd0dbSLois Curfman McInnes 32039b94acceSBarry Smith Input Parameters: 3204f6dfbefdSBarry Smith + snes - the `SNES` context 3205e5d3d808SBarry Smith . Amat - the matrix that defines the (approximate) Jacobian 3206dc4c0fb0SBarry Smith . Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`. 32078434afd1SBarry Smith . J - Jacobian evaluation routine (if `NULL` then `SNES` retains any previously set value), see `SNESJacobianFn` for details 3208c7afd0dbSLois Curfman McInnes - ctx - [optional] user-defined context for private data for the 3209dc4c0fb0SBarry Smith Jacobian evaluation routine (may be `NULL`) (if `NULL` then `SNES` retains any previously set value) 3210dc4c0fb0SBarry Smith 3211dc4c0fb0SBarry Smith Level: beginner 32129b94acceSBarry Smith 32139b94acceSBarry Smith Notes: 3214dc4c0fb0SBarry Smith If the `Amat` matrix and `Pmat` matrix are different you must call `MatAssemblyBegin()`/`MatAssemblyEnd()` on 321516913363SBarry Smith each matrix. 321616913363SBarry Smith 3217dc4c0fb0SBarry Smith If you know the operator `Amat` has a null space you can use `MatSetNullSpace()` and `MatSetTransposeNullSpace()` to supply the null 3218dc4c0fb0SBarry Smith space to `Amat` and the `KSP` solvers will automatically use that null space as needed during the solution process. 3219895c21f2SBarry Smith 3220dc4c0fb0SBarry Smith If using `SNESComputeJacobianDefaultColor()` to assemble a Jacobian, the `ctx` argument 3221f6dfbefdSBarry Smith must be a `MatFDColoring`. 3222a8a26c1eSJed Brown 3223c3cc8fd1SJed Brown Other defect-correction schemes can be used by computing a different matrix in place of the Jacobian. One common 3224f6dfbefdSBarry Smith example is to use the "Picard linearization" which only differentiates through the highest order parts of each term using `SNESSetPicard()` 3225c3cc8fd1SJed Brown 32261cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSPSetOperators()`, `SNESSetFunction()`, `MatMFFDComputeJacobian()`, `SNESComputeJacobianDefaultColor()`, `MatStructure`, 32278434afd1SBarry Smith `SNESSetPicard()`, `SNESJacobianFn`, `SNESFunctionFn` 32289b94acceSBarry Smith @*/ 32298434afd1SBarry Smith PetscErrorCode SNESSetJacobian(SNES snes, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx) 3230d71ae5a4SJacob Faibussowitsch { 32316cab3a1bSJed Brown DM dm; 32323a7fca6bSBarry Smith 32333a40ed3dSBarry Smith PetscFunctionBegin; 32340700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3235e5d3d808SBarry Smith if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2); 3236e5d3d808SBarry Smith if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3); 3237e5d3d808SBarry Smith if (Amat) PetscCheckSameComm(snes, 1, Amat, 2); 3238e5d3d808SBarry Smith if (Pmat) PetscCheckSameComm(snes, 1, Pmat, 3); 32399566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 32409566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, J, ctx)); 3241e5d3d808SBarry Smith if (Amat) { 32429566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)Amat)); 32439566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian)); 3244f5af7f23SKarl Rupp 3245e5d3d808SBarry Smith snes->jacobian = Amat; 32463a7fca6bSBarry Smith } 3247e5d3d808SBarry Smith if (Pmat) { 32489566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)Pmat)); 32499566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian_pre)); 3250f5af7f23SKarl Rupp 3251e5d3d808SBarry Smith snes->jacobian_pre = Pmat; 32523a7fca6bSBarry Smith } 32533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 32549b94acceSBarry Smith } 325562fef451SLois Curfman McInnes 3256c2aafc4cSSatish Balay /*@C 3257b4fd4287SBarry Smith SNESGetJacobian - Returns the Jacobian matrix and optionally the user 3258b4fd4287SBarry Smith provided context for evaluating the Jacobian. 3259b4fd4287SBarry Smith 3260420bcc1bSBarry Smith Not Collective, but `Mat` object will be parallel if `SNES` is 3261c7afd0dbSLois Curfman McInnes 3262b4fd4287SBarry Smith Input Parameter: 3263b4fd4287SBarry Smith . snes - the nonlinear solver context 3264b4fd4287SBarry Smith 3265b4fd4287SBarry Smith Output Parameters: 3266dc4c0fb0SBarry Smith + Amat - location to stash (approximate) Jacobian matrix (or `NULL`) 3267dc4c0fb0SBarry Smith . Pmat - location to stash matrix used to compute the preconditioner (or `NULL`) 32688434afd1SBarry Smith . J - location to put Jacobian function (or `NULL`), for calling sequence see `SNESJacobianFn` 3269dc4c0fb0SBarry Smith - ctx - location to stash Jacobian ctx (or `NULL`) 3270fee21e36SBarry Smith 327136851e7fSLois Curfman McInnes Level: advanced 327236851e7fSLois Curfman McInnes 32738434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `Mat`, `SNESSetJacobian()`, `SNESComputeJacobian()`, `SNESJacobianFn`, `SNESGetFunction()` 3274b4fd4287SBarry Smith @*/ 32758434afd1SBarry Smith PetscErrorCode SNESGetJacobian(SNES snes, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx) 3276d71ae5a4SJacob Faibussowitsch { 32776cab3a1bSJed Brown DM dm; 32786cab3a1bSJed Brown 32793a40ed3dSBarry Smith PetscFunctionBegin; 32800700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3281e5d3d808SBarry Smith if (Amat) *Amat = snes->jacobian; 3282e5d3d808SBarry Smith if (Pmat) *Pmat = snes->jacobian_pre; 32839566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 3284800f99ffSJeremy L Thompson PetscCall(DMSNESGetJacobian(dm, J, ctx)); 32853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3286b4fd4287SBarry Smith } 3287b4fd4287SBarry Smith 3288d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetDefaultComputeJacobian(SNES snes) 3289d71ae5a4SJacob Faibussowitsch { 329058b371f3SBarry Smith DM dm; 329158b371f3SBarry Smith DMSNES sdm; 329258b371f3SBarry Smith 329358b371f3SBarry Smith PetscFunctionBegin; 32949566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 32959566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 329658b371f3SBarry Smith if (!sdm->ops->computejacobian && snes->jacobian_pre) { 329758b371f3SBarry Smith DM dm; 329858b371f3SBarry Smith PetscBool isdense, ismf; 329958b371f3SBarry Smith 33009566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 33019566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &isdense, MATSEQDENSE, MATMPIDENSE, MATDENSE, NULL)); 33029566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &ismf, MATMFFD, MATSHELL, NULL)); 330358b371f3SBarry Smith if (isdense) { 33049566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefault, NULL)); 330558b371f3SBarry Smith } else if (!ismf) { 33069566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefaultColor, NULL)); 330758b371f3SBarry Smith } 330858b371f3SBarry Smith } 33093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 331058b371f3SBarry Smith } 331158b371f3SBarry Smith 33129b94acceSBarry Smith /*@ 33139b94acceSBarry Smith SNESSetUp - Sets up the internal data structures for the later use 33140b4b7b1cSBarry Smith of a nonlinear solver `SNESSolve()`. 33159b94acceSBarry Smith 3316c3339decSBarry Smith Collective 3317fee21e36SBarry Smith 33182fe279fdSBarry Smith Input Parameter: 3319f6dfbefdSBarry Smith . snes - the `SNES` context 3320c7afd0dbSLois Curfman McInnes 3321dc4c0fb0SBarry Smith Level: advanced 3322dc4c0fb0SBarry Smith 3323f6dfbefdSBarry Smith Note: 33240b4b7b1cSBarry Smith For basic use of the `SNES` solvers the user does not need to explicitly call 3325f6dfbefdSBarry Smith `SNESSetUp()`, since these actions will automatically occur during 3326f6dfbefdSBarry Smith the call to `SNESSolve()`. However, if one wishes to control this 3327f6dfbefdSBarry Smith phase separately, `SNESSetUp()` should be called after `SNESCreate()` 3328f6dfbefdSBarry Smith and optional routines of the form SNESSetXXX(), but before `SNESSolve()`. 3329272ac6f2SLois Curfman McInnes 33300b4b7b1cSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`, `SNESDestroy()`, `SNESSetFromOptions()` 33319b94acceSBarry Smith @*/ 3332d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUp(SNES snes) 3333d71ae5a4SJacob Faibussowitsch { 33346cab3a1bSJed Brown DM dm; 3335942e3340SBarry Smith DMSNES sdm; 3336c35f09e5SBarry Smith SNESLineSearch linesearch, pclinesearch; 33376e2a1849SPeter Brune void *lsprectx, *lspostctx; 33389b5c1c08SStefano Zampini PetscBool mf_operator, mf; 33399b5c1c08SStefano Zampini Vec f, fpc; 33409b5c1c08SStefano Zampini void *funcctx; 33419b5c1c08SStefano Zampini void *jacctx, *appctx; 33429b5c1c08SStefano Zampini Mat j, jpre; 33436b2b7091SBarry Smith PetscErrorCode (*precheck)(SNESLineSearch, Vec, Vec, PetscBool *, void *); 33446b2b7091SBarry Smith PetscErrorCode (*postcheck)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *); 33458434afd1SBarry Smith SNESFunctionFn *func; 33468434afd1SBarry Smith SNESJacobianFn *jac; 33473a40ed3dSBarry Smith 33483a40ed3dSBarry Smith PetscFunctionBegin; 33490700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 33503ba16761SJacob Faibussowitsch if (snes->setupcalled) PetscFunctionReturn(PETSC_SUCCESS); 3351fc8bc0e3SRichard Tran Mills PetscCall(PetscLogEventBegin(SNES_SetUp, snes, 0, 0, 0)); 33529b94acceSBarry Smith 335348a46eb9SPierre Jolivet if (!((PetscObject)snes)->type_name) PetscCall(SNESSetType(snes, SNESNEWTONLS)); 335485385478SLisandro Dalcin 33559566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &snes->vec_func, NULL, NULL)); 335658c9b817SLisandro Dalcin 33579566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 33589566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm)); 33599566063dSJacob Faibussowitsch PetscCall(SNESSetDefaultComputeJacobian(snes)); 336058b371f3SBarry Smith 336148a46eb9SPierre Jolivet if (!snes->vec_func) PetscCall(DMCreateGlobalVector(dm, &snes->vec_func)); 3362efd51863SBarry Smith 336348a46eb9SPierre Jolivet if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 3364b710008aSBarry Smith 3365d8d34be6SBarry Smith if (snes->linesearch) { 33669566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 33679566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetFunction(snes->linesearch, SNESComputeFunction)); 3368d8d34be6SBarry Smith } 33699e764e56SPeter Brune 33709b5c1c08SStefano Zampini PetscCall(SNESGetUseMatrixFree(snes, &mf_operator, &mf)); 3371b552625fSStefano Zampini if (snes->npc && snes->npcside == PC_LEFT) { 3372172a4300SPeter Brune snes->mf = PETSC_TRUE; 3373172a4300SPeter Brune snes->mf_operator = PETSC_FALSE; 3374172a4300SPeter Brune } 3375d8f46077SPeter Brune 3376efd4aadfSBarry Smith if (snes->npc) { 33776e2a1849SPeter Brune /* copy the DM over */ 33789566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 33799566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes->npc, dm)); 33806e2a1849SPeter Brune 33819566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &f, &func, &funcctx)); 33829566063dSJacob Faibussowitsch PetscCall(VecDuplicate(f, &fpc)); 33839566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes->npc, fpc, func, funcctx)); 33849566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, &j, &jpre, &jac, &jacctx)); 33859566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes->npc, j, jpre, jac, jacctx)); 33869566063dSJacob Faibussowitsch PetscCall(SNESGetApplicationContext(snes, &appctx)); 33879566063dSJacob Faibussowitsch PetscCall(SNESSetApplicationContext(snes->npc, appctx)); 33889b5c1c08SStefano Zampini PetscCall(SNESSetUseMatrixFree(snes->npc, mf_operator, mf)); 33899566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fpc)); 33906e2a1849SPeter Brune 33916e2a1849SPeter Brune /* copy the function pointers over */ 33929566063dSJacob Faibussowitsch PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)snes->npc)); 33936e2a1849SPeter Brune 33946e2a1849SPeter Brune /* default to 1 iteration */ 33959566063dSJacob Faibussowitsch PetscCall(SNESSetTolerances(snes->npc, 0.0, 0.0, 0.0, 1, snes->npc->max_funcs)); 3396efd4aadfSBarry Smith if (snes->npcside == PC_RIGHT) { 33979566063dSJacob Faibussowitsch PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_FINAL_ONLY)); 3398a9936a0cSPeter Brune } else { 33999566063dSJacob Faibussowitsch PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_NONE)); 3400a9936a0cSPeter Brune } 34019566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes->npc)); 34026e2a1849SPeter Brune 34036e2a1849SPeter Brune /* copy the line search context over */ 3404d8d34be6SBarry Smith if (snes->linesearch && snes->npc->linesearch) { 34059566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &linesearch)); 34069566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes->npc, &pclinesearch)); 34079566063dSJacob Faibussowitsch PetscCall(SNESLineSearchGetPreCheck(linesearch, &precheck, &lsprectx)); 34089566063dSJacob Faibussowitsch PetscCall(SNESLineSearchGetPostCheck(linesearch, &postcheck, &lspostctx)); 34099566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetPreCheck(pclinesearch, precheck, lsprectx)); 34109566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetPostCheck(pclinesearch, postcheck, lspostctx)); 34119566063dSJacob Faibussowitsch PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch)); 34126e2a1849SPeter Brune } 3413d8d34be6SBarry Smith } 34141baa6e33SBarry Smith if (snes->mf) PetscCall(SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version)); 3415835f2295SStefano Zampini if (snes->ops->usercompute && !snes->ctx) PetscCallBack("SNES callback compute application context", (*snes->ops->usercompute)(snes, &snes->ctx)); 34166e2a1849SPeter Brune 341737ec4e1aSPeter Brune snes->jac_iter = 0; 341837ec4e1aSPeter Brune snes->pre_iter = 0; 341937ec4e1aSPeter Brune 3420dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, setup); 342158c9b817SLisandro Dalcin 34229566063dSJacob Faibussowitsch PetscCall(SNESSetDefaultComputeJacobian(snes)); 342358b371f3SBarry Smith 3424b552625fSStefano Zampini if (snes->npc && snes->npcside == PC_LEFT) { 34256c67d002SPeter Brune if (snes->functype == SNES_FUNCTION_PRECONDITIONED) { 3426d8d34be6SBarry Smith if (snes->linesearch) { 34279566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &linesearch)); 34289566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunctionDefaultNPC)); 34296c67d002SPeter Brune } 34306c67d002SPeter Brune } 3431d8d34be6SBarry Smith } 3432fc8bc0e3SRichard Tran Mills PetscCall(PetscLogEventEnd(SNES_SetUp, snes, 0, 0, 0)); 34337aaed0d8SBarry Smith snes->setupcalled = PETSC_TRUE; 34343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 34359b94acceSBarry Smith } 34369b94acceSBarry Smith 343737596af1SLisandro Dalcin /*@ 34380b4b7b1cSBarry 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 343937596af1SLisandro Dalcin 3440c3339decSBarry Smith Collective 344137596af1SLisandro Dalcin 344237596af1SLisandro Dalcin Input Parameter: 34430b4b7b1cSBarry Smith . snes - the nonlinear iterative solver context obtained from `SNESCreate()` 344437596af1SLisandro Dalcin 3445d25893d9SBarry Smith Level: intermediate 3446d25893d9SBarry Smith 344795452b02SPatrick Sanan Notes: 34480b4b7b1cSBarry Smith Any options set on the `SNES` object, including those set with `SNESSetFromOptions()` remain. 34490b4b7b1cSBarry Smith 3450f6dfbefdSBarry Smith Call this if you wish to reuse a `SNES` but with different size vectors 345137596af1SLisandro Dalcin 3452f6dfbefdSBarry Smith Also calls the application context destroy routine set with `SNESSetComputeApplicationContext()` 3453f6dfbefdSBarry Smith 34541cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESDestroy()`, `SNESCreate()`, `SNESSetUp()`, `SNESSolve()` 345537596af1SLisandro Dalcin @*/ 3456d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESReset(SNES snes) 3457d71ae5a4SJacob Faibussowitsch { 345837596af1SLisandro Dalcin PetscFunctionBegin; 345937596af1SLisandro Dalcin PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 346049abdd8aSBarry Smith if (snes->ops->ctxdestroy && snes->ctx) { 3461835f2295SStefano Zampini PetscCallBack("SNES callback destroy application context", (*snes->ops->ctxdestroy)(&snes->ctx)); 346249abdd8aSBarry Smith snes->ctx = NULL; 3463d25893d9SBarry Smith } 34641baa6e33SBarry Smith if (snes->npc) PetscCall(SNESReset(snes->npc)); 34658a23116dSBarry Smith 3466dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, reset); 34671baa6e33SBarry Smith if (snes->ksp) PetscCall(KSPReset(snes->ksp)); 34689e764e56SPeter Brune 34691baa6e33SBarry Smith if (snes->linesearch) PetscCall(SNESLineSearchReset(snes->linesearch)); 34709e764e56SPeter Brune 34719566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_rhs)); 34729566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol)); 34739566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol_update)); 34749566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_func)); 34759566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian)); 34769566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian_pre)); 34779566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->picard)); 34789566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(snes->nwork, &snes->work)); 34799566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(snes->nvwork, &snes->vwork)); 3480f5af7f23SKarl Rupp 348140fdac6aSLawrence Mitchell snes->alwayscomputesfinalresidual = PETSC_FALSE; 348240fdac6aSLawrence Mitchell 348337596af1SLisandro Dalcin snes->nwork = snes->nvwork = 0; 348437596af1SLisandro Dalcin snes->setupcalled = PETSC_FALSE; 34853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 348637596af1SLisandro Dalcin } 348737596af1SLisandro Dalcin 348852baeb72SSatish Balay /*@ 348936d43d94SBarry Smith SNESConvergedReasonViewCancel - Clears all the reason view functions for a `SNES` object provided with `SNESConvergedReasonViewSet()` also 349036d43d94SBarry Smith removes the default viewer. 3491c4421ceaSFande Kong 3492c3339decSBarry Smith Collective 3493c4421ceaSFande Kong 3494c4421ceaSFande Kong Input Parameter: 34950b4b7b1cSBarry Smith . snes - the nonlinear iterative solver context obtained from `SNESCreate()` 3496c4421ceaSFande Kong 3497c4421ceaSFande Kong Level: intermediate 3498c4421ceaSFande Kong 3499420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESReset()`, `SNESConvergedReasonViewSet()` 3500c4421ceaSFande Kong @*/ 3501d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewCancel(SNES snes) 3502d71ae5a4SJacob Faibussowitsch { 3503c4421ceaSFande Kong PetscInt i; 3504c4421ceaSFande Kong 3505c4421ceaSFande Kong PetscFunctionBegin; 3506c4421ceaSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3507c4421ceaSFande Kong for (i = 0; i < snes->numberreasonviews; i++) { 350848a46eb9SPierre Jolivet if (snes->reasonviewdestroy[i]) PetscCall((*snes->reasonviewdestroy[i])(&snes->reasonviewcontext[i])); 3509c4421ceaSFande Kong } 3510c4421ceaSFande Kong snes->numberreasonviews = 0; 3511648c30bcSBarry Smith PetscCall(PetscViewerDestroy(&snes->convergedreasonviewer)); 35123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3513c4421ceaSFande Kong } 3514c4421ceaSFande Kong 35150764c050SBarry Smith /*@ 35169b94acceSBarry Smith SNESDestroy - Destroys the nonlinear solver context that was created 3517f6dfbefdSBarry Smith with `SNESCreate()`. 35189b94acceSBarry Smith 3519c3339decSBarry Smith Collective 3520c7afd0dbSLois Curfman McInnes 35219b94acceSBarry Smith Input Parameter: 3522f6dfbefdSBarry Smith . snes - the `SNES` context 35239b94acceSBarry Smith 352436851e7fSLois Curfman McInnes Level: beginner 352536851e7fSLois Curfman McInnes 35261cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()` 35279b94acceSBarry Smith @*/ 3528d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESDestroy(SNES *snes) 3529d71ae5a4SJacob Faibussowitsch { 35303a40ed3dSBarry Smith PetscFunctionBegin; 35313ba16761SJacob Faibussowitsch if (!*snes) PetscFunctionReturn(PETSC_SUCCESS); 3532f4f49eeaSPierre Jolivet PetscValidHeaderSpecific(*snes, SNES_CLASSID, 1); 3533f4f49eeaSPierre Jolivet if (--((PetscObject)*snes)->refct > 0) { 35349371c9d4SSatish Balay *snes = NULL; 35353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 35369371c9d4SSatish Balay } 3537d4bb536fSBarry Smith 3538f4f49eeaSPierre Jolivet PetscCall(SNESReset(*snes)); 35399566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&(*snes)->npc)); 35406b8b9a38SLisandro Dalcin 3541e04113cfSBarry Smith /* if memory was published with SAWs then destroy it */ 35429566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsViewOff((PetscObject)*snes)); 3543f4f49eeaSPierre Jolivet PetscTryTypeMethod(*snes, destroy); 35446d4c513bSLisandro Dalcin 35459566063dSJacob Faibussowitsch if ((*snes)->dm) PetscCall(DMCoarsenHookRemove((*snes)->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, *snes)); 35469566063dSJacob Faibussowitsch PetscCall(DMDestroy(&(*snes)->dm)); 35479566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&(*snes)->ksp)); 35489566063dSJacob Faibussowitsch PetscCall(SNESLineSearchDestroy(&(*snes)->linesearch)); 35496b8b9a38SLisandro Dalcin 35509566063dSJacob Faibussowitsch PetscCall(PetscFree((*snes)->kspconvctx)); 355148a46eb9SPierre Jolivet if ((*snes)->ops->convergeddestroy) PetscCall((*(*snes)->ops->convergeddestroy)((*snes)->cnvP)); 355248a46eb9SPierre Jolivet if ((*snes)->conv_hist_alloc) PetscCall(PetscFree2((*snes)->conv_hist, (*snes)->conv_hist_its)); 3553f4f49eeaSPierre Jolivet PetscCall(SNESMonitorCancel(*snes)); 3554f4f49eeaSPierre Jolivet PetscCall(SNESConvergedReasonViewCancel(*snes)); 35559566063dSJacob Faibussowitsch PetscCall(PetscHeaderDestroy(snes)); 35563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 35579b94acceSBarry Smith } 35589b94acceSBarry Smith 35599b94acceSBarry Smith /* ----------- Routines to set solver parameters ---------- */ 35609b94acceSBarry Smith 3561a8054027SBarry Smith /*@ 35620b4b7b1cSBarry Smith SNESSetLagPreconditioner - Sets when the preconditioner is rebuilt in the nonlinear solve `SNESSolve()`. 3563a8054027SBarry Smith 3564c3339decSBarry Smith Logically Collective 3565a8054027SBarry Smith 3566a8054027SBarry Smith Input Parameters: 3567f6dfbefdSBarry Smith + snes - the `SNES` context 3568d8e291bfSBarry Smith - lag - 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time 35693b4f5425SBarry Smith the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that 3570a8054027SBarry Smith 3571a8054027SBarry Smith Options Database Keys: 3572420bcc1bSBarry Smith + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple `SNESSolve()` 35733d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 3574420bcc1bSBarry Smith . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple `SNESSolve()` 35753d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 3576a8054027SBarry Smith 3577dc4c0fb0SBarry Smith Level: intermediate 3578dc4c0fb0SBarry Smith 3579420bcc1bSBarry Smith Notes: 3580a8054027SBarry Smith The default is 1 3581420bcc1bSBarry Smith 3582f6dfbefdSBarry Smith The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagPreconditionerPersists()` was called 3583d8e291bfSBarry Smith 3584f6dfbefdSBarry Smith `SNESSetLagPreconditionerPersists()` allows using the same uniform lagging (for example every second linear solve) across multiple nonlinear solves. 3585a8054027SBarry Smith 35863201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetLagPreconditionerPersists()`, 3587f6dfbefdSBarry Smith `SNESSetLagJacobianPersists()`, `SNES`, `SNESSolve()` 3588a8054027SBarry Smith @*/ 3589d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditioner(SNES snes, PetscInt lag) 3590d71ae5a4SJacob Faibussowitsch { 3591a8054027SBarry Smith PetscFunctionBegin; 35920700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 35935f80ce2aSJacob Faibussowitsch PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater"); 35945f80ce2aSJacob Faibussowitsch PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0"); 3595c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, lag, 2); 3596a8054027SBarry Smith snes->lagpreconditioner = lag; 35973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3598a8054027SBarry Smith } 3599a8054027SBarry Smith 3600efd51863SBarry Smith /*@ 3601f6dfbefdSBarry Smith SNESSetGridSequence - sets the number of steps of grid sequencing that `SNES` will do 3602efd51863SBarry Smith 3603c3339decSBarry Smith Logically Collective 3604efd51863SBarry Smith 3605efd51863SBarry Smith Input Parameters: 3606f6dfbefdSBarry Smith + snes - the `SNES` context 3607efd51863SBarry Smith - steps - the number of refinements to do, defaults to 0 3608efd51863SBarry Smith 3609f6dfbefdSBarry Smith Options Database Key: 361067b8a455SSatish Balay . -snes_grid_sequence <steps> - Use grid sequencing to generate initial guess 3611efd51863SBarry Smith 3612efd51863SBarry Smith Level: intermediate 3613efd51863SBarry Smith 36140b4b7b1cSBarry Smith Notes: 36150b4b7b1cSBarry Smith Once grid sequencing is turned on `SNESSolve()` will automatically perform the solve on each grid refinement. 36160b4b7b1cSBarry Smith 3617f6dfbefdSBarry Smith Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing. 3618c0df2a02SJed Brown 36193201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetGridSequence()`, 362054c05997SPierre Jolivet `SNESSetDM()`, `SNESSolve()` 3621efd51863SBarry Smith @*/ 3622d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetGridSequence(SNES snes, PetscInt steps) 3623d71ae5a4SJacob Faibussowitsch { 3624efd51863SBarry Smith PetscFunctionBegin; 3625efd51863SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3626efd51863SBarry Smith PetscValidLogicalCollectiveInt(snes, steps, 2); 3627efd51863SBarry Smith snes->gridsequence = steps; 36283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3629efd51863SBarry Smith } 3630efd51863SBarry Smith 3631fa19ca70SBarry Smith /*@ 3632f6dfbefdSBarry Smith SNESGetGridSequence - gets the number of steps of grid sequencing that `SNES` will do 3633fa19ca70SBarry Smith 3634c3339decSBarry Smith Logically Collective 3635fa19ca70SBarry Smith 3636fa19ca70SBarry Smith Input Parameter: 3637f6dfbefdSBarry Smith . snes - the `SNES` context 3638fa19ca70SBarry Smith 3639fa19ca70SBarry Smith Output Parameter: 3640fa19ca70SBarry Smith . steps - the number of refinements to do, defaults to 0 3641fa19ca70SBarry Smith 3642fa19ca70SBarry Smith Level: intermediate 3643fa19ca70SBarry Smith 36443201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetGridSequence()` 3645fa19ca70SBarry Smith @*/ 3646d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetGridSequence(SNES snes, PetscInt *steps) 3647d71ae5a4SJacob Faibussowitsch { 3648fa19ca70SBarry Smith PetscFunctionBegin; 3649fa19ca70SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3650fa19ca70SBarry Smith *steps = snes->gridsequence; 36513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3652fa19ca70SBarry Smith } 3653fa19ca70SBarry Smith 3654a8054027SBarry Smith /*@ 3655f6dfbefdSBarry Smith SNESGetLagPreconditioner - Return how often the preconditioner is rebuilt 3656a8054027SBarry Smith 36573f9fe445SBarry Smith Not Collective 3658a8054027SBarry Smith 3659a8054027SBarry Smith Input Parameter: 3660f6dfbefdSBarry Smith . snes - the `SNES` context 3661a8054027SBarry Smith 3662a8054027SBarry Smith Output Parameter: 3663a8054027SBarry 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 36643b4f5425SBarry Smith the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that 3665a8054027SBarry Smith 3666dc4c0fb0SBarry Smith Level: intermediate 3667dc4c0fb0SBarry Smith 3668a8054027SBarry Smith Notes: 3669a8054027SBarry Smith The default is 1 3670f6dfbefdSBarry Smith 3671a8054027SBarry Smith The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 3672a8054027SBarry Smith 36733201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3674a8054027SBarry Smith @*/ 3675d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagPreconditioner(SNES snes, PetscInt *lag) 3676d71ae5a4SJacob Faibussowitsch { 3677a8054027SBarry Smith PetscFunctionBegin; 36780700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3679a8054027SBarry Smith *lag = snes->lagpreconditioner; 36803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3681a8054027SBarry Smith } 3682a8054027SBarry Smith 3683e35cf81dSBarry Smith /*@ 3684f6dfbefdSBarry Smith SNESSetLagJacobian - Set when the Jacobian is rebuilt in the nonlinear solve. See `SNESSetLagPreconditioner()` for determining how 3685e35cf81dSBarry Smith often the preconditioner is rebuilt. 3686e35cf81dSBarry Smith 3687c3339decSBarry Smith Logically Collective 3688e35cf81dSBarry Smith 3689e35cf81dSBarry Smith Input Parameters: 3690f6dfbefdSBarry Smith + snes - the `SNES` context 3691e35cf81dSBarry 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 3692fe3ffe1eSBarry Smith the Jacobian is built etc. -2 means rebuild at next chance but then never again 3693e35cf81dSBarry Smith 3694e35cf81dSBarry Smith Options Database Keys: 369579a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 36963d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 369779a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 36983d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag. 3699e35cf81dSBarry Smith 3700dc4c0fb0SBarry Smith Level: intermediate 3701dc4c0fb0SBarry Smith 3702e35cf81dSBarry Smith Notes: 3703e35cf81dSBarry Smith The default is 1 3704f6dfbefdSBarry Smith 3705e35cf81dSBarry Smith The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 3706f6dfbefdSBarry Smith 3707fe3ffe1eSBarry 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 3708fe3ffe1eSBarry Smith at the next Newton step but never again (unless it is reset to another value) 3709e35cf81dSBarry Smith 37103201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagPreconditioner()`, `SNESGetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3711e35cf81dSBarry Smith @*/ 3712d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobian(SNES snes, PetscInt lag) 3713d71ae5a4SJacob Faibussowitsch { 3714e35cf81dSBarry Smith PetscFunctionBegin; 37150700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 37165f80ce2aSJacob Faibussowitsch PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater"); 37175f80ce2aSJacob Faibussowitsch PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0"); 3718c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, lag, 2); 3719e35cf81dSBarry Smith snes->lagjacobian = lag; 37203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3721e35cf81dSBarry Smith } 3722e35cf81dSBarry Smith 3723e35cf81dSBarry Smith /*@ 3724f6dfbefdSBarry Smith SNESGetLagJacobian - Get how often the Jacobian is rebuilt. See `SNESGetLagPreconditioner()` to determine when the preconditioner is rebuilt 3725e35cf81dSBarry Smith 37263f9fe445SBarry Smith Not Collective 3727e35cf81dSBarry Smith 3728e35cf81dSBarry Smith Input Parameter: 3729f6dfbefdSBarry Smith . snes - the `SNES` context 3730e35cf81dSBarry Smith 3731e35cf81dSBarry Smith Output Parameter: 3732e35cf81dSBarry 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 3733e35cf81dSBarry Smith the Jacobian is built etc. 3734e35cf81dSBarry Smith 3735dc4c0fb0SBarry Smith Level: intermediate 3736dc4c0fb0SBarry Smith 3737e35cf81dSBarry Smith Notes: 3738e35cf81dSBarry Smith The default is 1 3739f6dfbefdSBarry Smith 3740f6dfbefdSBarry Smith The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagJacobianPersists()` was called. 3741e35cf81dSBarry Smith 37423201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobian()`, `SNESSetLagPreconditioner()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3743e35cf81dSBarry Smith 3744e35cf81dSBarry Smith @*/ 3745d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagJacobian(SNES snes, PetscInt *lag) 3746d71ae5a4SJacob Faibussowitsch { 3747e35cf81dSBarry Smith PetscFunctionBegin; 37480700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3749e35cf81dSBarry Smith *lag = snes->lagjacobian; 37503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3751e35cf81dSBarry Smith } 3752e35cf81dSBarry Smith 375337ec4e1aSPeter Brune /*@ 3754f6dfbefdSBarry Smith SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple nonlinear solves 375537ec4e1aSPeter Brune 3756c3339decSBarry Smith Logically collective 375737ec4e1aSPeter Brune 3758d8d19677SJose E. Roman Input Parameters: 3759f6dfbefdSBarry Smith + snes - the `SNES` context 37609d7e2deaSPeter Brune - flg - jacobian lagging persists if true 376137ec4e1aSPeter Brune 376237ec4e1aSPeter Brune Options Database Keys: 376379a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 37643d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 376579a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 37663d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 37673d5a8a6aSBarry Smith 3768dc4c0fb0SBarry Smith Level: advanced 3769dc4c0fb0SBarry Smith 377095452b02SPatrick Sanan Notes: 3771420bcc1bSBarry Smith Normally when `SNESSetLagJacobian()` is used, the Jacobian is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior 3772f6dfbefdSBarry Smith 377395452b02SPatrick Sanan This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by 377437ec4e1aSPeter Brune several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several 377537ec4e1aSPeter Brune timesteps may present huge efficiency gains. 377637ec4e1aSPeter Brune 377742747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditionerPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()` 377837ec4e1aSPeter Brune @*/ 3779d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobianPersists(SNES snes, PetscBool flg) 3780d71ae5a4SJacob Faibussowitsch { 378137ec4e1aSPeter Brune PetscFunctionBegin; 378237ec4e1aSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 378337ec4e1aSPeter Brune PetscValidLogicalCollectiveBool(snes, flg, 2); 378437ec4e1aSPeter Brune snes->lagjac_persist = flg; 37853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 378637ec4e1aSPeter Brune } 378737ec4e1aSPeter Brune 378837ec4e1aSPeter Brune /*@ 3789d8e291bfSBarry Smith SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple nonlinear solves 379037ec4e1aSPeter Brune 3791c3339decSBarry Smith Logically Collective 379237ec4e1aSPeter Brune 3793d8d19677SJose E. Roman Input Parameters: 3794f6dfbefdSBarry Smith + snes - the `SNES` context 37959d7e2deaSPeter Brune - flg - preconditioner lagging persists if true 379637ec4e1aSPeter Brune 379737ec4e1aSPeter Brune Options Database Keys: 379879a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 37993d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag 380079a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 38013d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 380237ec4e1aSPeter Brune 3803dc4c0fb0SBarry Smith Level: developer 3804dc4c0fb0SBarry Smith 380595452b02SPatrick Sanan Notes: 3806420bcc1bSBarry Smith Normally when `SNESSetLagPreconditioner()` is used, the preconditioner is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior 3807f6dfbefdSBarry Smith 380895452b02SPatrick Sanan This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale 380937ec4e1aSPeter Brune by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over 381037ec4e1aSPeter Brune several timesteps may present huge efficiency gains. 381137ec4e1aSPeter Brune 38121cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobianPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagPreconditioner()` 381337ec4e1aSPeter Brune @*/ 3814d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes, PetscBool flg) 3815d71ae5a4SJacob Faibussowitsch { 381637ec4e1aSPeter Brune PetscFunctionBegin; 381737ec4e1aSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 381837ec4e1aSPeter Brune PetscValidLogicalCollectiveBool(snes, flg, 2); 381937ec4e1aSPeter Brune snes->lagpre_persist = flg; 38203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 382137ec4e1aSPeter Brune } 382237ec4e1aSPeter Brune 38239b94acceSBarry Smith /*@ 3824f6dfbefdSBarry Smith SNESSetForceIteration - force `SNESSolve()` to take at least one iteration regardless of the initial residual norm 3825be5caee7SBarry Smith 3826c3339decSBarry Smith Logically Collective 3827be5caee7SBarry Smith 3828be5caee7SBarry Smith Input Parameters: 3829f6dfbefdSBarry Smith + snes - the `SNES` context 3830f6dfbefdSBarry Smith - force - `PETSC_TRUE` require at least one iteration 3831be5caee7SBarry Smith 3832f6dfbefdSBarry Smith Options Database Key: 3833be5caee7SBarry Smith . -snes_force_iteration <force> - Sets forcing an iteration 3834be5caee7SBarry Smith 3835dc4c0fb0SBarry Smith Level: intermediate 3836dc4c0fb0SBarry Smith 3837f6dfbefdSBarry Smith Note: 3838f6dfbefdSBarry Smith This is used sometimes with `TS` to prevent `TS` from detecting a false steady state solution 3839be5caee7SBarry Smith 38403201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `TS`, `SNESSetDivergenceTolerance()` 3841be5caee7SBarry Smith @*/ 3842d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetForceIteration(SNES snes, PetscBool force) 3843d71ae5a4SJacob Faibussowitsch { 3844be5caee7SBarry Smith PetscFunctionBegin; 3845be5caee7SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3846be5caee7SBarry Smith snes->forceiteration = force; 38473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3848be5caee7SBarry Smith } 3849be5caee7SBarry Smith 385085216dc7SFande Kong /*@ 3851f6dfbefdSBarry Smith SNESGetForceIteration - Check whether or not `SNESSolve()` take at least one iteration regardless of the initial residual norm 385285216dc7SFande Kong 3853c3339decSBarry Smith Logically Collective 385485216dc7SFande Kong 38552fe279fdSBarry Smith Input Parameter: 3856f6dfbefdSBarry Smith . snes - the `SNES` context 385785216dc7SFande Kong 385885216dc7SFande Kong Output Parameter: 3859dc4c0fb0SBarry Smith . force - `PETSC_TRUE` requires at least one iteration. 386085216dc7SFande Kong 386106dd6b0eSSatish Balay Level: intermediate 386206dd6b0eSSatish Balay 38633201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetForceIteration()`, `SNESSetDivergenceTolerance()` 386485216dc7SFande Kong @*/ 3865d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetForceIteration(SNES snes, PetscBool *force) 3866d71ae5a4SJacob Faibussowitsch { 386785216dc7SFande Kong PetscFunctionBegin; 386885216dc7SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 386985216dc7SFande Kong *force = snes->forceiteration; 38703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 387185216dc7SFande Kong } 3872be5caee7SBarry Smith 3873be5caee7SBarry Smith /*@ 38740b4b7b1cSBarry Smith SNESSetTolerances - Sets various parameters used in `SNES` convergence tests. 38759b94acceSBarry Smith 3876c3339decSBarry Smith Logically Collective 3877c7afd0dbSLois Curfman McInnes 38789b94acceSBarry Smith Input Parameters: 3879f6dfbefdSBarry Smith + snes - the `SNES` context 38800b4b7b1cSBarry Smith . abstol - the absolute convergence tolerance, $ F(x^n) \le abstol $ 38810b4b7b1cSBarry Smith . rtol - the relative convergence tolerance, $ F(x^n) \le reltol * F(x^0) $ 38825358d0d4SBarry Smith . stol - convergence tolerance in terms of the norm of the change in the solution between steps, || delta x || < stol*|| x || 38830b4b7b1cSBarry Smith . maxit - the maximum number of iterations allowed in the solver, default 50. 38840b4b7b1cSBarry Smith - maxf - the maximum number of function evaluations allowed in the solver (use `PETSC_UNLIMITED` indicates no limit), default 10,000 3885fee21e36SBarry Smith 388633174efeSLois Curfman McInnes Options Database Keys: 388777e5a1f9SBarry Smith + -snes_atol <abstol> - Sets `abstol` 388877e5a1f9SBarry Smith . -snes_rtol <rtol> - Sets `rtol` 388977e5a1f9SBarry Smith . -snes_stol <stol> - Sets `stol` 389077e5a1f9SBarry Smith . -snes_max_it <maxit> - Sets `maxit` 389177e5a1f9SBarry Smith - -snes_max_funcs <maxf> - Sets `maxf` (use `unlimited` to have no maximum) 38929b94acceSBarry Smith 389336851e7fSLois Curfman McInnes Level: intermediate 389436851e7fSLois Curfman McInnes 389577e5a1f9SBarry Smith Note: 389677e5a1f9SBarry Smith All parameters must be non-negative 389777e5a1f9SBarry Smith 389877e5a1f9SBarry Smith Use `PETSC_CURRENT` to retain the current value of any parameter and `PETSC_DETERMINE` to use the default value for the given `SNES`. 389977e5a1f9SBarry Smith The default value is the value in the object when its type is set. 390077e5a1f9SBarry Smith 390177e5a1f9SBarry Smith Use `PETSC_UNLIMITED` on `maxit` or `maxf` to indicate there is no bound on the number of iterations or number of function evaluations. 390277e5a1f9SBarry Smith 390377e5a1f9SBarry Smith Fortran Note: 390477e5a1f9SBarry Smith Use `PETSC_CURRENT_INTEGER`, `PETSC_CURRENT_REAL`, `PETSC_UNLIMITED_INTEGER`, `PETSC_DETERMINE_INTEGER`, or `PETSC_DETERMINE_REAL` 390577e5a1f9SBarry Smith 39063201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESSolve()`, `SNES`, `SNESSetDivergenceTolerance()`, `SNESSetForceIteration()` 39079b94acceSBarry Smith @*/ 3908d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTolerances(SNES snes, PetscReal abstol, PetscReal rtol, PetscReal stol, PetscInt maxit, PetscInt maxf) 3909d71ae5a4SJacob Faibussowitsch { 39103a40ed3dSBarry Smith PetscFunctionBegin; 39110700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3912c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, abstol, 2); 3913c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, rtol, 3); 3914c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, stol, 4); 3915c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, maxit, 5); 3916c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, maxf, 6); 3917c5eb9154SBarry Smith 391877e5a1f9SBarry Smith if (abstol == (PetscReal)PETSC_DETERMINE) { 391977e5a1f9SBarry Smith snes->abstol = snes->default_abstol; 392077e5a1f9SBarry Smith } else if (abstol != (PetscReal)PETSC_CURRENT) { 39215f80ce2aSJacob Faibussowitsch PetscCheck(abstol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)abstol); 3922ab54825eSJed Brown snes->abstol = abstol; 3923ab54825eSJed Brown } 392477e5a1f9SBarry Smith 392577e5a1f9SBarry Smith if (rtol == (PetscReal)PETSC_DETERMINE) { 392677e5a1f9SBarry Smith snes->rtol = snes->default_rtol; 392777e5a1f9SBarry Smith } else if (rtol != (PetscReal)PETSC_CURRENT) { 39285f80ce2aSJacob 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); 3929ab54825eSJed Brown snes->rtol = rtol; 3930ab54825eSJed Brown } 393177e5a1f9SBarry Smith 393277e5a1f9SBarry Smith if (stol == (PetscReal)PETSC_DETERMINE) { 393377e5a1f9SBarry Smith snes->stol = snes->default_stol; 393477e5a1f9SBarry Smith } else if (stol != (PetscReal)PETSC_CURRENT) { 39355f80ce2aSJacob Faibussowitsch PetscCheck(stol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Step tolerance %g must be non-negative", (double)stol); 3936c60f73f4SPeter Brune snes->stol = stol; 3937ab54825eSJed Brown } 393877e5a1f9SBarry Smith 3939835f2295SStefano Zampini if (maxit == PETSC_DETERMINE) { 394077e5a1f9SBarry Smith snes->max_its = snes->default_max_its; 3941835f2295SStefano Zampini } else if (maxit == PETSC_UNLIMITED) { 394277e5a1f9SBarry Smith snes->max_its = PETSC_INT_MAX; 394377e5a1f9SBarry Smith } else if (maxit != PETSC_CURRENT) { 394463a3b9bcSJacob Faibussowitsch PetscCheck(maxit >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", maxit); 3945ab54825eSJed Brown snes->max_its = maxit; 3946ab54825eSJed Brown } 394777e5a1f9SBarry Smith 3948835f2295SStefano Zampini if (maxf == PETSC_DETERMINE) { 394977e5a1f9SBarry Smith snes->max_funcs = snes->default_max_funcs; 3950835f2295SStefano Zampini } else if (maxf == PETSC_UNLIMITED || maxf == -1) { 395177e5a1f9SBarry Smith snes->max_funcs = PETSC_UNLIMITED; 395277e5a1f9SBarry Smith } else if (maxf != PETSC_CURRENT) { 395377e5a1f9SBarry Smith PetscCheck(maxf >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations %" PetscInt_FMT " must be nonnegative", maxf); 3954ab54825eSJed Brown snes->max_funcs = maxf; 3955ab54825eSJed Brown } 39563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 39579b94acceSBarry Smith } 39589b94acceSBarry Smith 3959e4d06f11SPatrick Farrell /*@ 3960f6dfbefdSBarry Smith SNESSetDivergenceTolerance - Sets the divergence tolerance used for the `SNES` divergence test. 3961e4d06f11SPatrick Farrell 3962c3339decSBarry Smith Logically Collective 3963e4d06f11SPatrick Farrell 3964e4d06f11SPatrick Farrell Input Parameters: 3965f6dfbefdSBarry Smith + snes - the `SNES` context 39660b4b7b1cSBarry 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 39670b4b7b1cSBarry Smith is stopped due to divergence. 3968e4d06f11SPatrick Farrell 3969f6dfbefdSBarry Smith Options Database Key: 3970dc4c0fb0SBarry Smith . -snes_divergence_tolerance <divtol> - Sets `divtol` 3971e4d06f11SPatrick Farrell 3972e4d06f11SPatrick Farrell Level: intermediate 3973e4d06f11SPatrick Farrell 397477e5a1f9SBarry Smith Notes: 397577e5a1f9SBarry Smith Use `PETSC_DETERMINE` to use the default value from when the object's type was set. 3976e5cd489fSStefano Zampini 397777e5a1f9SBarry Smith Fortran Note: 397877e5a1f9SBarry Smith Use ``PETSC_DETERMINE_REAL` or `PETSC_UNLIMITED_REAL` 397977e5a1f9SBarry Smith 398077e5a1f9SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetTolerances()`, `SNESGetDivergenceTolerance()` 3981e4d06f11SPatrick Farrell @*/ 3982d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDivergenceTolerance(SNES snes, PetscReal divtol) 3983d71ae5a4SJacob Faibussowitsch { 3984e4d06f11SPatrick Farrell PetscFunctionBegin; 3985e4d06f11SPatrick Farrell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3986e4d06f11SPatrick Farrell PetscValidLogicalCollectiveReal(snes, divtol, 2); 398777e5a1f9SBarry Smith 398877e5a1f9SBarry Smith if (divtol == (PetscReal)PETSC_DETERMINE) { 398977e5a1f9SBarry Smith snes->divtol = snes->default_divtol; 399077e5a1f9SBarry Smith } else if (divtol == (PetscReal)PETSC_UNLIMITED || divtol == -1) { 399177e5a1f9SBarry Smith snes->divtol = PETSC_UNLIMITED; 399277e5a1f9SBarry Smith } else if (divtol != (PetscReal)PETSC_CURRENT) { 399377e5a1f9SBarry Smith PetscCheck(divtol >= 1.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Divergence tolerance %g must be greater than 1.0", (double)divtol); 399477e5a1f9SBarry Smith snes->divtol = divtol; 399577e5a1f9SBarry Smith } 39963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3997e4d06f11SPatrick Farrell } 3998e4d06f11SPatrick Farrell 39999b94acceSBarry Smith /*@ 40000b4b7b1cSBarry Smith SNESGetTolerances - Gets various parameters used in `SNES` convergence tests. 400133174efeSLois Curfman McInnes 4002c7afd0dbSLois Curfman McInnes Not Collective 4003c7afd0dbSLois Curfman McInnes 400477e5a1f9SBarry Smith Input Parameter: 400577e5a1f9SBarry Smith . snes - the `SNES` context 400677e5a1f9SBarry Smith 400777e5a1f9SBarry Smith Output Parameters: 40080b4b7b1cSBarry Smith + atol - the absolute convergence tolerance 40090b4b7b1cSBarry Smith . rtol - the relative convergence tolerance 401077e5a1f9SBarry Smith . stol - convergence tolerance in terms of the norm of the change in the solution between steps 40110b4b7b1cSBarry Smith . maxit - the maximum number of iterations allowed 40120b4b7b1cSBarry Smith - maxf - the maximum number of function evaluations allowed, `PETSC_UNLIMITED` indicates no bound 4013fee21e36SBarry Smith 401436851e7fSLois Curfman McInnes Level: intermediate 401536851e7fSLois Curfman McInnes 40160b4b7b1cSBarry Smith Notes: 40170b4b7b1cSBarry Smith See `SNESSetTolerances()` for details on the parameters. 40180b4b7b1cSBarry Smith 4019dc4c0fb0SBarry Smith The user can specify `NULL` for any parameter that is not needed. 4020dc4c0fb0SBarry Smith 40211cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTolerances()` 402233174efeSLois Curfman McInnes @*/ 4023d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetTolerances(SNES snes, PetscReal *atol, PetscReal *rtol, PetscReal *stol, PetscInt *maxit, PetscInt *maxf) 4024d71ae5a4SJacob Faibussowitsch { 40253a40ed3dSBarry Smith PetscFunctionBegin; 40260700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 402785385478SLisandro Dalcin if (atol) *atol = snes->abstol; 402833174efeSLois Curfman McInnes if (rtol) *rtol = snes->rtol; 4029c60f73f4SPeter Brune if (stol) *stol = snes->stol; 403033174efeSLois Curfman McInnes if (maxit) *maxit = snes->max_its; 403133174efeSLois Curfman McInnes if (maxf) *maxf = snes->max_funcs; 40323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 403333174efeSLois Curfman McInnes } 403433174efeSLois Curfman McInnes 4035e4d06f11SPatrick Farrell /*@ 4036e4d06f11SPatrick Farrell SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test. 4037e4d06f11SPatrick Farrell 4038e4d06f11SPatrick Farrell Not Collective 4039e4d06f11SPatrick Farrell 4040e4d06f11SPatrick Farrell Input Parameters: 4041f6dfbefdSBarry Smith + snes - the `SNES` context 4042e4d06f11SPatrick Farrell - divtol - divergence tolerance 4043e4d06f11SPatrick Farrell 4044e4d06f11SPatrick Farrell Level: intermediate 4045e4d06f11SPatrick Farrell 40461cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetDivergenceTolerance()` 4047e4d06f11SPatrick Farrell @*/ 4048d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDivergenceTolerance(SNES snes, PetscReal *divtol) 4049d71ae5a4SJacob Faibussowitsch { 4050e4d06f11SPatrick Farrell PetscFunctionBegin; 4051e4d06f11SPatrick Farrell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4052e4d06f11SPatrick Farrell if (divtol) *divtol = snes->divtol; 40533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4054e4d06f11SPatrick Farrell } 4055e4d06f11SPatrick Farrell 40566ba87a44SLisandro Dalcin PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *); 40576ba87a44SLisandro Dalcin 4058d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorLGRange(SNES snes, PetscInt n, PetscReal rnorm, void *monctx) 4059d71ae5a4SJacob Faibussowitsch { 4060b271bb04SBarry Smith PetscDrawLG lg; 4061b271bb04SBarry Smith PetscReal x, y, per; 4062b271bb04SBarry Smith PetscViewer v = (PetscViewer)monctx; 4063b271bb04SBarry Smith static PetscReal prev; /* should be in the context */ 4064b271bb04SBarry Smith PetscDraw draw; 4065b271bb04SBarry Smith 4066459f5d12SBarry Smith PetscFunctionBegin; 40674d4332d5SBarry Smith PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 4); 40689566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 0, &lg)); 40699566063dSJacob Faibussowitsch if (!n) PetscCall(PetscDrawLGReset(lg)); 40709566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 40719566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "Residual norm")); 4072b271bb04SBarry Smith x = (PetscReal)n; 407377b4d14cSPeter Brune if (rnorm > 0.0) y = PetscLog10Real(rnorm); 407494c9c6d3SKarl Rupp else y = -15.0; 40759566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 40766934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 40779566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 40789566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 4079b271bb04SBarry Smith } 4080b271bb04SBarry Smith 40819566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 1, &lg)); 40829566063dSJacob Faibussowitsch if (!n) PetscCall(PetscDrawLGReset(lg)); 40839566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 4084aaa8cc7dSPierre Jolivet PetscCall(PetscDrawSetTitle(draw, "% elements > .2*max element")); 40859566063dSJacob Faibussowitsch PetscCall(SNESMonitorRange_Private(snes, n, &per)); 4086b271bb04SBarry Smith x = (PetscReal)n; 4087b271bb04SBarry Smith y = 100.0 * per; 40889566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 40896934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 40909566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 40919566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 4092b271bb04SBarry Smith } 4093b271bb04SBarry Smith 40949566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 2, &lg)); 40959371c9d4SSatish Balay if (!n) { 40969371c9d4SSatish Balay prev = rnorm; 40979371c9d4SSatish Balay PetscCall(PetscDrawLGReset(lg)); 40989371c9d4SSatish Balay } 40999566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 41009566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm")); 4101b271bb04SBarry Smith x = (PetscReal)n; 4102b271bb04SBarry Smith y = (prev - rnorm) / prev; 41039566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 41046934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 41059566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 41069566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 4107b271bb04SBarry Smith } 4108b271bb04SBarry Smith 41099566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 3, &lg)); 41109566063dSJacob Faibussowitsch if (!n) PetscCall(PetscDrawLGReset(lg)); 41119566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw)); 41129566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm*(% > .2 max)")); 4113b271bb04SBarry Smith x = (PetscReal)n; 4114b271bb04SBarry Smith y = (prev - rnorm) / (prev * per); 4115b271bb04SBarry Smith if (n > 2) { /*skip initial crazy value */ 41169566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 4117b271bb04SBarry Smith } 41186934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) { 41199566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 41209566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg)); 4121b271bb04SBarry Smith } 4122b271bb04SBarry Smith prev = rnorm; 41233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4124b271bb04SBarry Smith } 4125b271bb04SBarry Smith 4126228d79bcSJed Brown /*@ 41272d157150SStefano Zampini SNESConverged - Run the convergence test and update the `SNESConvergedReason`. 41282d157150SStefano Zampini 41292d157150SStefano Zampini Collective 41302d157150SStefano Zampini 41312d157150SStefano Zampini Input Parameters: 41322d157150SStefano Zampini + snes - the `SNES` context 41332d157150SStefano Zampini . it - current iteration 41342d157150SStefano Zampini . xnorm - 2-norm of current iterate 41352d157150SStefano Zampini . snorm - 2-norm of current step 41362d157150SStefano Zampini - fnorm - 2-norm of function 41372d157150SStefano Zampini 41382d157150SStefano Zampini Level: developer 41392d157150SStefano Zampini 41402d157150SStefano Zampini Note: 4141420bcc1bSBarry Smith This routine is called by the `SNESSolve()` implementations. 41422d157150SStefano Zampini It does not typically need to be called by the user. 41432d157150SStefano Zampini 4144c948abdaSPierre Jolivet .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()` 41452d157150SStefano Zampini @*/ 41462d157150SStefano Zampini PetscErrorCode SNESConverged(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm) 41472d157150SStefano Zampini { 41482d157150SStefano Zampini PetscFunctionBegin; 41492d157150SStefano Zampini if (!snes->reason) { 41502d157150SStefano Zampini if (snes->normschedule == SNES_NORM_ALWAYS) PetscUseTypeMethod(snes, converged, it, xnorm, snorm, fnorm, &snes->reason, snes->cnvP); 41512d157150SStefano Zampini if (it == snes->max_its && !snes->reason) { 41522d157150SStefano Zampini if (snes->normschedule == SNES_NORM_ALWAYS) { 41532d157150SStefano Zampini PetscCall(PetscInfo(snes, "Maximum number of iterations has been reached: %" PetscInt_FMT "\n", snes->max_its)); 41542d157150SStefano Zampini snes->reason = SNES_DIVERGED_MAX_IT; 41552d157150SStefano Zampini } else snes->reason = SNES_CONVERGED_ITS; 41562d157150SStefano Zampini } 41572d157150SStefano Zampini } 41582d157150SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 41592d157150SStefano Zampini } 41602d157150SStefano Zampini 41612d157150SStefano Zampini /*@ 41620b4b7b1cSBarry Smith SNESMonitor - runs any `SNES` monitor routines provided with `SNESMonitor()` or the options database 4163228d79bcSJed Brown 4164c3339decSBarry Smith Collective 4165228d79bcSJed Brown 4166228d79bcSJed Brown Input Parameters: 4167f6dfbefdSBarry Smith + snes - nonlinear solver context obtained from `SNESCreate()` 41680b4b7b1cSBarry Smith . iter - current iteration number 41690b4b7b1cSBarry Smith - rnorm - current relative norm of the residual 4170228d79bcSJed Brown 4171dc4c0fb0SBarry Smith Level: developer 4172dc4c0fb0SBarry Smith 4173f6dfbefdSBarry Smith Note: 4174420bcc1bSBarry Smith This routine is called by the `SNESSolve()` implementations. 4175228d79bcSJed Brown It does not typically need to be called by the user. 4176228d79bcSJed Brown 41771cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorSet()` 4178228d79bcSJed Brown @*/ 4179d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitor(SNES snes, PetscInt iter, PetscReal rnorm) 4180d71ae5a4SJacob Faibussowitsch { 41817a03ce2fSLisandro Dalcin PetscInt i, n = snes->numbermonitors; 41827a03ce2fSLisandro Dalcin 41837a03ce2fSLisandro Dalcin PetscFunctionBegin; 41845f3c5e7aSBarry Smith if (n > 0) SNESCheckFunctionNorm(snes, rnorm); 41859566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(snes->vec_sol)); 418648a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall((*snes->monitor[i])(snes, iter, rnorm, snes->monitorcontext[i])); 41879566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(snes->vec_sol)); 41883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 41897a03ce2fSLisandro Dalcin } 41907a03ce2fSLisandro Dalcin 41919b94acceSBarry Smith /* ------------ Routines to set performance monitoring options ----------- */ 41929b94acceSBarry Smith 4193bf388a1fSBarry Smith /*MC 4194f6dfbefdSBarry Smith SNESMonitorFunction - functional form passed to `SNESMonitorSet()` to monitor convergence of nonlinear solver 4195bf388a1fSBarry Smith 4196bf388a1fSBarry Smith Synopsis: 4197aaa7dc30SBarry Smith #include <petscsnes.h> 419837fdd005SBarry Smith PetscErrorCode SNESMonitorFunction(SNES snes, PetscInt its, PetscReal norm, void *mctx) 4199bf388a1fSBarry Smith 4200c3339decSBarry Smith Collective 42011843f636SBarry Smith 42021843f636SBarry Smith Input Parameters: 4203f6dfbefdSBarry Smith + snes - the `SNES` context 4204bf388a1fSBarry Smith . its - iteration number 4205bf388a1fSBarry Smith . norm - 2-norm function value (may be estimated) 4206bf388a1fSBarry Smith - mctx - [optional] monitoring context 4207bf388a1fSBarry Smith 4208878cb397SSatish Balay Level: advanced 4209878cb397SSatish Balay 42101cc06b55SBarry Smith .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSet()`, `SNESMonitorGet()` 4211bf388a1fSBarry Smith M*/ 4212bf388a1fSBarry Smith 42139b94acceSBarry Smith /*@C 4214a6570f20SBarry Smith SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every 42150b4b7b1cSBarry Smith iteration of the `SNES` nonlinear solver to display the iteration's 42169b94acceSBarry Smith progress. 42179b94acceSBarry Smith 4218c3339decSBarry Smith Logically Collective 4219fee21e36SBarry Smith 4220c7afd0dbSLois Curfman McInnes Input Parameters: 4221f6dfbefdSBarry Smith + snes - the `SNES` context 422220f4b53cSBarry Smith . f - the monitor function, for the calling sequence see `SNESMonitorFunction` 4223420bcc1bSBarry Smith . mctx - [optional] user-defined context for private data for the monitor routine (use `NULL` if no context is desired) 422449abdd8aSBarry Smith - monitordestroy - [optional] routine that frees monitor context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence 42259b94acceSBarry Smith 42269665c990SLois Curfman McInnes Options Database Keys: 4227f6dfbefdSBarry Smith + -snes_monitor - sets `SNESMonitorDefault()` 4228798534f6SMatthew G. Knepley . -snes_monitor draw::draw_lg - sets line graph monitor, 4229dc4c0fb0SBarry 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 4230c7afd0dbSLois Curfman McInnes the options database. 42319665c990SLois Curfman McInnes 4232dc4c0fb0SBarry Smith Level: intermediate 4233dc4c0fb0SBarry Smith 4234f6dfbefdSBarry Smith Note: 42356bc08f3fSLois Curfman McInnes Several different monitoring routines may be set by calling 4236f6dfbefdSBarry Smith `SNESMonitorSet()` multiple times; all will be called in the 42376bc08f3fSLois Curfman McInnes order in which they were set. 4238639f9d9dSBarry Smith 4239420bcc1bSBarry Smith Fortran Note: 4240f6dfbefdSBarry Smith Only a single monitor function can be set for each `SNES` object 4241025f1a04SBarry Smith 424249abdd8aSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESMonitorDefault()`, `SNESMonitorCancel()`, `SNESMonitorFunction`, `PetscCtxDestroyFn` 42439b94acceSBarry Smith @*/ 424449abdd8aSBarry Smith PetscErrorCode SNESMonitorSet(SNES snes, PetscErrorCode (*f)(SNES, PetscInt, PetscReal, void *), void *mctx, PetscCtxDestroyFn *monitordestroy) 4245d71ae5a4SJacob Faibussowitsch { 4246b90d0a6eSBarry Smith PetscInt i; 424778064530SBarry Smith PetscBool identical; 4248b90d0a6eSBarry Smith 42493a40ed3dSBarry Smith PetscFunctionBegin; 42500700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4251b90d0a6eSBarry Smith for (i = 0; i < snes->numbermonitors; i++) { 42529566063dSJacob Faibussowitsch PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))f, mctx, monitordestroy, (PetscErrorCode (*)(void))snes->monitor[i], snes->monitorcontext[i], snes->monitordestroy[i], &identical)); 42533ba16761SJacob Faibussowitsch if (identical) PetscFunctionReturn(PETSC_SUCCESS); 4254649052a6SBarry Smith } 42555f80ce2aSJacob Faibussowitsch PetscCheck(snes->numbermonitors < MAXSNESMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set"); 42566e4dcb14SBarry Smith snes->monitor[snes->numbermonitors] = f; 4257b8a78c4aSBarry Smith snes->monitordestroy[snes->numbermonitors] = monitordestroy; 4258835f2295SStefano Zampini snes->monitorcontext[snes->numbermonitors++] = mctx; 42593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 42609b94acceSBarry Smith } 42619b94acceSBarry Smith 4262a278d85bSSatish Balay /*@ 4263f6dfbefdSBarry Smith SNESMonitorCancel - Clears all the monitor functions for a `SNES` object. 42645cd90555SBarry Smith 4265c3339decSBarry Smith Logically Collective 4266c7afd0dbSLois Curfman McInnes 42672fe279fdSBarry Smith Input Parameter: 4268f6dfbefdSBarry Smith . snes - the `SNES` context 42695cd90555SBarry Smith 42701a480d89SAdministrator Options Database Key: 4271a6570f20SBarry Smith . -snes_monitor_cancel - cancels all monitors that have been hardwired 4272dc4c0fb0SBarry Smith into a code by calls to `SNESMonitorSet()`, but does not cancel those 4273c7afd0dbSLois Curfman McInnes set via the options database 42745cd90555SBarry Smith 4275dc4c0fb0SBarry Smith Level: intermediate 4276dc4c0fb0SBarry Smith 4277f6dfbefdSBarry Smith Note: 4278f6dfbefdSBarry Smith There is no way to clear one specific monitor from a `SNES` object. 42795cd90555SBarry Smith 42801cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorGet()`, `SNESMonitorDefault()`, `SNESMonitorSet()` 42815cd90555SBarry Smith @*/ 4282d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorCancel(SNES snes) 4283d71ae5a4SJacob Faibussowitsch { 4284d952e501SBarry Smith PetscInt i; 4285d952e501SBarry Smith 42865cd90555SBarry Smith PetscFunctionBegin; 42870700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4288d952e501SBarry Smith for (i = 0; i < snes->numbermonitors; i++) { 428948a46eb9SPierre Jolivet if (snes->monitordestroy[i]) PetscCall((*snes->monitordestroy[i])(&snes->monitorcontext[i])); 4290d952e501SBarry Smith } 42915cd90555SBarry Smith snes->numbermonitors = 0; 42923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 42935cd90555SBarry Smith } 42945cd90555SBarry Smith 4295bf388a1fSBarry Smith /*MC 4296bf388a1fSBarry Smith SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver 4297bf388a1fSBarry Smith 4298bf388a1fSBarry Smith Synopsis: 4299aaa7dc30SBarry Smith #include <petscsnes.h> 430037fdd005SBarry Smith PetscErrorCode SNESConvergenceTest(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *cctx) 4301bf388a1fSBarry Smith 4302c3339decSBarry Smith Collective 43031843f636SBarry Smith 43041843f636SBarry Smith Input Parameters: 4305f6dfbefdSBarry Smith + snes - the `SNES` context 4306bf388a1fSBarry Smith . it - current iteration (0 is the first and is before any Newton step) 4307bf388a1fSBarry Smith . xnorm - 2-norm of current iterate 4308bf388a1fSBarry Smith . gnorm - 2-norm of current step 43091843f636SBarry Smith . f - 2-norm of function 43101843f636SBarry Smith - cctx - [optional] convergence context 43111843f636SBarry Smith 43121843f636SBarry Smith Output Parameter: 43131843f636SBarry Smith . reason - reason for convergence/divergence, only needs to be set when convergence or divergence is detected 4314bf388a1fSBarry Smith 4315878cb397SSatish Balay Level: intermediate 4316bf388a1fSBarry Smith 4317c948abdaSPierre Jolivet .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()` 4318bf388a1fSBarry Smith M*/ 4319bf388a1fSBarry Smith 43209b94acceSBarry Smith /*@C 43219b94acceSBarry Smith SNESSetConvergenceTest - Sets the function that is to be used 43229b94acceSBarry Smith to test for convergence of the nonlinear iterative solution. 43239b94acceSBarry Smith 4324c3339decSBarry Smith Logically Collective 4325fee21e36SBarry Smith 4326c7afd0dbSLois Curfman McInnes Input Parameters: 4327f6dfbefdSBarry Smith + snes - the `SNES` context 4328e4094ef1SJacob Faibussowitsch . SNESConvergenceTestFunction - routine to test for convergence 4329dc4c0fb0SBarry Smith . cctx - [optional] context for private data for the convergence routine (may be `NULL`) 4330dc4c0fb0SBarry Smith - destroy - [optional] destructor for the context (may be `NULL`; `PETSC_NULL_FUNCTION` in Fortran) 43319b94acceSBarry Smith 433236851e7fSLois Curfman McInnes Level: advanced 433336851e7fSLois Curfman McInnes 43341cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedDefault()`, `SNESConvergedSkip()`, `SNESConvergenceTestFunction` 43359b94acceSBarry Smith @*/ 4336d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceTest(SNES snes, PetscErrorCode (*SNESConvergenceTestFunction)(SNES, PetscInt, PetscReal, PetscReal, PetscReal, SNESConvergedReason *, void *), void *cctx, PetscErrorCode (*destroy)(void *)) 4337d71ae5a4SJacob Faibussowitsch { 43383a40ed3dSBarry Smith PetscFunctionBegin; 43390700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4340e2a6519dSDmitry Karpeev if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip; 43411baa6e33SBarry Smith if (snes->ops->convergeddestroy) PetscCall((*snes->ops->convergeddestroy)(snes->cnvP)); 4342bf388a1fSBarry Smith snes->ops->converged = SNESConvergenceTestFunction; 43437f7931b9SBarry Smith snes->ops->convergeddestroy = destroy; 434485385478SLisandro Dalcin snes->cnvP = cctx; 43453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 43469b94acceSBarry Smith } 43479b94acceSBarry Smith 434852baeb72SSatish Balay /*@ 43490b4b7b1cSBarry Smith SNESGetConvergedReason - Gets the reason the `SNES` iteration was stopped, which may be due to convergence, divergence, or stagnation 4350184914b5SBarry Smith 4351184914b5SBarry Smith Not Collective 4352184914b5SBarry Smith 4353184914b5SBarry Smith Input Parameter: 4354f6dfbefdSBarry Smith . snes - the `SNES` context 4355184914b5SBarry Smith 4356184914b5SBarry Smith Output Parameter: 4357f6dfbefdSBarry Smith . reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` for the individual convergence tests for complete lists 4358184914b5SBarry Smith 4359f6dfbefdSBarry Smith Options Database Key: 43606a4d7782SBarry Smith . -snes_converged_reason - prints the reason to standard out 43616a4d7782SBarry Smith 4362184914b5SBarry Smith Level: intermediate 4363184914b5SBarry Smith 4364f6dfbefdSBarry Smith Note: 4365f6dfbefdSBarry Smith Should only be called after the call the `SNESSolve()` is complete, if it is called earlier it returns the value `SNES__CONVERGED_ITERATING`. 4366184914b5SBarry Smith 43671cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESSetConvergedReason()`, `SNESConvergedReason`, `SNESGetConvergedReasonString()` 4368184914b5SBarry Smith @*/ 4369d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReason(SNES snes, SNESConvergedReason *reason) 4370d71ae5a4SJacob Faibussowitsch { 4371184914b5SBarry Smith PetscFunctionBegin; 43720700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 43734f572ea9SToby Isaac PetscAssertPointer(reason, 2); 4374184914b5SBarry Smith *reason = snes->reason; 43753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4376184914b5SBarry Smith } 4377184914b5SBarry Smith 4378c4421ceaSFande Kong /*@C 4379f6dfbefdSBarry Smith SNESGetConvergedReasonString - Return a human readable string for `SNESConvergedReason` 4380c4421ceaSFande Kong 4381c4421ceaSFande Kong Not Collective 4382c4421ceaSFande Kong 4383c4421ceaSFande Kong Input Parameter: 4384f6dfbefdSBarry Smith . snes - the `SNES` context 4385c4421ceaSFande Kong 4386c4421ceaSFande Kong Output Parameter: 4387dc4c0fb0SBarry Smith . strreason - a human readable string that describes `SNES` converged reason 4388c4421ceaSFande Kong 438999c90e12SSatish Balay Level: beginner 4390c4421ceaSFande Kong 43911cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetConvergedReason()` 4392c4421ceaSFande Kong @*/ 4393d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReasonString(SNES snes, const char **strreason) 4394d71ae5a4SJacob Faibussowitsch { 4395c4421ceaSFande Kong PetscFunctionBegin; 4396c4421ceaSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 43974f572ea9SToby Isaac PetscAssertPointer(strreason, 2); 4398c4421ceaSFande Kong *strreason = SNESConvergedReasons[snes->reason]; 43993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4400c4421ceaSFande Kong } 4401c4421ceaSFande Kong 440233866048SMatthew G. Knepley /*@ 4403f6dfbefdSBarry Smith SNESSetConvergedReason - Sets the reason the `SNES` iteration was stopped. 440433866048SMatthew G. Knepley 440533866048SMatthew G. Knepley Not Collective 440633866048SMatthew G. Knepley 440733866048SMatthew G. Knepley Input Parameters: 4408f6dfbefdSBarry Smith + snes - the `SNES` context 4409f6dfbefdSBarry Smith - reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` or the 441033866048SMatthew G. Knepley manual pages for the individual convergence tests for complete lists 441133866048SMatthew G. Knepley 4412f6dfbefdSBarry Smith Level: developer 4413f6dfbefdSBarry Smith 4414420bcc1bSBarry Smith Developer Note: 4415f6dfbefdSBarry Smith Called inside the various `SNESSolve()` implementations 441633866048SMatthew G. Knepley 44171cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetConvergedReason()`, `SNESSetConvergenceTest()`, `SNESConvergedReason` 441833866048SMatthew G. Knepley @*/ 4419d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergedReason(SNES snes, SNESConvergedReason reason) 4420d71ae5a4SJacob Faibussowitsch { 442133866048SMatthew G. Knepley PetscFunctionBegin; 442233866048SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 44235f3c5e7aSBarry Smith PetscCheck(!snes->errorifnotconverged || reason > 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "SNES code should have previously errored due to negative reason"); 442433866048SMatthew G. Knepley snes->reason = reason; 44253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 442633866048SMatthew G. Knepley } 442733866048SMatthew G. Knepley 4428c9005455SLois Curfman McInnes /*@ 4429420bcc1bSBarry Smith SNESSetConvergenceHistory - Sets the arrays used to hold the convergence history. 4430c9005455SLois Curfman McInnes 4431c3339decSBarry Smith Logically Collective 4432fee21e36SBarry Smith 4433c7afd0dbSLois Curfman McInnes Input Parameters: 4434f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 44358c7482ecSBarry Smith . a - array to hold history, this array will contain the function norms computed at each step 4436cd5578b5SBarry Smith . its - integer array holds the number of linear iterations for each solve. 4437420bcc1bSBarry Smith . na - size of `a` and `its` 4438f6dfbefdSBarry Smith - reset - `PETSC_TRUE` indicates each new nonlinear solve resets the history counter to zero, 4439758f92a0SBarry Smith else it continues storing new values for new nonlinear solves after the old ones 4440c7afd0dbSLois Curfman McInnes 4441dc4c0fb0SBarry Smith Level: intermediate 4442dc4c0fb0SBarry Smith 4443308dcc3eSBarry Smith Notes: 4444ce78bad3SBarry 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 444577e5a1f9SBarry Smith default array of length 1,000 is allocated. 4446308dcc3eSBarry Smith 4447c9005455SLois Curfman McInnes This routine is useful, e.g., when running a code for purposes 4448c9005455SLois Curfman McInnes of accurate performance monitoring, when no I/O should be done 4449c9005455SLois Curfman McInnes during the section of code that is being timed. 4450c9005455SLois Curfman McInnes 4451420bcc1bSBarry Smith If the arrays run out of space after a number of iterations then the later values are not saved in the history 4452420bcc1bSBarry Smith 44531cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetConvergenceHistory()` 4454c9005455SLois Curfman McInnes @*/ 4455d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceHistory(SNES snes, PetscReal a[], PetscInt its[], PetscInt na, PetscBool reset) 4456d71ae5a4SJacob Faibussowitsch { 44573a40ed3dSBarry Smith PetscFunctionBegin; 44580700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 44594f572ea9SToby Isaac if (a) PetscAssertPointer(a, 2); 44604f572ea9SToby Isaac if (its) PetscAssertPointer(its, 3); 44617a1ec6d4SBarry Smith if (!a) { 446277e5a1f9SBarry Smith if (na == PETSC_DECIDE) na = 1000; 44639566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(na, &a, na, &its)); 4464071fcb05SBarry Smith snes->conv_hist_alloc = PETSC_TRUE; 4465308dcc3eSBarry Smith } 4466c9005455SLois Curfman McInnes snes->conv_hist = a; 4467758f92a0SBarry Smith snes->conv_hist_its = its; 4468115dd874SBarry Smith snes->conv_hist_max = (size_t)na; 4469a12bc48fSLisandro Dalcin snes->conv_hist_len = 0; 4470758f92a0SBarry Smith snes->conv_hist_reset = reset; 44713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4472758f92a0SBarry Smith } 4473758f92a0SBarry Smith 4474d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB) 4475c6db04a5SJed Brown #include <engine.h> /* MATLAB include file */ 4476c6db04a5SJed Brown #include <mex.h> /* MATLAB include file */ 447799e0435eSBarry Smith 4478d71ae5a4SJacob Faibussowitsch PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes) 4479d71ae5a4SJacob Faibussowitsch { 4480308dcc3eSBarry Smith mxArray *mat; 4481308dcc3eSBarry Smith PetscInt i; 4482308dcc3eSBarry Smith PetscReal *ar; 4483308dcc3eSBarry Smith 4484308dcc3eSBarry Smith mat = mxCreateDoubleMatrix(snes->conv_hist_len, 1, mxREAL); 4485308dcc3eSBarry Smith ar = (PetscReal *)mxGetData(mat); 4486f5af7f23SKarl Rupp for (i = 0; i < snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i]; 448711cc89d2SBarry Smith return mat; 4488308dcc3eSBarry Smith } 4489308dcc3eSBarry Smith #endif 4490308dcc3eSBarry Smith 44910c4c9dddSBarry Smith /*@C 4492420bcc1bSBarry Smith SNESGetConvergenceHistory - Gets the arrays used to hold the convergence history. 4493758f92a0SBarry Smith 44943f9fe445SBarry Smith Not Collective 4495758f92a0SBarry Smith 4496758f92a0SBarry Smith Input Parameter: 4497f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 4498758f92a0SBarry Smith 4499758f92a0SBarry Smith Output Parameters: 4500f6dfbefdSBarry Smith + a - array to hold history, usually was set with `SNESSetConvergenceHistory()` 4501758f92a0SBarry Smith . its - integer array holds the number of linear iterations (or 4502758f92a0SBarry Smith negative if not converged) for each solve. 450320f4b53cSBarry Smith - na - size of `a` and `its` 4504758f92a0SBarry Smith 4505dc4c0fb0SBarry Smith Level: intermediate 4506dc4c0fb0SBarry Smith 450720f4b53cSBarry Smith Note: 450820f4b53cSBarry Smith This routine is useful, e.g., when running a code for purposes 450920f4b53cSBarry Smith of accurate performance monitoring, when no I/O should be done 451020f4b53cSBarry Smith during the section of code that is being timed. 451120f4b53cSBarry Smith 4512ce78bad3SBarry Smith Fortran Notes: 4513ce78bad3SBarry Smith Return the arrays with ``SNESRestoreConvergenceHistory()` 4514ce78bad3SBarry Smith 4515ce78bad3SBarry Smith Use the arguments 4516dc4c0fb0SBarry Smith .vb 4517ce78bad3SBarry Smith PetscReal, pointer :: a(:) 4518ce78bad3SBarry Smith PetscInt, pointer :: its(:) 4519dc4c0fb0SBarry Smith .ve 4520758f92a0SBarry Smith 45211cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceHistory()` 4522758f92a0SBarry Smith @*/ 4523d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergenceHistory(SNES snes, PetscReal *a[], PetscInt *its[], PetscInt *na) 4524d71ae5a4SJacob Faibussowitsch { 4525758f92a0SBarry Smith PetscFunctionBegin; 45260700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4527758f92a0SBarry Smith if (a) *a = snes->conv_hist; 4528758f92a0SBarry Smith if (its) *its = snes->conv_hist_its; 4529115dd874SBarry Smith if (na) *na = (PetscInt)snes->conv_hist_len; 45303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4531c9005455SLois Curfman McInnes } 4532c9005455SLois Curfman McInnes 4533ac226902SBarry Smith /*@C 453476b2cf59SMatthew Knepley SNESSetUpdate - Sets the general-purpose update function called 4535eec8f646SJed Brown at the beginning of every iteration of the nonlinear solve. Specifically 453653e5d35bSStefano Zampini it is called just before the Jacobian is "evaluated" and after the function 453753e5d35bSStefano Zampini evaluation. 453876b2cf59SMatthew Knepley 4539c3339decSBarry Smith Logically Collective 454076b2cf59SMatthew Knepley 454176b2cf59SMatthew Knepley Input Parameters: 4542a2b725a8SWilliam Gropp + snes - The nonlinear solver context 454353e5d35bSStefano Zampini - func - The update function; for calling sequence see `SNESUpdateFn` 454476b2cf59SMatthew Knepley 4545fe97e370SBarry Smith Level: advanced 4546fe97e370SBarry Smith 4547420bcc1bSBarry Smith Notes: 4548f6dfbefdSBarry 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 4549f6dfbefdSBarry Smith to `SNESSetFunction()`, or `SNESSetPicard()` 455053e5d35bSStefano Zampini This is not used by most users, and it is intended to provide a general hook that is run 455153e5d35bSStefano Zampini right before the direction step is computed. 4552ce78bad3SBarry Smith 455353e5d35bSStefano Zampini Users are free to modify the current residual vector, 455453e5d35bSStefano Zampini the current linearization point, or any other vector associated to the specific solver used. 455553e5d35bSStefano Zampini If such modifications take place, it is the user responsibility to update all the relevant 4556ce78bad3SBarry Smith vectors. For example, if one is adjusting the model parameters at each Newton step their code may look like 4557ce78bad3SBarry Smith .vb 4558ce78bad3SBarry Smith PetscErrorCode update(SNES snes, PetscInt iteration) 4559ce78bad3SBarry Smith { 4560ce78bad3SBarry Smith PetscFunctionBeginUser; 4561ce78bad3SBarry Smith if (iteration > 0) { 4562ce78bad3SBarry Smith // update the model parameters here 4563ce78bad3SBarry Smith Vec x,f; 4564ce78bad3SBarry Smith PetscCall(SNESGetSolution(snes,&x)); 4565ce78bad3SBarry Smith PetcCall(SNESGetFunction(snes,&f,NULL,NULL)); 4566ce78bad3SBarry Smith PetscCall(SNESComputeFunction(snes,x,f)); 4567ce78bad3SBarry Smith } 4568ce78bad3SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 4569ce78bad3SBarry Smith } 4570ce78bad3SBarry Smith .ve 457176b2cf59SMatthew Knepley 4572aaa8cc7dSPierre 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. 45736b7fb656SBarry Smith 4574e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetJacobian()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRSetPostCheck()`, 457553e5d35bSStefano Zampini `SNESMonitorSet()` 457676b2cf59SMatthew Knepley @*/ 457753e5d35bSStefano Zampini PetscErrorCode SNESSetUpdate(SNES snes, SNESUpdateFn *func) 4578d71ae5a4SJacob Faibussowitsch { 457976b2cf59SMatthew Knepley PetscFunctionBegin; 45800700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4581e7788613SBarry Smith snes->ops->update = func; 45823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 458376b2cf59SMatthew Knepley } 458476b2cf59SMatthew Knepley 4585ffeef943SBarry Smith /*@ 4586f6dfbefdSBarry Smith SNESConvergedReasonView - Displays the reason a `SNES` solve converged or diverged to a viewer 45872a359c20SBarry Smith 4588c3339decSBarry Smith Collective 45892a359c20SBarry Smith 4590e4094ef1SJacob Faibussowitsch Input Parameters: 4591f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 45922a359c20SBarry Smith - viewer - the viewer to display the reason 45932a359c20SBarry Smith 45942a359c20SBarry Smith Options Database Keys: 4595ee300463SSatish Balay + -snes_converged_reason - print reason for converged or diverged, also prints number of iterations 4596ee300463SSatish Balay - -snes_converged_reason ::failed - only print reason and number of iterations when diverged 4597eafd5ff0SAlex Lindsay 4598420bcc1bSBarry Smith Level: beginner 4599420bcc1bSBarry Smith 4600f6dfbefdSBarry Smith Note: 4601f6dfbefdSBarry Smith To change the format of the output call `PetscViewerPushFormat`(viewer,format) before this call. Use `PETSC_VIEWER_DEFAULT` for the default, 4602f6dfbefdSBarry Smith use `PETSC_VIEWER_FAILED` to only display a reason if it fails. 46032a359c20SBarry Smith 46041cc06b55SBarry Smith .seealso: [](ch_snes), `SNESConvergedReason`, `PetscViewer`, `SNES`, 4605f6dfbefdSBarry Smith `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, 4606f6dfbefdSBarry Smith `SNESConvergedReasonViewFromOptions()`, 4607db781477SPatrick Sanan `PetscViewerPushFormat()`, `PetscViewerPopFormat()` 46082a359c20SBarry Smith @*/ 4609d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonView(SNES snes, PetscViewer viewer) 4610d71ae5a4SJacob Faibussowitsch { 461175cca76cSMatthew G. Knepley PetscViewerFormat format; 46122a359c20SBarry Smith PetscBool isAscii; 46132a359c20SBarry Smith 46142a359c20SBarry Smith PetscFunctionBegin; 461519a666eeSBarry Smith if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)); 46169566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii)); 46172a359c20SBarry Smith if (isAscii) { 46189566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 461965bf60d2SBarry Smith PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel + 1)); 462075cca76cSMatthew G. Knepley if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 462175cca76cSMatthew G. Knepley DM dm; 462275cca76cSMatthew G. Knepley Vec u; 462375cca76cSMatthew G. Knepley PetscDS prob; 462475cca76cSMatthew G. Knepley PetscInt Nf, f; 462595cbbfd3SMatthew G. Knepley PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *); 462695cbbfd3SMatthew G. Knepley void **exactCtx; 462775cca76cSMatthew G. Knepley PetscReal error; 462875cca76cSMatthew G. Knepley 46299566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 46309566063dSJacob Faibussowitsch PetscCall(SNESGetSolution(snes, &u)); 46319566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob)); 46329566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(prob, &Nf)); 46339566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(Nf, &exactSol, Nf, &exactCtx)); 46349566063dSJacob Faibussowitsch for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f])); 46359566063dSJacob Faibussowitsch PetscCall(DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error)); 46369566063dSJacob Faibussowitsch PetscCall(PetscFree2(exactSol, exactCtx)); 46379566063dSJacob Faibussowitsch if (error < 1.0e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n")); 463863a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", (double)error)); 463975cca76cSMatthew G. Knepley } 4640eafd5ff0SAlex Lindsay if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) { 46412a359c20SBarry Smith if (((PetscObject)snes)->prefix) { 464263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter)); 46432a359c20SBarry Smith } else { 464463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve converged due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter)); 46452a359c20SBarry Smith } 4646eafd5ff0SAlex Lindsay } else if (snes->reason <= 0) { 46472a359c20SBarry Smith if (((PetscObject)snes)->prefix) { 464863a3b9bcSJacob 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)); 46492a359c20SBarry Smith } else { 465063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve did not converge due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter)); 46512a359c20SBarry Smith } 46522a359c20SBarry Smith } 465365bf60d2SBarry Smith PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel + 1)); 46542a359c20SBarry Smith } 46553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 46562a359c20SBarry Smith } 46572a359c20SBarry Smith 4658c4421ceaSFande Kong /*@C 4659c4421ceaSFande Kong SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the 4660aaa8cc7dSPierre Jolivet end of the nonlinear solver to display the convergence reason of the nonlinear solver. 4661c4421ceaSFande Kong 4662c3339decSBarry Smith Logically Collective 4663c4421ceaSFande Kong 4664c4421ceaSFande Kong Input Parameters: 4665f6dfbefdSBarry Smith + snes - the `SNES` context 4666420bcc1bSBarry Smith . f - the `SNESConvergedReason` view function 4667420bcc1bSBarry Smith . vctx - [optional] user-defined context for private data for the `SNESConvergedReason` view function (use `NULL` if no context is desired) 466849abdd8aSBarry Smith - reasonviewdestroy - [optional] routine that frees the context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence 4669420bcc1bSBarry Smith 4670420bcc1bSBarry Smith Calling sequence of `f`: 4671420bcc1bSBarry Smith + snes - the `SNES` context 467249abdd8aSBarry Smith - vctx - [optional] context for private data for the function 4673c4421ceaSFande Kong 4674c4421ceaSFande Kong Options Database Keys: 4675f6dfbefdSBarry Smith + -snes_converged_reason - sets a default `SNESConvergedReasonView()` 4676420bcc1bSBarry Smith - -snes_converged_reason_view_cancel - cancels all converged reason viewers that have been hardwired into a code by 4677420bcc1bSBarry Smith calls to `SNESConvergedReasonViewSet()`, but does not cancel those set via the options database. 4678c4421ceaSFande Kong 4679dc4c0fb0SBarry Smith Level: intermediate 4680dc4c0fb0SBarry Smith 4681f6dfbefdSBarry Smith Note: 4682c4421ceaSFande Kong Several different converged reason view routines may be set by calling 4683f6dfbefdSBarry Smith `SNESConvergedReasonViewSet()` multiple times; all will be called in the 4684c4421ceaSFande Kong order in which they were set. 4685c4421ceaSFande Kong 468649abdd8aSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`, `SNESConvergedReasonViewCancel()`, 468749abdd8aSBarry Smith `PetscCtxDestroyFn` 4688c4421ceaSFande Kong @*/ 468949abdd8aSBarry Smith PetscErrorCode SNESConvergedReasonViewSet(SNES snes, PetscErrorCode (*f)(SNES snes, void *vctx), void *vctx, PetscCtxDestroyFn *reasonviewdestroy) 4690d71ae5a4SJacob Faibussowitsch { 4691c4421ceaSFande Kong PetscInt i; 4692c4421ceaSFande Kong PetscBool identical; 4693c4421ceaSFande Kong 4694c4421ceaSFande Kong PetscFunctionBegin; 4695c4421ceaSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4696c4421ceaSFande Kong for (i = 0; i < snes->numberreasonviews; i++) { 46979566063dSJacob Faibussowitsch PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))f, vctx, reasonviewdestroy, (PetscErrorCode (*)(void))snes->reasonview[i], snes->reasonviewcontext[i], snes->reasonviewdestroy[i], &identical)); 46983ba16761SJacob Faibussowitsch if (identical) PetscFunctionReturn(PETSC_SUCCESS); 4699c4421ceaSFande Kong } 47005f80ce2aSJacob Faibussowitsch PetscCheck(snes->numberreasonviews < MAXSNESREASONVIEWS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many SNES reasonview set"); 4701c4421ceaSFande Kong snes->reasonview[snes->numberreasonviews] = f; 4702c4421ceaSFande Kong snes->reasonviewdestroy[snes->numberreasonviews] = reasonviewdestroy; 4703835f2295SStefano Zampini snes->reasonviewcontext[snes->numberreasonviews++] = vctx; 47043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4705c4421ceaSFande Kong } 4706c4421ceaSFande Kong 470791f3e32bSBarry Smith /*@ 4708420bcc1bSBarry Smith SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a `SNESConvergedReason` is to be viewed at the end of `SNESSolve()` 47090b4b7b1cSBarry Smith All the user-provided viewer routines set with `SNESConvergedReasonViewSet()` will be called, if they exist. 47102a359c20SBarry Smith 4711c3339decSBarry Smith Collective 47122a359c20SBarry Smith 47132fe279fdSBarry Smith Input Parameter: 4714f6dfbefdSBarry Smith . snes - the `SNES` object 47152a359c20SBarry Smith 4716f6dfbefdSBarry Smith Level: advanced 47172a359c20SBarry Smith 47181cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESConvergedReasonViewSet()`, `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, 4719f6dfbefdSBarry Smith `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()` 47202a359c20SBarry Smith @*/ 4721d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes) 4722d71ae5a4SJacob Faibussowitsch { 47232a359c20SBarry Smith static PetscBool incall = PETSC_FALSE; 47242a359c20SBarry Smith 47252a359c20SBarry Smith PetscFunctionBegin; 47263ba16761SJacob Faibussowitsch if (incall) PetscFunctionReturn(PETSC_SUCCESS); 47272a359c20SBarry Smith incall = PETSC_TRUE; 4728c4421ceaSFande Kong 4729c4421ceaSFande Kong /* All user-provided viewers are called first, if they exist. */ 473036d43d94SBarry Smith for (PetscInt i = 0; i < snes->numberreasonviews; i++) PetscCall((*snes->reasonview[i])(snes, snes->reasonviewcontext[i])); 4731c4421ceaSFande Kong 4732c4421ceaSFande Kong /* Call PETSc default routine if users ask for it */ 473336d43d94SBarry Smith if (snes->convergedreasonviewer) { 473436d43d94SBarry Smith PetscCall(PetscViewerPushFormat(snes->convergedreasonviewer, snes->convergedreasonformat)); 473536d43d94SBarry Smith PetscCall(SNESConvergedReasonView(snes, snes->convergedreasonviewer)); 473636d43d94SBarry Smith PetscCall(PetscViewerPopFormat(snes->convergedreasonviewer)); 47372a359c20SBarry Smith } 47382a359c20SBarry Smith incall = PETSC_FALSE; 47393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 47402a359c20SBarry Smith } 47412a359c20SBarry Smith 4742487a658cSBarry Smith /*@ 47430b4b7b1cSBarry Smith SNESSolve - Solves a nonlinear system $F(x) = b $ associated with a `SNES` object 47449b94acceSBarry Smith 4745c3339decSBarry Smith Collective 4746c7afd0dbSLois Curfman McInnes 4747b2002411SLois Curfman McInnes Input Parameters: 4748f6dfbefdSBarry Smith + snes - the `SNES` context 47490b4b7b1cSBarry Smith . b - the constant part of the equation $F(x) = b$, or `NULL` to use zero. 475085385478SLisandro Dalcin - x - the solution vector. 47519b94acceSBarry Smith 4752dc4c0fb0SBarry Smith Level: beginner 4753dc4c0fb0SBarry Smith 4754f6dfbefdSBarry Smith Note: 4755420bcc1bSBarry Smith The user should initialize the vector, `x`, with the initial guess 4756a9b45538SStefano Zampini for the nonlinear solve prior to calling `SNESSolve()` . 47578ddd3da0SLois Curfman McInnes 47581cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESSetFunction()`, `SNESSetJacobian()`, `SNESSetGridSequence()`, `SNESGetSolution()`, 4759db781477SPatrick Sanan `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRGetPreCheck()`, `SNESNewtonTRSetPostCheck()`, `SNESNewtonTRGetPostCheck()`, 4760a9b45538SStefano Zampini `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()` 47619b94acceSBarry Smith @*/ 4762d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSolve(SNES snes, Vec b, Vec x) 4763d71ae5a4SJacob Faibussowitsch { 4764ace3abfcSBarry Smith PetscBool flg; 4765efd51863SBarry Smith PetscInt grid; 47660298fd71SBarry Smith Vec xcreated = NULL; 4767caa4e7f2SJed Brown DM dm; 4768052efed2SBarry Smith 47693a40ed3dSBarry Smith PetscFunctionBegin; 47700700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4771a69afd8bSBarry Smith if (x) PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4772a69afd8bSBarry Smith if (x) PetscCheckSameComm(snes, 1, x, 3); 47730700a824SBarry Smith if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 477485385478SLisandro Dalcin if (b) PetscCheckSameComm(snes, 1, b, 2); 477585385478SLisandro Dalcin 477634b4d3a8SMatthew G. Knepley /* High level operations using the nonlinear solver */ 477706fc46c8SMatthew G. Knepley { 477806fc46c8SMatthew G. Knepley PetscViewer viewer; 477906fc46c8SMatthew G. Knepley PetscViewerFormat format; 47807c88af5aSMatthew G. Knepley PetscInt num; 478106fc46c8SMatthew G. Knepley PetscBool flg; 478206fc46c8SMatthew G. Knepley static PetscBool incall = PETSC_FALSE; 478306fc46c8SMatthew G. Knepley 478406fc46c8SMatthew G. Knepley if (!incall) { 478534b4d3a8SMatthew G. Knepley /* Estimate the convergence rate of the discretization */ 4786648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg)); 478706fc46c8SMatthew G. Knepley if (flg) { 478806fc46c8SMatthew G. Knepley PetscConvEst conv; 478946079b62SMatthew G. Knepley DM dm; 479046079b62SMatthew G. Knepley PetscReal *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */ 479146079b62SMatthew G. Knepley PetscInt Nf; 479206fc46c8SMatthew G. Knepley 479306fc46c8SMatthew G. Knepley incall = PETSC_TRUE; 47949566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 47959566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 47969566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(Nf, &alpha)); 47979566063dSJacob Faibussowitsch PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)snes), &conv)); 47989566063dSJacob Faibussowitsch PetscCall(PetscConvEstSetSolver(conv, (PetscObject)snes)); 47999566063dSJacob Faibussowitsch PetscCall(PetscConvEstSetFromOptions(conv)); 48009566063dSJacob Faibussowitsch PetscCall(PetscConvEstSetUp(conv)); 48019566063dSJacob Faibussowitsch PetscCall(PetscConvEstGetConvRate(conv, alpha)); 48029566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(viewer, format)); 48039566063dSJacob Faibussowitsch PetscCall(PetscConvEstRateView(conv, alpha, viewer)); 48049566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer)); 4805648c30bcSBarry Smith PetscCall(PetscViewerDestroy(&viewer)); 48069566063dSJacob Faibussowitsch PetscCall(PetscConvEstDestroy(&conv)); 48079566063dSJacob Faibussowitsch PetscCall(PetscFree(alpha)); 480806fc46c8SMatthew G. Knepley incall = PETSC_FALSE; 480906fc46c8SMatthew G. Knepley } 481034b4d3a8SMatthew G. Knepley /* Adaptively refine the initial grid */ 4811b2588ea6SMatthew G. Knepley num = 1; 48129566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_initial", &num, &flg)); 481334b4d3a8SMatthew G. Knepley if (flg) { 481434b4d3a8SMatthew G. Knepley DMAdaptor adaptor; 481534b4d3a8SMatthew G. Knepley 481634b4d3a8SMatthew G. Knepley incall = PETSC_TRUE; 48179566063dSJacob Faibussowitsch PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor)); 48189566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSolver(adaptor, snes)); 48199566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSequenceLength(adaptor, num)); 48209566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetFromOptions(adaptor)); 48219566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetUp(adaptor)); 48229566063dSJacob Faibussowitsch PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x)); 48239566063dSJacob Faibussowitsch PetscCall(DMAdaptorDestroy(&adaptor)); 482434b4d3a8SMatthew G. Knepley incall = PETSC_FALSE; 482534b4d3a8SMatthew G. Knepley } 48267c88af5aSMatthew G. Knepley /* Use grid sequencing to adapt */ 48277c88af5aSMatthew G. Knepley num = 0; 48289566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_sequence", &num, NULL)); 48297c88af5aSMatthew G. Knepley if (num) { 48307c88af5aSMatthew G. Knepley DMAdaptor adaptor; 4831e03fd340SMatthew G. Knepley const char *prefix; 48327c88af5aSMatthew G. Knepley 48337c88af5aSMatthew G. Knepley incall = PETSC_TRUE; 48349566063dSJacob Faibussowitsch PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor)); 4835e03fd340SMatthew G. Knepley PetscCall(SNESGetOptionsPrefix(snes, &prefix)); 4836e03fd340SMatthew G. Knepley PetscCall(DMAdaptorSetOptionsPrefix(adaptor, prefix)); 48379566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSolver(adaptor, snes)); 48389566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSequenceLength(adaptor, num)); 48399566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetFromOptions(adaptor)); 48409566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetUp(adaptor)); 4841e5148a0bSMatthew G. Knepley PetscCall(PetscObjectViewFromOptions((PetscObject)adaptor, NULL, "-snes_adapt_view")); 48429566063dSJacob Faibussowitsch PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x)); 48439566063dSJacob Faibussowitsch PetscCall(DMAdaptorDestroy(&adaptor)); 48447c88af5aSMatthew G. Knepley incall = PETSC_FALSE; 48457c88af5aSMatthew G. Knepley } 484606fc46c8SMatthew G. Knepley } 484706fc46c8SMatthew G. Knepley } 4848ad540459SPierre Jolivet if (!x) x = snes->vec_sol; 4849caa4e7f2SJed Brown if (!x) { 48509566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 48519566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dm, &xcreated)); 4852a69afd8bSBarry Smith x = xcreated; 4853a69afd8bSBarry Smith } 48549566063dSJacob Faibussowitsch PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view_pre")); 4855f05ece33SBarry Smith 48569566063dSJacob Faibussowitsch for (grid = 0; grid < snes->gridsequence; grid++) PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)))); 4857efd51863SBarry Smith for (grid = 0; grid < snes->gridsequence + 1; grid++) { 485885385478SLisandro Dalcin /* set solution vector */ 48599566063dSJacob Faibussowitsch if (!grid) PetscCall(PetscObjectReference((PetscObject)x)); 48609566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol)); 486185385478SLisandro Dalcin snes->vec_sol = x; 48629566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 4863caa4e7f2SJed Brown 4864caa4e7f2SJed Brown /* set affine vector if provided */ 48659566063dSJacob Faibussowitsch if (b) PetscCall(PetscObjectReference((PetscObject)b)); 48669566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_rhs)); 486785385478SLisandro Dalcin snes->vec_rhs = b; 486885385478SLisandro Dalcin 48695f80ce2aSJacob 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"); 48705f80ce2aSJacob Faibussowitsch PetscCheck(snes->vec_func != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be function vector"); 4871dd8e379bSPierre Jolivet PetscCheck(snes->vec_rhs != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be right-hand side vector"); 4872aa624791SPierre Jolivet if (!snes->vec_sol_update /* && snes->vec_sol */) PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_sol_update)); 48739566063dSJacob Faibussowitsch PetscCall(DMShellSetGlobalVector(dm, snes->vec_sol)); 48749566063dSJacob Faibussowitsch PetscCall(SNESSetUp(snes)); 48753f149594SLisandro Dalcin 48767eee914bSBarry Smith if (!grid) { 48779927e4dfSBarry Smith if (snes->ops->computeinitialguess) PetscCallBack("SNES callback compute initial guess", (*snes->ops->computeinitialguess)(snes, snes->vec_sol, snes->initialguessP)); 4878dd568438SSatish Balay } 4879d25893d9SBarry Smith 4880abc0a331SBarry Smith if (snes->conv_hist_reset) snes->conv_hist_len = 0; 488112b1dd1aSStefano Zampini PetscCall(SNESResetCounters(snes)); 48822d157150SStefano Zampini snes->reason = SNES_CONVERGED_ITERATING; 48839566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_Solve, snes, 0, 0, 0)); 4884dbbe0bcdSBarry Smith PetscUseTypeMethod(snes, solve); 48859566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_Solve, snes, 0, 0, 0)); 48862d157150SStefano Zampini PetscCheck(snes->reason, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error, solver %s returned without setting converged reason", ((PetscObject)snes)->type_name); 4887422a814eSBarry Smith snes->domainerror = PETSC_FALSE; /* clear the flag if it has been set */ 48883f149594SLisandro Dalcin 488937ec4e1aSPeter Brune if (snes->lagjac_persist) snes->jac_iter += snes->iter; 489037ec4e1aSPeter Brune if (snes->lagpre_persist) snes->pre_iter += snes->iter; 489137ec4e1aSPeter Brune 4892648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_test_local_min", NULL, NULL, &flg)); 48939566063dSJacob Faibussowitsch if (flg && !PetscPreLoadingOn) PetscCall(SNESTestLocalMin(snes)); 4894c4421ceaSFande Kong /* Call converged reason views. This may involve user-provided viewers as well */ 48959566063dSJacob Faibussowitsch PetscCall(SNESConvergedReasonViewFromOptions(snes)); 48965968eb51SBarry Smith 48975f80ce2aSJacob Faibussowitsch if (snes->errorifnotconverged) PetscCheck(snes->reason >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_NOT_CONVERGED, "SNESSolve has not converged"); 48989c8e83a9SBarry Smith if (snes->reason < 0) break; 4899efd51863SBarry Smith if (grid < snes->gridsequence) { 4900efd51863SBarry Smith DM fine; 4901efd51863SBarry Smith Vec xnew; 4902efd51863SBarry Smith Mat interp; 4903efd51863SBarry Smith 49049566063dSJacob Faibussowitsch PetscCall(DMRefine(snes->dm, PetscObjectComm((PetscObject)snes), &fine)); 49055f80ce2aSJacob Faibussowitsch PetscCheck(fine, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_INCOMP, "DMRefine() did not perform any refinement, cannot continue grid sequencing"); 49062eace19aSMatthew G. Knepley PetscCall(DMGetCoordinatesLocalSetUp(fine)); 49079566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(snes->dm, fine, &interp, NULL)); 49089566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(fine, &xnew)); 49099566063dSJacob Faibussowitsch PetscCall(MatInterpolate(interp, x, xnew)); 49109566063dSJacob Faibussowitsch PetscCall(DMInterpolate(snes->dm, interp, fine)); 49119566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interp)); 4912efd51863SBarry Smith x = xnew; 4913efd51863SBarry Smith 49149566063dSJacob Faibussowitsch PetscCall(SNESReset(snes)); 49159566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes, fine)); 49169566063dSJacob Faibussowitsch PetscCall(SNESResetFromOptions(snes)); 49179566063dSJacob Faibussowitsch PetscCall(DMDestroy(&fine)); 49189566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)))); 4919efd51863SBarry Smith } 4920efd51863SBarry Smith } 49219566063dSJacob Faibussowitsch PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view")); 49229566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(snes->vec_sol, (PetscObject)snes, "-snes_view_solution")); 49239566063dSJacob Faibussowitsch PetscCall(DMMonitor(snes->dm)); 49249566063dSJacob Faibussowitsch PetscCall(SNESMonitorPauseFinal_Internal(snes)); 49253f7e2da0SPeter Brune 49269566063dSJacob Faibussowitsch PetscCall(VecDestroy(&xcreated)); 49279566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsBlock((PetscObject)snes)); 49283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49299b94acceSBarry Smith } 49309b94acceSBarry Smith 49319b94acceSBarry Smith /* --------- Internal routines for SNES Package --------- */ 49329b94acceSBarry Smith 4933cc4c1da9SBarry Smith /*@ 49340b4b7b1cSBarry Smith SNESSetType - Sets the algorithm/method to be used to solve the nonlinear system with the given `SNES` 49359b94acceSBarry Smith 4936c3339decSBarry Smith Collective 4937fee21e36SBarry Smith 4938c7afd0dbSLois Curfman McInnes Input Parameters: 4939f6dfbefdSBarry Smith + snes - the `SNES` context 4940454a90a3SBarry Smith - type - a known method 4941c7afd0dbSLois Curfman McInnes 4942c7afd0dbSLois Curfman McInnes Options Database Key: 4943454a90a3SBarry Smith . -snes_type <type> - Sets the method; use -help for a list 494404d7464bSBarry Smith of available methods (for instance, newtonls or newtontr) 4945ae12b187SLois Curfman McInnes 4946dc4c0fb0SBarry Smith Level: intermediate 4947dc4c0fb0SBarry Smith 49489b94acceSBarry Smith Notes: 49490b4b7b1cSBarry Smith See `SNESType` for available methods (for instance) 4950f6dfbefdSBarry Smith + `SNESNEWTONLS` - Newton's method with line search 4951c7afd0dbSLois Curfman McInnes (systems of nonlinear equations) 49524a221d59SStefano Zampini - `SNESNEWTONTR` - Newton's method with trust region 4953c7afd0dbSLois Curfman McInnes (systems of nonlinear equations) 49549b94acceSBarry Smith 4955f6dfbefdSBarry Smith Normally, it is best to use the `SNESSetFromOptions()` command and then 4956f6dfbefdSBarry Smith set the `SNES` solver type from the options database rather than by using 4957ae12b187SLois Curfman McInnes this routine. Using the options database provides the user with 4958ae12b187SLois Curfman McInnes maximum flexibility in evaluating the many nonlinear solvers. 4959f6dfbefdSBarry Smith The `SNESSetType()` routine is provided for those situations where it 4960ae12b187SLois Curfman McInnes is necessary to set the nonlinear solver independently of the command 4961ae12b187SLois Curfman McInnes line or options database. This might be the case, for example, when 4962ae12b187SLois Curfman McInnes the choice of solver changes during the execution of the program, 4963ae12b187SLois Curfman McInnes and the user's application is taking responsibility for choosing the 4964b0a32e0cSBarry Smith appropriate method. 496536851e7fSLois Curfman McInnes 4966420bcc1bSBarry Smith Developer Note: 4967f6dfbefdSBarry Smith `SNESRegister()` adds a constructor for a new `SNESType` to `SNESList`, `SNESSetType()` locates 4968f6dfbefdSBarry Smith the constructor in that list and calls it to create the specific object. 49698f6c3df8SBarry Smith 49701cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESType`, `SNESCreate()`, `SNESDestroy()`, `SNESGetType()`, `SNESSetFromOptions()` 49719b94acceSBarry Smith @*/ 4972d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetType(SNES snes, SNESType type) 4973d71ae5a4SJacob Faibussowitsch { 4974ace3abfcSBarry Smith PetscBool match; 49755f80ce2aSJacob Faibussowitsch PetscErrorCode (*r)(SNES); 49763a40ed3dSBarry Smith 49773a40ed3dSBarry Smith PetscFunctionBegin; 49780700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 49794f572ea9SToby Isaac PetscAssertPointer(type, 2); 498082bf6240SBarry Smith 49819566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes, type, &match)); 49823ba16761SJacob Faibussowitsch if (match) PetscFunctionReturn(PETSC_SUCCESS); 498392ff6ae8SBarry Smith 49849566063dSJacob Faibussowitsch PetscCall(PetscFunctionListFind(SNESList, type, &r)); 49856adde796SStefano Zampini PetscCheck(r, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested SNES type %s", type); 498675396ef9SLisandro Dalcin /* Destroy the previous private SNES context */ 4987dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, destroy); 498843547594SStefano Zampini /* Reinitialize type-specific function pointers in SNESOps structure */ 498943547594SStefano Zampini snes->ops->reset = NULL; 49909e5d0892SLisandro Dalcin snes->ops->setup = NULL; 49919e5d0892SLisandro Dalcin snes->ops->solve = NULL; 49929e5d0892SLisandro Dalcin snes->ops->view = NULL; 49939e5d0892SLisandro Dalcin snes->ops->setfromoptions = NULL; 49949e5d0892SLisandro Dalcin snes->ops->destroy = NULL; 49957fe760d5SStefano Zampini 49967fe760d5SStefano Zampini /* It may happen the user has customized the line search before calling SNESSetType */ 49979566063dSJacob Faibussowitsch if (((PetscObject)snes)->type_name) PetscCall(SNESLineSearchDestroy(&snes->linesearch)); 49987fe760d5SStefano Zampini 499975396ef9SLisandro Dalcin /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */ 500075396ef9SLisandro Dalcin snes->setupcalled = PETSC_FALSE; 5001f5af7f23SKarl Rupp 50029566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)snes, type)); 50039566063dSJacob Faibussowitsch PetscCall((*r)(snes)); 50043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50059b94acceSBarry Smith } 50069b94acceSBarry Smith 5007cc4c1da9SBarry Smith /*@ 5008f6dfbefdSBarry Smith SNESGetType - Gets the `SNES` method type and name (as a string). 50099b94acceSBarry Smith 5010c7afd0dbSLois Curfman McInnes Not Collective 5011c7afd0dbSLois Curfman McInnes 50129b94acceSBarry Smith Input Parameter: 50134b0e389bSBarry Smith . snes - nonlinear solver context 50149b94acceSBarry Smith 50159b94acceSBarry Smith Output Parameter: 5016f6dfbefdSBarry Smith . type - `SNES` method (a character string) 50179b94acceSBarry Smith 501836851e7fSLois Curfman McInnes Level: intermediate 501936851e7fSLois Curfman McInnes 50201cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetType()`, `SNESType`, `SNESSetFromOptions()`, `SNES` 50219b94acceSBarry Smith @*/ 5022d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetType(SNES snes, SNESType *type) 5023d71ae5a4SJacob Faibussowitsch { 50243a40ed3dSBarry Smith PetscFunctionBegin; 50250700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 50264f572ea9SToby Isaac PetscAssertPointer(type, 2); 50277adad957SLisandro Dalcin *type = ((PetscObject)snes)->type_name; 50283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50299b94acceSBarry Smith } 50309b94acceSBarry Smith 50313cd8a7caSMatthew G. Knepley /*@ 5032f6dfbefdSBarry Smith SNESSetSolution - Sets the solution vector for use by the `SNES` routines. 50333cd8a7caSMatthew G. Knepley 5034c3339decSBarry Smith Logically Collective 50353cd8a7caSMatthew G. Knepley 50363cd8a7caSMatthew G. Knepley Input Parameters: 5037f6dfbefdSBarry Smith + snes - the `SNES` context obtained from `SNESCreate()` 50383cd8a7caSMatthew G. Knepley - u - the solution vector 50393cd8a7caSMatthew G. Knepley 50403cd8a7caSMatthew G. Knepley Level: beginner 50413cd8a7caSMatthew G. Knepley 50421cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetSolution()`, `Vec` 50433cd8a7caSMatthew G. Knepley @*/ 5044d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetSolution(SNES snes, Vec u) 5045d71ae5a4SJacob Faibussowitsch { 50463cd8a7caSMatthew G. Knepley DM dm; 50473cd8a7caSMatthew G. Knepley 50483cd8a7caSMatthew G. Knepley PetscFunctionBegin; 50493cd8a7caSMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 50503cd8a7caSMatthew G. Knepley PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 50519566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)u)); 50529566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol)); 50533cd8a7caSMatthew G. Knepley 50543cd8a7caSMatthew G. Knepley snes->vec_sol = u; 50553cd8a7caSMatthew G. Knepley 50569566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 50579566063dSJacob Faibussowitsch PetscCall(DMShellSetGlobalVector(dm, u)); 50583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50593cd8a7caSMatthew G. Knepley } 50603cd8a7caSMatthew G. Knepley 506152baeb72SSatish Balay /*@ 50629b94acceSBarry Smith SNESGetSolution - Returns the vector where the approximate solution is 5063f6dfbefdSBarry Smith stored. This is the fine grid solution when using `SNESSetGridSequence()`. 50649b94acceSBarry Smith 5065420bcc1bSBarry Smith Not Collective, but `x` is parallel if `snes` is parallel 5066c7afd0dbSLois Curfman McInnes 50679b94acceSBarry Smith Input Parameter: 5068f6dfbefdSBarry Smith . snes - the `SNES` context 50699b94acceSBarry Smith 50709b94acceSBarry Smith Output Parameter: 50719b94acceSBarry Smith . x - the solution 50729b94acceSBarry Smith 507370e92668SMatthew Knepley Level: intermediate 507436851e7fSLois Curfman McInnes 50751cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetSolution()`, `SNESSolve()`, `SNES`, `SNESGetSolutionUpdate()`, `SNESGetFunction()` 50769b94acceSBarry Smith @*/ 5077d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolution(SNES snes, Vec *x) 5078d71ae5a4SJacob Faibussowitsch { 50793a40ed3dSBarry Smith PetscFunctionBegin; 50800700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 50814f572ea9SToby Isaac PetscAssertPointer(x, 2); 508285385478SLisandro Dalcin *x = snes->vec_sol; 50833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 508470e92668SMatthew Knepley } 508570e92668SMatthew Knepley 508652baeb72SSatish Balay /*@ 50879b94acceSBarry Smith SNESGetSolutionUpdate - Returns the vector where the solution update is 50889b94acceSBarry Smith stored. 50899b94acceSBarry Smith 5090420bcc1bSBarry Smith Not Collective, but `x` is parallel if `snes` is parallel 5091c7afd0dbSLois Curfman McInnes 50929b94acceSBarry Smith Input Parameter: 5093f6dfbefdSBarry Smith . snes - the `SNES` context 50949b94acceSBarry Smith 50959b94acceSBarry Smith Output Parameter: 50969b94acceSBarry Smith . x - the solution update 50979b94acceSBarry Smith 509836851e7fSLois Curfman McInnes Level: advanced 509936851e7fSLois Curfman McInnes 51001cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()` 51019b94acceSBarry Smith @*/ 5102d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionUpdate(SNES snes, Vec *x) 5103d71ae5a4SJacob Faibussowitsch { 51043a40ed3dSBarry Smith PetscFunctionBegin; 51050700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 51064f572ea9SToby Isaac PetscAssertPointer(x, 2); 510785385478SLisandro Dalcin *x = snes->vec_sol_update; 51083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 51099b94acceSBarry Smith } 51109b94acceSBarry Smith 51119b94acceSBarry Smith /*@C 5112f6dfbefdSBarry Smith SNESGetFunction - Returns the function that defines the nonlinear system set with `SNESSetFunction()` 51139b94acceSBarry Smith 5114420bcc1bSBarry Smith Not Collective, but `r` is parallel if `snes` is parallel. Collective if `r` is requested, but has not been created yet. 5115c7afd0dbSLois Curfman McInnes 51169b94acceSBarry Smith Input Parameter: 5117f6dfbefdSBarry Smith . snes - the `SNES` context 51189b94acceSBarry Smith 5119d8d19677SJose E. Roman Output Parameters: 5120dc4c0fb0SBarry Smith + r - the vector that is used to store residuals (or `NULL` if you don't want it) 51218434afd1SBarry Smith . f - the function (or `NULL` if you don't want it); for calling sequence see `SNESFunctionFn` 5122dc4c0fb0SBarry Smith - ctx - the function context (or `NULL` if you don't want it) 51239b94acceSBarry Smith 512436851e7fSLois Curfman McInnes Level: advanced 512536851e7fSLois Curfman McInnes 5126f6dfbefdSBarry Smith Note: 5127dc4c0fb0SBarry Smith The vector `r` DOES NOT, in general, contain the current value of the `SNES` nonlinear function 512804edfde5SBarry Smith 51298434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetSolution()`, `SNESFunctionFn` 51309b94acceSBarry Smith @*/ 51318434afd1SBarry Smith PetscErrorCode SNESGetFunction(SNES snes, Vec *r, SNESFunctionFn **f, void **ctx) 5132d71ae5a4SJacob Faibussowitsch { 51336cab3a1bSJed Brown DM dm; 5134a63bb30eSJed Brown 51353a40ed3dSBarry Smith PetscFunctionBegin; 51360700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5137a63bb30eSJed Brown if (r) { 5138a63bb30eSJed Brown if (!snes->vec_func) { 5139a63bb30eSJed Brown if (snes->vec_rhs) { 51409566063dSJacob Faibussowitsch PetscCall(VecDuplicate(snes->vec_rhs, &snes->vec_func)); 5141a63bb30eSJed Brown } else if (snes->vec_sol) { 51429566063dSJacob Faibussowitsch PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_func)); 5143a63bb30eSJed Brown } else if (snes->dm) { 51449566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(snes->dm, &snes->vec_func)); 5145a63bb30eSJed Brown } 5146a63bb30eSJed Brown } 5147a63bb30eSJed Brown *r = snes->vec_func; 5148a63bb30eSJed Brown } 51499566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 51509566063dSJacob Faibussowitsch PetscCall(DMSNESGetFunction(dm, f, ctx)); 51513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 51529b94acceSBarry Smith } 51539b94acceSBarry Smith 5154c79ef259SPeter Brune /*@C 515537fdd005SBarry Smith SNESGetNGS - Returns the function and context set with `SNESSetNGS()` 5156c79ef259SPeter Brune 5157c79ef259SPeter Brune Input Parameter: 5158f6dfbefdSBarry Smith . snes - the `SNES` context 5159c79ef259SPeter Brune 5160d8d19677SJose E. Roman Output Parameters: 51618434afd1SBarry Smith + f - the function (or `NULL`) see `SNESNGSFn` for calling sequence 5162dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`) 5163c79ef259SPeter Brune 5164c79ef259SPeter Brune Level: advanced 5165c79ef259SPeter Brune 51668434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetNGS()`, `SNESGetFunction()`, `SNESNGSFn` 5167c79ef259SPeter Brune @*/ 51688434afd1SBarry Smith PetscErrorCode SNESGetNGS(SNES snes, SNESNGSFn **f, void **ctx) 5169d71ae5a4SJacob Faibussowitsch { 51706cab3a1bSJed Brown DM dm; 51716cab3a1bSJed Brown 5172646217ecSPeter Brune PetscFunctionBegin; 5173646217ecSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 51749566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 51759566063dSJacob Faibussowitsch PetscCall(DMSNESGetNGS(dm, f, ctx)); 51763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5177646217ecSPeter Brune } 5178646217ecSPeter Brune 5179cc4c1da9SBarry Smith /*@ 51803c7409f5SSatish Balay SNESSetOptionsPrefix - Sets the prefix used for searching for all 5181f6dfbefdSBarry Smith `SNES` options in the database. 51823c7409f5SSatish Balay 5183c3339decSBarry Smith Logically Collective 5184fee21e36SBarry Smith 5185d8d19677SJose E. Roman Input Parameters: 5186f6dfbefdSBarry Smith + snes - the `SNES` context 5187c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names 5188c7afd0dbSLois Curfman McInnes 5189dc4c0fb0SBarry Smith Level: advanced 5190dc4c0fb0SBarry Smith 5191f6dfbefdSBarry Smith Note: 5192a83b1b31SSatish Balay A hyphen (-) must NOT be given at the beginning of the prefix name. 5193c7afd0dbSLois Curfman McInnes The first character of all runtime options is AUTOMATICALLY the hyphen. 5194d850072dSLois Curfman McInnes 51951cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESAppendOptionsPrefix()` 51963c7409f5SSatish Balay @*/ 5197d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetOptionsPrefix(SNES snes, const char prefix[]) 5198d71ae5a4SJacob Faibussowitsch { 51993a40ed3dSBarry Smith PetscFunctionBegin; 52000700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 52019566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes, prefix)); 52029566063dSJacob Faibussowitsch if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 520335f5d045SPeter Brune if (snes->linesearch) { 52049566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 52059566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch, prefix)); 520635f5d045SPeter Brune } 52079566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(snes->ksp, prefix)); 52083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 52093c7409f5SSatish Balay } 52103c7409f5SSatish Balay 5211cc4c1da9SBarry Smith /*@ 5212f525115eSLois Curfman McInnes SNESAppendOptionsPrefix - Appends to the prefix used for searching for all 5213f6dfbefdSBarry Smith `SNES` options in the database. 52143c7409f5SSatish Balay 5215c3339decSBarry Smith Logically Collective 5216fee21e36SBarry Smith 5217c7afd0dbSLois Curfman McInnes Input Parameters: 5218f6dfbefdSBarry Smith + snes - the `SNES` context 5219c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names 5220c7afd0dbSLois Curfman McInnes 5221dc4c0fb0SBarry Smith Level: advanced 5222dc4c0fb0SBarry Smith 5223f6dfbefdSBarry Smith Note: 5224a83b1b31SSatish Balay A hyphen (-) must NOT be given at the beginning of the prefix name. 5225c7afd0dbSLois Curfman McInnes The first character of all runtime options is AUTOMATICALLY the hyphen. 5226d850072dSLois Curfman McInnes 52271cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetOptionsPrefix()`, `SNESSetOptionsPrefix()` 52283c7409f5SSatish Balay @*/ 5229d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESAppendOptionsPrefix(SNES snes, const char prefix[]) 5230d71ae5a4SJacob Faibussowitsch { 52313a40ed3dSBarry Smith PetscFunctionBegin; 52320700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 52339566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes, prefix)); 52349566063dSJacob Faibussowitsch if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 523535f5d045SPeter Brune if (snes->linesearch) { 52369566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 52379566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch, prefix)); 523835f5d045SPeter Brune } 52399566063dSJacob Faibussowitsch PetscCall(KSPAppendOptionsPrefix(snes->ksp, prefix)); 52403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 52413c7409f5SSatish Balay } 52423c7409f5SSatish Balay 5243cc4c1da9SBarry Smith /*@ 5244f6dfbefdSBarry Smith SNESGetOptionsPrefix - Gets the prefix used for searching for all 5245f6dfbefdSBarry Smith `SNES` options in the database. 52463c7409f5SSatish Balay 5247c7afd0dbSLois Curfman McInnes Not Collective 5248c7afd0dbSLois Curfman McInnes 52493c7409f5SSatish Balay Input Parameter: 5250f6dfbefdSBarry Smith . snes - the `SNES` context 52513c7409f5SSatish Balay 52523c7409f5SSatish Balay Output Parameter: 52533c7409f5SSatish Balay . prefix - pointer to the prefix string used 52543c7409f5SSatish Balay 525536851e7fSLois Curfman McInnes Level: advanced 525636851e7fSLois Curfman McInnes 52571cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetOptionsPrefix()`, `SNESAppendOptionsPrefix()` 52583c7409f5SSatish Balay @*/ 5259d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetOptionsPrefix(SNES snes, const char *prefix[]) 5260d71ae5a4SJacob Faibussowitsch { 52613a40ed3dSBarry Smith PetscFunctionBegin; 52620700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 52639566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)snes, prefix)); 52643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 52653c7409f5SSatish Balay } 52663c7409f5SSatish Balay 52673cea93caSBarry Smith /*@C 52681c84c290SBarry Smith SNESRegister - Adds a method to the nonlinear solver package. 52691c84c290SBarry Smith 527020f4b53cSBarry Smith Not Collective 52711c84c290SBarry Smith 52721c84c290SBarry Smith Input Parameters: 527320f4b53cSBarry Smith + sname - name of a new user-defined solver 527420f4b53cSBarry Smith - function - routine to create method context 52751c84c290SBarry Smith 5276dc4c0fb0SBarry Smith Level: advanced 5277dc4c0fb0SBarry Smith 5278f6dfbefdSBarry Smith Note: 5279f6dfbefdSBarry Smith `SNESRegister()` may be called multiple times to add several user-defined solvers. 52801c84c290SBarry Smith 5281e4094ef1SJacob Faibussowitsch Example Usage: 52821c84c290SBarry Smith .vb 5283bdf89e91SBarry Smith SNESRegister("my_solver", MySolverCreate); 52841c84c290SBarry Smith .ve 52851c84c290SBarry Smith 52861c84c290SBarry Smith Then, your solver can be chosen with the procedural interface via 5287b44f4de4SBarry Smith .vb 5288b44f4de4SBarry Smith SNESSetType(snes, "my_solver") 5289b44f4de4SBarry Smith .ve 52901c84c290SBarry Smith or at runtime via the option 5291b44f4de4SBarry Smith .vb 5292b44f4de4SBarry Smith -snes_type my_solver 5293b44f4de4SBarry Smith .ve 52941c84c290SBarry Smith 52951cc06b55SBarry Smith .seealso: [](ch_snes), `SNESRegisterAll()`, `SNESRegisterDestroy()` 52963cea93caSBarry Smith @*/ 5297d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESRegister(const char sname[], PetscErrorCode (*function)(SNES)) 5298d71ae5a4SJacob Faibussowitsch { 5299b2002411SLois Curfman McInnes PetscFunctionBegin; 53009566063dSJacob Faibussowitsch PetscCall(SNESInitializePackage()); 53019566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&SNESList, sname, function)); 53023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5303b2002411SLois Curfman McInnes } 5304da9b6338SBarry Smith 5305d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestLocalMin(SNES snes) 5306d71ae5a4SJacob Faibussowitsch { 530777431f27SBarry Smith PetscInt N, i, j; 5308da9b6338SBarry Smith Vec u, uh, fh; 5309da9b6338SBarry Smith PetscScalar value; 5310da9b6338SBarry Smith PetscReal norm; 5311da9b6338SBarry Smith 5312da9b6338SBarry Smith PetscFunctionBegin; 53139566063dSJacob Faibussowitsch PetscCall(SNESGetSolution(snes, &u)); 53149566063dSJacob Faibussowitsch PetscCall(VecDuplicate(u, &uh)); 53159566063dSJacob Faibussowitsch PetscCall(VecDuplicate(u, &fh)); 5316da9b6338SBarry Smith 5317da9b6338SBarry Smith /* currently only works for sequential */ 53189566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Testing FormFunction() for local min\n")); 53199566063dSJacob Faibussowitsch PetscCall(VecGetSize(u, &N)); 5320da9b6338SBarry Smith for (i = 0; i < N; i++) { 53219566063dSJacob Faibussowitsch PetscCall(VecCopy(u, uh)); 532263a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "i = %" PetscInt_FMT "\n", i)); 5323da9b6338SBarry Smith for (j = -10; j < 11; j++) { 53248b49ba18SBarry Smith value = PetscSign(j) * PetscExpReal(PetscAbs(j) - 10.0); 53259566063dSJacob Faibussowitsch PetscCall(VecSetValue(uh, i, value, ADD_VALUES)); 53269566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, uh, fh)); 53279566063dSJacob Faibussowitsch PetscCall(VecNorm(fh, NORM_2, &norm)); 532863a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), " j norm %" PetscInt_FMT " %18.16e\n", j, (double)norm)); 5329da9b6338SBarry Smith value = -value; 53309566063dSJacob Faibussowitsch PetscCall(VecSetValue(uh, i, value, ADD_VALUES)); 5331da9b6338SBarry Smith } 5332da9b6338SBarry Smith } 53339566063dSJacob Faibussowitsch PetscCall(VecDestroy(&uh)); 53349566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fh)); 53353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5336da9b6338SBarry Smith } 533771f87433Sdalcinl 533871f87433Sdalcinl /*@ 5339f6dfbefdSBarry Smith SNESKSPSetUseEW - Sets `SNES` to the use Eisenstat-Walker method for 534071f87433Sdalcinl computing relative tolerance for linear solvers within an inexact 534171f87433Sdalcinl Newton method. 534271f87433Sdalcinl 5343c3339decSBarry Smith Logically Collective 534471f87433Sdalcinl 534571f87433Sdalcinl Input Parameters: 5346f6dfbefdSBarry Smith + snes - `SNES` context 5347f6dfbefdSBarry Smith - flag - `PETSC_TRUE` or `PETSC_FALSE` 534871f87433Sdalcinl 5349f6dfbefdSBarry Smith Options Database Keys: 535064ba62caSBarry Smith + -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence 535164ba62caSBarry Smith . -snes_ksp_ew_version ver - version of Eisenstat-Walker method 535264ba62caSBarry Smith . -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0 535364ba62caSBarry Smith . -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax 535464ba62caSBarry Smith . -snes_ksp_ew_gamma <gamma> - Sets gamma 535564ba62caSBarry Smith . -snes_ksp_ew_alpha <alpha> - Sets alpha 535664ba62caSBarry Smith . -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2 535764ba62caSBarry Smith - -snes_ksp_ew_threshold <threshold> - Sets threshold 535864ba62caSBarry Smith 5359dc4c0fb0SBarry Smith Level: advanced 5360dc4c0fb0SBarry Smith 5361f6dfbefdSBarry Smith Note: 5362f6dfbefdSBarry Smith The default is to use a constant relative tolerance for 536371f87433Sdalcinl the inner linear solvers. Alternatively, one can use the 53641d27aa22SBarry Smith Eisenstat-Walker method {cite}`ew96`, where the relative convergence tolerance 536571f87433Sdalcinl is reset at each Newton iteration according progress of the nonlinear 536671f87433Sdalcinl solver. 536771f87433Sdalcinl 53681cc06b55SBarry Smith .seealso: [](ch_snes), `KSP`, `SNES`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()` 536971f87433Sdalcinl @*/ 5370d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetUseEW(SNES snes, PetscBool flag) 5371d71ae5a4SJacob Faibussowitsch { 537271f87433Sdalcinl PetscFunctionBegin; 53730700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5374acfcf0e5SJed Brown PetscValidLogicalCollectiveBool(snes, flag, 2); 537571f87433Sdalcinl snes->ksp_ewconv = flag; 53763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 537771f87433Sdalcinl } 537871f87433Sdalcinl 537971f87433Sdalcinl /*@ 5380f6dfbefdSBarry Smith SNESKSPGetUseEW - Gets if `SNES` is using Eisenstat-Walker method 538171f87433Sdalcinl for computing relative tolerance for linear solvers within an 538271f87433Sdalcinl inexact Newton method. 538371f87433Sdalcinl 538471f87433Sdalcinl Not Collective 538571f87433Sdalcinl 538671f87433Sdalcinl Input Parameter: 5387f6dfbefdSBarry Smith . snes - `SNES` context 538871f87433Sdalcinl 538971f87433Sdalcinl Output Parameter: 5390f6dfbefdSBarry Smith . flag - `PETSC_TRUE` or `PETSC_FALSE` 539171f87433Sdalcinl 539271f87433Sdalcinl Level: advanced 539371f87433Sdalcinl 53941cc06b55SBarry Smith .seealso: [](ch_snes), `SNESKSPSetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()` 539571f87433Sdalcinl @*/ 5396d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag) 5397d71ae5a4SJacob Faibussowitsch { 539871f87433Sdalcinl PetscFunctionBegin; 53990700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 54004f572ea9SToby Isaac PetscAssertPointer(flag, 2); 540171f87433Sdalcinl *flag = snes->ksp_ewconv; 54023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 540371f87433Sdalcinl } 540471f87433Sdalcinl 540571f87433Sdalcinl /*@ 5406fa9f3622SBarry Smith SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker 540771f87433Sdalcinl convergence criteria for the linear solvers within an inexact 540871f87433Sdalcinl Newton method. 540971f87433Sdalcinl 5410c3339decSBarry Smith Logically Collective 541171f87433Sdalcinl 541271f87433Sdalcinl Input Parameters: 5413f6dfbefdSBarry Smith + snes - `SNES` context 54140f0abf79SStefano Zampini . version - version 1, 2 (default is 2), 3 or 4 541571f87433Sdalcinl . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 541671f87433Sdalcinl . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 541771f87433Sdalcinl . gamma - multiplicative factor for version 2 rtol computation 541871f87433Sdalcinl (0 <= gamma2 <= 1) 541971f87433Sdalcinl . alpha - power for version 2 rtol computation (1 < alpha <= 2) 542071f87433Sdalcinl . alpha2 - power for safeguard 542171f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1) 542271f87433Sdalcinl 5423dc4c0fb0SBarry Smith Level: advanced 5424dc4c0fb0SBarry Smith 5425f6dfbefdSBarry Smith Notes: 542671f87433Sdalcinl Version 3 was contributed by Luis Chacon, June 2006. 542771f87433Sdalcinl 542877e5a1f9SBarry Smith Use `PETSC_CURRENT` to retain the default for any of the parameters. 542971f87433Sdalcinl 54301cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()` 543171f87433Sdalcinl @*/ 5432d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetParametersEW(SNES snes, PetscInt version, PetscReal rtol_0, PetscReal rtol_max, PetscReal gamma, PetscReal alpha, PetscReal alpha2, PetscReal threshold) 5433d71ae5a4SJacob Faibussowitsch { 5434fa9f3622SBarry Smith SNESKSPEW *kctx; 54355fd66863SKarl Rupp 543671f87433Sdalcinl PetscFunctionBegin; 54370700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5438fa9f3622SBarry Smith kctx = (SNESKSPEW *)snes->kspconvctx; 54395f80ce2aSJacob Faibussowitsch PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing"); 5440c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, version, 2); 5441c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, rtol_0, 3); 5442c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, rtol_max, 4); 5443c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, gamma, 5); 5444c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, alpha, 6); 5445c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, alpha2, 7); 5446c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, threshold, 8); 544771f87433Sdalcinl 544877e5a1f9SBarry Smith if (version != PETSC_CURRENT) kctx->version = version; 544977e5a1f9SBarry Smith if (rtol_0 != (PetscReal)PETSC_CURRENT) kctx->rtol_0 = rtol_0; 545077e5a1f9SBarry Smith if (rtol_max != (PetscReal)PETSC_CURRENT) kctx->rtol_max = rtol_max; 545177e5a1f9SBarry Smith if (gamma != (PetscReal)PETSC_CURRENT) kctx->gamma = gamma; 545277e5a1f9SBarry Smith if (alpha != (PetscReal)PETSC_CURRENT) kctx->alpha = alpha; 545377e5a1f9SBarry Smith if (alpha2 != (PetscReal)PETSC_CURRENT) kctx->alpha2 = alpha2; 545477e5a1f9SBarry Smith if (threshold != (PetscReal)PETSC_CURRENT) kctx->threshold = threshold; 545571f87433Sdalcinl 54560f0abf79SStefano 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); 54570b121fc5SBarry 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); 54580b121fc5SBarry 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); 54590b121fc5SBarry 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); 54600b121fc5SBarry 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); 54610b121fc5SBarry 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); 54623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 546371f87433Sdalcinl } 546471f87433Sdalcinl 546571f87433Sdalcinl /*@ 5466fa9f3622SBarry Smith SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker 546771f87433Sdalcinl convergence criteria for the linear solvers within an inexact 546871f87433Sdalcinl Newton method. 546971f87433Sdalcinl 547071f87433Sdalcinl Not Collective 547171f87433Sdalcinl 547297bb3fdcSJose E. Roman Input Parameter: 5473f6dfbefdSBarry Smith . snes - `SNES` context 547471f87433Sdalcinl 547571f87433Sdalcinl Output Parameters: 54760f0abf79SStefano Zampini + version - version 1, 2 (default is 2), 3 or 4 547771f87433Sdalcinl . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 547871f87433Sdalcinl . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 5479bf388a1fSBarry Smith . gamma - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1) 548071f87433Sdalcinl . alpha - power for version 2 rtol computation (1 < alpha <= 2) 548171f87433Sdalcinl . alpha2 - power for safeguard 548271f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1) 548371f87433Sdalcinl 548471f87433Sdalcinl Level: advanced 548571f87433Sdalcinl 54861cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPSetParametersEW()` 548771f87433Sdalcinl @*/ 5488d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetParametersEW(SNES snes, PetscInt *version, PetscReal *rtol_0, PetscReal *rtol_max, PetscReal *gamma, PetscReal *alpha, PetscReal *alpha2, PetscReal *threshold) 5489d71ae5a4SJacob Faibussowitsch { 5490fa9f3622SBarry Smith SNESKSPEW *kctx; 54915fd66863SKarl Rupp 549271f87433Sdalcinl PetscFunctionBegin; 54930700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5494fa9f3622SBarry Smith kctx = (SNESKSPEW *)snes->kspconvctx; 54955f80ce2aSJacob Faibussowitsch PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing"); 549671f87433Sdalcinl if (version) *version = kctx->version; 549771f87433Sdalcinl if (rtol_0) *rtol_0 = kctx->rtol_0; 549871f87433Sdalcinl if (rtol_max) *rtol_max = kctx->rtol_max; 549971f87433Sdalcinl if (gamma) *gamma = kctx->gamma; 550071f87433Sdalcinl if (alpha) *alpha = kctx->alpha; 550171f87433Sdalcinl if (alpha2) *alpha2 = kctx->alpha2; 550271f87433Sdalcinl if (threshold) *threshold = kctx->threshold; 55033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 550471f87433Sdalcinl } 550571f87433Sdalcinl 55065c0db29aSPierre Jolivet PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx) 5507d71ae5a4SJacob Faibussowitsch { 55085c0db29aSPierre Jolivet SNES snes = (SNES)ctx; 5509fa9f3622SBarry Smith SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx; 551077e5a1f9SBarry Smith PetscReal rtol = PETSC_CURRENT, stol; 551171f87433Sdalcinl 551271f87433Sdalcinl PetscFunctionBegin; 55133ba16761SJacob Faibussowitsch if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS); 551430058271SDmitry Karpeev if (!snes->iter) { 551530058271SDmitry Karpeev rtol = kctx->rtol_0; /* first time in, so use the original user rtol */ 55169566063dSJacob Faibussowitsch PetscCall(VecNorm(snes->vec_func, NORM_2, &kctx->norm_first)); 55170f0abf79SStefano Zampini } else { 55180fdf79fbSJacob 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); 551971f87433Sdalcinl if (kctx->version == 1) { 55200f0abf79SStefano Zampini rtol = PetscAbsReal(snes->norm - kctx->lresid_last) / kctx->norm_last; 552185ec1a3cSBarry Smith stol = PetscPowReal(kctx->rtol_last, kctx->alpha2); 552271f87433Sdalcinl if (stol > kctx->threshold) rtol = PetscMax(rtol, stol); 552371f87433Sdalcinl } else if (kctx->version == 2) { 552485ec1a3cSBarry Smith rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha); 552585ec1a3cSBarry Smith stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha); 552671f87433Sdalcinl if (stol > kctx->threshold) rtol = PetscMax(rtol, stol); 552771f87433Sdalcinl } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */ 552885ec1a3cSBarry Smith rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha); 552971f87433Sdalcinl /* safeguard: avoid sharp decrease of rtol */ 553085ec1a3cSBarry Smith stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha); 553171f87433Sdalcinl stol = PetscMax(rtol, stol); 553271f87433Sdalcinl rtol = PetscMin(kctx->rtol_0, stol); 553371f87433Sdalcinl /* safeguard: avoid oversolving */ 553430058271SDmitry Karpeev stol = kctx->gamma * (kctx->norm_first * snes->rtol) / snes->norm; 553571f87433Sdalcinl stol = PetscMax(rtol, stol); 553671f87433Sdalcinl rtol = PetscMin(kctx->rtol_0, stol); 55370fdf79fbSJacob Faibussowitsch } else /* if (kctx->version == 4) */ { 55380fdf79fbSJacob Faibussowitsch /* H.-B. An et al. Journal of Computational and Applied Mathematics 200 (2007) 47-60 */ 55390f0abf79SStefano Zampini PetscReal ared = PetscAbsReal(kctx->norm_last - snes->norm); 55400f0abf79SStefano Zampini PetscReal pred = PetscAbsReal(kctx->norm_last - kctx->lresid_last); 55410f0abf79SStefano Zampini PetscReal rk = ared / pred; 55420f0abf79SStefano Zampini if (rk < kctx->v4_p1) rtol = 1. - 2. * kctx->v4_p1; 55430f0abf79SStefano Zampini else if (rk < kctx->v4_p2) rtol = kctx->rtol_last; 55440f0abf79SStefano Zampini else if (rk < kctx->v4_p3) rtol = kctx->v4_m1 * kctx->rtol_last; 55450f0abf79SStefano Zampini else rtol = kctx->v4_m2 * kctx->rtol_last; 55460f0abf79SStefano Zampini 5547a4598233SStefano 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; 55480f0abf79SStefano Zampini kctx->rtol_last_2 = kctx->rtol_last; 55490f0abf79SStefano Zampini kctx->rk_last_2 = kctx->rk_last; 55500f0abf79SStefano Zampini kctx->rk_last = rk; 55510fdf79fbSJacob Faibussowitsch } 55520f0abf79SStefano Zampini } 55530f0abf79SStefano Zampini /* safeguard: avoid rtol greater than rtol_max */ 555471f87433Sdalcinl rtol = PetscMin(rtol, kctx->rtol_max); 555577e5a1f9SBarry Smith PetscCall(KSPSetTolerances(ksp, rtol, PETSC_CURRENT, PETSC_CURRENT, PETSC_CURRENT)); 555663a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "iter %" PetscInt_FMT ", Eisenstat-Walker (version %" PetscInt_FMT ") KSP rtol=%g\n", snes->iter, kctx->version, (double)rtol)); 55573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 555871f87433Sdalcinl } 555971f87433Sdalcinl 55605c0db29aSPierre Jolivet PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx) 5561d71ae5a4SJacob Faibussowitsch { 55625c0db29aSPierre Jolivet SNES snes = (SNES)ctx; 5563fa9f3622SBarry Smith SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx; 556471f87433Sdalcinl PCSide pcside; 556571f87433Sdalcinl Vec lres; 556671f87433Sdalcinl 556771f87433Sdalcinl PetscFunctionBegin; 55683ba16761SJacob Faibussowitsch if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS); 55699566063dSJacob Faibussowitsch PetscCall(KSPGetTolerances(ksp, &kctx->rtol_last, NULL, NULL, NULL)); 557071dbe336SPeter Brune kctx->norm_last = snes->norm; 55710f0abf79SStefano Zampini if (kctx->version == 1 || kctx->version == 4) { 55724f00ce20SMatthew G. Knepley PC pc; 55730f0abf79SStefano Zampini PetscBool getRes; 55744f00ce20SMatthew G. Knepley 55759566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksp, &pc)); 55760f0abf79SStefano Zampini PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &getRes)); 55770f0abf79SStefano Zampini if (!getRes) { 55780f0abf79SStefano Zampini KSPNormType normtype; 55790f0abf79SStefano Zampini 55800f0abf79SStefano Zampini PetscCall(KSPGetNormType(ksp, &normtype)); 55810f0abf79SStefano Zampini getRes = (PetscBool)(normtype == KSP_NORM_UNPRECONDITIONED); 55820f0abf79SStefano Zampini } 55839566063dSJacob Faibussowitsch PetscCall(KSPGetPCSide(ksp, &pcside)); 55840f0abf79SStefano Zampini if (pcside == PC_RIGHT || getRes) { /* KSP residual is true linear residual */ 55859566063dSJacob Faibussowitsch PetscCall(KSPGetResidualNorm(ksp, &kctx->lresid_last)); 558671f87433Sdalcinl } else { 558771f87433Sdalcinl /* KSP residual is preconditioned residual */ 558871f87433Sdalcinl /* compute true linear residual norm */ 55890f0abf79SStefano Zampini Mat J; 55900f0abf79SStefano Zampini PetscCall(KSPGetOperators(ksp, &J, NULL)); 55919566063dSJacob Faibussowitsch PetscCall(VecDuplicate(b, &lres)); 55920f0abf79SStefano Zampini PetscCall(MatMult(J, x, lres)); 55939566063dSJacob Faibussowitsch PetscCall(VecAYPX(lres, -1.0, b)); 55949566063dSJacob Faibussowitsch PetscCall(VecNorm(lres, NORM_2, &kctx->lresid_last)); 55959566063dSJacob Faibussowitsch PetscCall(VecDestroy(&lres)); 559671f87433Sdalcinl } 559771f87433Sdalcinl } 55983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 559971f87433Sdalcinl } 560071f87433Sdalcinl 5601d4211eb9SBarry Smith /*@ 5602f6dfbefdSBarry Smith SNESGetKSP - Returns the `KSP` context for a `SNES` solver. 5603d4211eb9SBarry Smith 5604420bcc1bSBarry Smith Not Collective, but if `snes` is parallel, then `ksp` is parallel 5605d4211eb9SBarry Smith 5606d4211eb9SBarry Smith Input Parameter: 5607f6dfbefdSBarry Smith . snes - the `SNES` context 5608d4211eb9SBarry Smith 5609d4211eb9SBarry Smith Output Parameter: 5610f6dfbefdSBarry Smith . ksp - the `KSP` context 5611d4211eb9SBarry Smith 5612dc4c0fb0SBarry Smith Level: beginner 5613dc4c0fb0SBarry Smith 5614d4211eb9SBarry Smith Notes: 5615f6dfbefdSBarry Smith The user can then directly manipulate the `KSP` context to set various 5616d4211eb9SBarry Smith options, etc. Likewise, the user can then extract and manipulate the 5617f6dfbefdSBarry Smith `PC` contexts as well. 5618f6dfbefdSBarry Smith 56190b4b7b1cSBarry 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. 5620d4211eb9SBarry Smith 56211cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSP`, `PC`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()` 5622d4211eb9SBarry Smith @*/ 5623d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetKSP(SNES snes, KSP *ksp) 5624d71ae5a4SJacob Faibussowitsch { 562571f87433Sdalcinl PetscFunctionBegin; 5626d4211eb9SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 56274f572ea9SToby Isaac PetscAssertPointer(ksp, 2); 5628d4211eb9SBarry Smith 5629d4211eb9SBarry Smith if (!snes->ksp) { 56309566063dSJacob Faibussowitsch PetscCall(KSPCreate(PetscObjectComm((PetscObject)snes), &snes->ksp)); 56319566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->ksp, (PetscObject)snes, 1)); 5632d4211eb9SBarry Smith 56335c0db29aSPierre Jolivet PetscCall(KSPSetPreSolve(snes->ksp, KSPPreSolve_SNESEW, snes)); 56345c0db29aSPierre Jolivet PetscCall(KSPSetPostSolve(snes->ksp, KSPPostSolve_SNESEW, snes)); 5635a5c2985bSBarry Smith 56369566063dSJacob Faibussowitsch PetscCall(KSPMonitorSetFromOptions(snes->ksp, "-snes_monitor_ksp", "snes_preconditioned_residual", snes)); 56379566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptions((PetscObject)snes->ksp, ((PetscObject)snes)->options)); 5638d4211eb9SBarry Smith } 5639d4211eb9SBarry Smith *ksp = snes->ksp; 56403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 564171f87433Sdalcinl } 56426c699258SBarry Smith 5643af0996ceSBarry Smith #include <petsc/private/dmimpl.h> 56446c699258SBarry Smith /*@ 56450b4b7b1cSBarry Smith SNESSetDM - Sets the `DM` that may be used by some `SNES` nonlinear solvers or their underlying preconditioners 56466c699258SBarry Smith 5647c3339decSBarry Smith Logically Collective 56486c699258SBarry Smith 56496c699258SBarry Smith Input Parameters: 56502a808120SBarry Smith + snes - the nonlinear solver context 5651420bcc1bSBarry Smith - dm - the `DM`, cannot be `NULL` 5652dc4c0fb0SBarry Smith 5653dc4c0fb0SBarry Smith Level: intermediate 56546c699258SBarry Smith 5655f6dfbefdSBarry Smith Note: 5656f6dfbefdSBarry Smith A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`, 5657f6dfbefdSBarry Smith even when not using interfaces like `DMSNESSetFunction()`. Use `DMClone()` to get a distinct `DM` when solving different 5658e03a659cSJed Brown problems using the same function space. 5659e03a659cSJed Brown 5660420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()` 56616c699258SBarry Smith @*/ 5662d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDM(SNES snes, DM dm) 5663d71ae5a4SJacob Faibussowitsch { 5664345fed2cSBarry Smith KSP ksp; 5665942e3340SBarry Smith DMSNES sdm; 56666c699258SBarry Smith 56676c699258SBarry Smith PetscFunctionBegin; 56680700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 56692a808120SBarry Smith PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 56709566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 5671942e3340SBarry Smith if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */ 567251f4b3c7SToby Isaac if (snes->dm->dmsnes && !dm->dmsnes) { 56739566063dSJacob Faibussowitsch PetscCall(DMCopyDMSNES(snes->dm, dm)); 56749566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(snes->dm, &sdm)); 5675f5af7f23SKarl Rupp if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */ 56766cab3a1bSJed Brown } 56779566063dSJacob Faibussowitsch PetscCall(DMCoarsenHookRemove(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes)); 56789566063dSJacob Faibussowitsch PetscCall(DMDestroy(&snes->dm)); 56796cab3a1bSJed Brown } 56806c699258SBarry Smith snes->dm = dm; 5681116d1032SJed Brown snes->dmAuto = PETSC_FALSE; 5682f5af7f23SKarl Rupp 56839566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 56849566063dSJacob Faibussowitsch PetscCall(KSPSetDM(ksp, dm)); 56859566063dSJacob Faibussowitsch PetscCall(KSPSetDMActive(ksp, PETSC_FALSE)); 5686efd4aadfSBarry Smith if (snes->npc) { 56879566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes->npc, snes->dm)); 56889566063dSJacob Faibussowitsch PetscCall(SNESSetNPCSide(snes, snes->npcside)); 56892c155ee1SBarry Smith } 56903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 56916c699258SBarry Smith } 56926c699258SBarry Smith 56936c699258SBarry Smith /*@ 56940b4b7b1cSBarry Smith SNESGetDM - Gets the `DM` that may be used by some `SNES` nonlinear solvers/preconditioners 56956c699258SBarry Smith 56960b4b7b1cSBarry Smith Not Collective but `dm` obtained is parallel on `snes` 56976c699258SBarry Smith 56986c699258SBarry Smith Input Parameter: 5699420bcc1bSBarry Smith . snes - the `SNES` context 57006c699258SBarry Smith 57016c699258SBarry Smith Output Parameter: 5702420bcc1bSBarry Smith . dm - the `DM` 57036c699258SBarry Smith 57046c699258SBarry Smith Level: intermediate 57056c699258SBarry Smith 5706420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESSetDM()`, `KSPSetDM()`, `KSPGetDM()` 57076c699258SBarry Smith @*/ 5708d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDM(SNES snes, DM *dm) 5709d71ae5a4SJacob Faibussowitsch { 57106c699258SBarry Smith PetscFunctionBegin; 57110700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 57126cab3a1bSJed Brown if (!snes->dm) { 57139566063dSJacob Faibussowitsch PetscCall(DMShellCreate(PetscObjectComm((PetscObject)snes), &snes->dm)); 5714116d1032SJed Brown snes->dmAuto = PETSC_TRUE; 57156cab3a1bSJed Brown } 57166c699258SBarry Smith *dm = snes->dm; 57173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 57186c699258SBarry Smith } 57190807856dSBarry Smith 572031823bd8SMatthew G Knepley /*@ 5721be95d8f1SBarry Smith SNESSetNPC - Sets the nonlinear preconditioner to be used. 572231823bd8SMatthew G Knepley 5723c3339decSBarry Smith Collective 572431823bd8SMatthew G Knepley 572531823bd8SMatthew G Knepley Input Parameters: 5726f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 572762842358SBarry Smith - npc - the `SNES` nonlinear preconditioner object 572862842358SBarry Smith 572962842358SBarry Smith Options Database Key: 573062842358SBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner 573131823bd8SMatthew G Knepley 5732dc4c0fb0SBarry Smith Level: developer 5733dc4c0fb0SBarry Smith 573431823bd8SMatthew G Knepley Notes: 573562842358SBarry Smith This is rarely used, rather use `SNESGetNPC()` to retrieve the preconditioner and configure it using the API. 573631823bd8SMatthew G Knepley 5737f6dfbefdSBarry Smith Only some `SNESType` can use a nonlinear preconditioner 5738f6dfbefdSBarry Smith 5739420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNGS`, `SNESFAS`, `SNESGetNPC()`, `SNESHasNPC()` 574031823bd8SMatthew G Knepley @*/ 5741d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPC(SNES snes, SNES npc) 5742d71ae5a4SJacob Faibussowitsch { 574331823bd8SMatthew G Knepley PetscFunctionBegin; 574431823bd8SMatthew G Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5745f6dfbefdSBarry Smith PetscValidHeaderSpecific(npc, SNES_CLASSID, 2); 5746f6dfbefdSBarry Smith PetscCheckSameComm(snes, 1, npc, 2); 5747f6dfbefdSBarry Smith PetscCall(PetscObjectReference((PetscObject)npc)); 57489566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&snes->npc)); 5749f6dfbefdSBarry Smith snes->npc = npc; 57503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 575131823bd8SMatthew G Knepley } 575231823bd8SMatthew G Knepley 575331823bd8SMatthew G Knepley /*@ 5754f6dfbefdSBarry Smith SNESGetNPC - Gets a nonlinear preconditioning solver SNES` to be used to precondition the original nonlinear solver. 575531823bd8SMatthew G Knepley 57560b4b7b1cSBarry Smith Not Collective; but any changes to the obtained the `pc` object must be applied collectively 575731823bd8SMatthew G Knepley 575831823bd8SMatthew G Knepley Input Parameter: 5759f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 576031823bd8SMatthew G Knepley 576131823bd8SMatthew G Knepley Output Parameter: 576262842358SBarry Smith . pc - the `SNES` preconditioner context 576331823bd8SMatthew G Knepley 5764f6dfbefdSBarry Smith Options Database Key: 5765f6dfbefdSBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner 5766b5badacbSBarry Smith 57670b4b7b1cSBarry Smith Level: advanced 5768dc4c0fb0SBarry Smith 576995452b02SPatrick Sanan Notes: 57700b4b7b1cSBarry Smith If a `SNES` was previously set with `SNESSetNPC()` then that value is returned, otherwise a new `SNES` object is created that will 57710b4b7b1cSBarry Smith be used as the nonlinear preconditioner for the current `SNES`. 5772be95d8f1SBarry Smith 5773f6dfbefdSBarry Smith The (preconditioner) `SNES` returned automatically inherits the same nonlinear function and Jacobian supplied to the original 577462842358SBarry Smith `SNES`. These may be overwritten if needed. 577562842358SBarry Smith 577662842358SBarry Smith Use the options database prefixes `-npc_snes`, `-npc_ksp`, etc., to control the configuration of the nonlinear preconditioner 5777951fe5abSBarry Smith 57781cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESHasNPC()`, `SNES`, `SNESCreate()` 577931823bd8SMatthew G Knepley @*/ 5780d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPC(SNES snes, SNES *pc) 5781d71ae5a4SJacob Faibussowitsch { 5782a64e098fSPeter Brune const char *optionsprefix; 578331823bd8SMatthew G Knepley 578431823bd8SMatthew G Knepley PetscFunctionBegin; 578531823bd8SMatthew G Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 57864f572ea9SToby Isaac PetscAssertPointer(pc, 2); 5787efd4aadfSBarry Smith if (!snes->npc) { 5788ec785e5bSStefano Zampini void *ctx; 5789ec785e5bSStefano Zampini 57909566063dSJacob Faibussowitsch PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &snes->npc)); 57919566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->npc, (PetscObject)snes, 1)); 57929566063dSJacob Faibussowitsch PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 57939566063dSJacob Faibussowitsch PetscCall(SNESSetOptionsPrefix(snes->npc, optionsprefix)); 57949566063dSJacob Faibussowitsch PetscCall(SNESAppendOptionsPrefix(snes->npc, "npc_")); 5795fb87a551SStefano Zampini if (snes->ops->usercompute) { 579649abdd8aSBarry Smith PetscCall(SNESSetComputeApplicationContext(snes, snes->ops->usercompute, snes->ops->ctxdestroy)); 5797fb87a551SStefano Zampini } else { 5798ec785e5bSStefano Zampini PetscCall(SNESGetApplicationContext(snes, &ctx)); 5799ec785e5bSStefano Zampini PetscCall(SNESSetApplicationContext(snes->npc, ctx)); 5800fb87a551SStefano Zampini } 58019566063dSJacob Faibussowitsch PetscCall(SNESSetCountersReset(snes->npc, PETSC_FALSE)); 580231823bd8SMatthew G Knepley } 5803efd4aadfSBarry Smith *pc = snes->npc; 58043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 580531823bd8SMatthew G Knepley } 580631823bd8SMatthew G Knepley 58073ad1a0b9SPatrick Farrell /*@ 58080b4b7b1cSBarry Smith SNESHasNPC - Returns whether a nonlinear preconditioner is associated with the given `SNES` 58093ad1a0b9SPatrick Farrell 58103ad1a0b9SPatrick Farrell Not Collective 58113ad1a0b9SPatrick Farrell 58123ad1a0b9SPatrick Farrell Input Parameter: 5813f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 58143ad1a0b9SPatrick Farrell 58153ad1a0b9SPatrick Farrell Output Parameter: 5816420bcc1bSBarry Smith . has_npc - whether the `SNES` has a nonlinear preconditioner or not 58173ad1a0b9SPatrick Farrell 58183ad1a0b9SPatrick Farrell Level: developer 58193ad1a0b9SPatrick Farrell 58201cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESGetNPC()` 58213ad1a0b9SPatrick Farrell @*/ 5822d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc) 5823d71ae5a4SJacob Faibussowitsch { 58243ad1a0b9SPatrick Farrell PetscFunctionBegin; 58253ad1a0b9SPatrick Farrell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5826835f2295SStefano Zampini PetscAssertPointer(has_npc, 2); 5827835f2295SStefano Zampini *has_npc = snes->npc ? PETSC_TRUE : PETSC_FALSE; 58283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 58293ad1a0b9SPatrick Farrell } 58303ad1a0b9SPatrick Farrell 5831c40d0f55SPeter Brune /*@ 583262842358SBarry Smith SNESSetNPCSide - Sets the nonlinear preconditioning side used by the nonlinear preconditioner inside `SNES`. 5833c40d0f55SPeter Brune 5834c3339decSBarry Smith Logically Collective 5835c40d0f55SPeter Brune 5836c40d0f55SPeter Brune Input Parameter: 5837f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 5838c40d0f55SPeter Brune 5839c40d0f55SPeter Brune Output Parameter: 5840c40d0f55SPeter Brune . side - the preconditioning side, where side is one of 5841c40d0f55SPeter Brune .vb 58422d547940SBarry Smith PC_LEFT - left preconditioning 58432d547940SBarry Smith PC_RIGHT - right preconditioning (default for most nonlinear solvers) 5844c40d0f55SPeter Brune .ve 5845c40d0f55SPeter Brune 5846f6dfbefdSBarry Smith Options Database Key: 584767b8a455SSatish Balay . -snes_npc_side <right,left> - nonlinear preconditioner side 5848c40d0f55SPeter Brune 5849dc4c0fb0SBarry Smith Level: intermediate 5850dc4c0fb0SBarry Smith 5851f6dfbefdSBarry Smith Note: 5852f6dfbefdSBarry Smith `SNESNRICHARDSON` and `SNESNCG` only support left preconditioning. 58532d547940SBarry Smith 585462842358SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNPC()`, `SNESNRICHARDSON`, `SNESNCG`, `SNESType`, `SNESGetNPCSide()`, `KSPSetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide` 5855c40d0f55SPeter Brune @*/ 5856d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPCSide(SNES snes, PCSide side) 5857d71ae5a4SJacob Faibussowitsch { 5858c40d0f55SPeter Brune PetscFunctionBegin; 5859c40d0f55SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5860c40d0f55SPeter Brune PetscValidLogicalCollectiveEnum(snes, side, 2); 5861b552625fSStefano Zampini if (side == PC_SIDE_DEFAULT) side = PC_RIGHT; 586254c59aa7SJacob Faibussowitsch PetscCheck((side == PC_LEFT) || (side == PC_RIGHT), PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Only PC_LEFT and PC_RIGHT are supported"); 5863efd4aadfSBarry Smith snes->npcside = side; 58643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5865c40d0f55SPeter Brune } 5866c40d0f55SPeter Brune 5867c40d0f55SPeter Brune /*@ 586862842358SBarry Smith SNESGetNPCSide - Gets the preconditioning side used by the nonlinear preconditioner inside `SNES`. 5869c40d0f55SPeter Brune 5870c40d0f55SPeter Brune Not Collective 5871c40d0f55SPeter Brune 5872c40d0f55SPeter Brune Input Parameter: 5873f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 5874c40d0f55SPeter Brune 5875c40d0f55SPeter Brune Output Parameter: 5876c40d0f55SPeter Brune . side - the preconditioning side, where side is one of 5877c40d0f55SPeter Brune .vb 5878f6dfbefdSBarry Smith `PC_LEFT` - left preconditioning 5879f6dfbefdSBarry Smith `PC_RIGHT` - right preconditioning (default for most nonlinear solvers) 5880c40d0f55SPeter Brune .ve 5881c40d0f55SPeter Brune 5882c40d0f55SPeter Brune Level: intermediate 5883c40d0f55SPeter Brune 588462842358SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNPC()`, `SNESSetNPCSide()`, `KSPGetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide` 5885c40d0f55SPeter Brune @*/ 5886d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPCSide(SNES snes, PCSide *side) 5887d71ae5a4SJacob Faibussowitsch { 5888c40d0f55SPeter Brune PetscFunctionBegin; 5889c40d0f55SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 58904f572ea9SToby Isaac PetscAssertPointer(side, 2); 5891efd4aadfSBarry Smith *side = snes->npcside; 58923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5893c40d0f55SPeter Brune } 5894c40d0f55SPeter Brune 58959e764e56SPeter Brune /*@ 58960b4b7b1cSBarry Smith SNESSetLineSearch - Sets the `SNESLineSearch` to be used for a given `SNES` 58979e764e56SPeter Brune 5898c3339decSBarry Smith Collective 58999e764e56SPeter Brune 59009e764e56SPeter Brune Input Parameters: 5901f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()` 59029e764e56SPeter Brune - linesearch - the linesearch object 59039e764e56SPeter Brune 5904dc4c0fb0SBarry Smith Level: developer 5905dc4c0fb0SBarry Smith 5906f6dfbefdSBarry Smith Note: 5907420bcc1bSBarry Smith This is almost never used, rather one uses `SNESGetLineSearch()` to retrieve the line search and set options on it 59089e764e56SPeter Brune to configure it using the API). 59099e764e56SPeter Brune 5910420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()` 59119e764e56SPeter Brune @*/ 5912d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch) 5913d71ae5a4SJacob Faibussowitsch { 59149e764e56SPeter Brune PetscFunctionBegin; 59159e764e56SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5916f1c6b773SPeter Brune PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 2); 59179e764e56SPeter Brune PetscCheckSameComm(snes, 1, linesearch, 2); 59189566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)linesearch)); 59199566063dSJacob Faibussowitsch PetscCall(SNESLineSearchDestroy(&snes->linesearch)); 5920f5af7f23SKarl Rupp 59219e764e56SPeter Brune snes->linesearch = linesearch; 59223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 59239e764e56SPeter Brune } 59249e764e56SPeter Brune 5925a34ceb2aSJed Brown /*@ 592662842358SBarry Smith SNESGetLineSearch - Returns the line search associated with the `SNES`. 59279e764e56SPeter Brune 59289e764e56SPeter Brune Not Collective 59299e764e56SPeter Brune 59309e764e56SPeter Brune Input Parameter: 5931f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()` 59329e764e56SPeter Brune 59339e764e56SPeter Brune Output Parameter: 59349e764e56SPeter Brune . linesearch - linesearch context 59359e764e56SPeter Brune 5936162e0bf5SPeter Brune Level: beginner 59379e764e56SPeter Brune 593862842358SBarry Smith Notes: 593962842358SBarry Smith It creates a default line search instance which can be configured as needed in case it has not been already set with `SNESSetLineSearch()`. 594062842358SBarry Smith 594162842358SBarry Smith You can also use the options database keys `-snes_linesearch_*` to configure the line search. See `SNESLineSearchSetFromOptions()` for the possible options. 594262842358SBarry Smith 594362842358SBarry Smith .seealso: [](ch_snes), `SNESLineSearch`, `SNESSetLineSearch()`, `SNESLineSearchCreate()`, `SNESLineSearchSetFromOptions()` 59449e764e56SPeter Brune @*/ 5945d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch) 5946d71ae5a4SJacob Faibussowitsch { 59479e764e56SPeter Brune const char *optionsprefix; 59489e764e56SPeter Brune 59499e764e56SPeter Brune PetscFunctionBegin; 59509e764e56SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 59514f572ea9SToby Isaac PetscAssertPointer(linesearch, 2); 59529e764e56SPeter Brune if (!snes->linesearch) { 59539566063dSJacob Faibussowitsch PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 59549566063dSJacob Faibussowitsch PetscCall(SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch)); 59559566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetSNES(snes->linesearch, snes)); 59569566063dSJacob Faibussowitsch PetscCall(SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix)); 59579566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->linesearch, (PetscObject)snes, 1)); 59589e764e56SPeter Brune } 59599e764e56SPeter Brune *linesearch = snes->linesearch; 59603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 59619e764e56SPeter Brune } 5962