191627157SBarry Smith 2af0996ceSBarry Smith #include <petsc/private/snesimpl.h> /*I "petscsnes.h" I*/ 31e25c274SJed Brown #include <petscdm.h> /*I "petscdm.h" I*/ 491627157SBarry Smith 562cd874fSBarry Smith /* 662cd874fSBarry Smith MatFDColoringSetFunction() takes a function with four arguments, we want to use SNESComputeFunction() 762cd874fSBarry Smith since it logs function computation information. 862cd874fSBarry Smith */ 99371c9d4SSatish Balay static PetscErrorCode SNESComputeFunctionCtx(SNES snes, Vec x, Vec f, void *ctx) { 1062cd874fSBarry Smith return SNESComputeFunction(snes, x, f); 1162cd874fSBarry Smith } 129371c9d4SSatish Balay static PetscErrorCode SNESComputeMFFunctionCtx(SNES snes, Vec x, Vec f, void *ctx) { 130df40c35SBarry Smith return SNESComputeMFFunction(snes, x, f); 140df40c35SBarry Smith } 1562cd874fSBarry Smith 1691627157SBarry Smith /*@C 178d359177SBarry Smith SNESComputeJacobianDefaultColor - Computes the Jacobian using 18b4fc646aSLois Curfman McInnes finite differences and coloring to exploit matrix sparsity. 1991627157SBarry Smith 20*f6dfbefdSBarry Smith Collective on snes 21fee21e36SBarry Smith 22c7afd0dbSLois Curfman McInnes Input Parameters: 23c7afd0dbSLois Curfman McInnes + snes - nonlinear solver object 24c7afd0dbSLois Curfman McInnes . x1 - location at which to evaluate Jacobian 257fb41025SPeter Brune - ctx - MatFDColoring context or NULL 26c7afd0dbSLois Curfman McInnes 27c7afd0dbSLois Curfman McInnes Output Parameters: 28c7afd0dbSLois Curfman McInnes + J - Jacobian matrix (not altered in this routine) 2956744491SBarry Smith - B - newly computed Jacobian matrix to use with preconditioner (generally the same as J) 30c7afd0dbSLois Curfman McInnes 3136851e7fSLois Curfman McInnes Level: intermediate 3236851e7fSLois Curfman McInnes 33*f6dfbefdSBarry Smith Options Database Keys: 345620d6dcSBarry Smith + -snes_fd_color_use_mat - use a matrix coloring from the explicit matrix nonzero pattern instead of from the DM providing the matrix 35*f6dfbefdSBarry Smith . -snes_fd_color - Activates `SNESComputeJacobianDefaultColor()` in `SNESSetFromOptions()` 365620d6dcSBarry Smith . -mat_fd_coloring_err <err> - Sets <err> (square root of relative error in the function) 375620d6dcSBarry Smith . -mat_fd_coloring_umin <umin> - Sets umin, the minimum allowable u-value magnitude 38*f6dfbefdSBarry Smith . -mat_fd_type - Either wp or ds (see `MATMFFD_WP` or `MATMFFD_DS`) 39ec5066bdSBarry Smith . -snes_mf_operator - Use matrix free application of Jacobian 40a5b23f4aSJose E. Roman - -snes_mf - Use matrix free Jacobian with no explicit Jacobian representation 415620d6dcSBarry Smith 4295452b02SPatrick Sanan Notes: 4395452b02SPatrick Sanan If the coloring is not provided through the context, this will first try to get the 44*f6dfbefdSBarry Smith coloring from the `DM`. If the `DM` has no coloring routine, then it will try to 45*f6dfbefdSBarry Smith get the coloring from the matrix. This requires that the matrix have its nonzero locations already provided. 46b0ae01b7SPeter Brune 47*f6dfbefdSBarry Smith `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free via `SNESSetUseMatrixFree()`, 48*f6dfbefdSBarry Smith and computing explicitly with finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation 49*f6dfbefdSBarry Smith and the `MatFDColoring` object, see src/ts/tutorials/autodiff/ex16adj_tl.cxx 50ec5066bdSBarry Smith 51*f6dfbefdSBarry Smith This function can be provided to `SNESSetJacobian()` along with an appropriate sparse matrix to hold the Jacobian 52*f6dfbefdSBarry Smith 53*f6dfbefdSBarry Smith .seealso: `SNES`, `SNESSetJacobian()`, `SNESTestJacobian()`, `SNESComputeJacobianDefault()`, `SNESSetUseMatrixFree()`, 54db781477SPatrick Sanan `MatFDColoringCreate()`, `MatFDColoringSetFunction()` 5591627157SBarry Smith @*/ 569371c9d4SSatish Balay PetscErrorCode SNESComputeJacobianDefaultColor(SNES snes, Vec x1, Mat J, Mat B, void *ctx) { 577fb41025SPeter Brune MatFDColoring color = (MatFDColoring)ctx; 584e269d77SPeter Brune DM dm; 59335efc43SPeter Brune MatColoring mc; 604e269d77SPeter Brune ISColoring iscoloring; 61b0ae01b7SPeter Brune PetscBool hascolor; 62aa2f1b4eSJed Brown PetscBool solvec, matcolor = PETSC_FALSE; 630df40c35SBarry Smith DMSNES dms; 64dff777c9SBarry Smith 653a40ed3dSBarry Smith PetscFunctionBegin; 66064a246eSJacob Faibussowitsch if (color) PetscValidHeaderSpecific(color, MAT_FDCOLORING_CLASSID, 5); 679566063dSJacob Faibussowitsch if (!color) PetscCall(PetscObjectQuery((PetscObject)B, "SNESMatFDColoring", (PetscObject *)&color)); 6862cd874fSBarry Smith 694e269d77SPeter Brune if (!color) { 709566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 719566063dSJacob Faibussowitsch PetscCall(DMHasColoring(dm, &hascolor)); 72924833adSPeter Brune matcolor = PETSC_FALSE; 739566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_fd_color_use_mat", &matcolor, NULL)); 74c3138ed3SPeter Brune if (hascolor && !matcolor) { 759566063dSJacob Faibussowitsch PetscCall(DMCreateColoring(dm, IS_COLORING_GLOBAL, &iscoloring)); 76b0ae01b7SPeter Brune } else { 779566063dSJacob Faibussowitsch PetscCall(MatColoringCreate(B, &mc)); 789566063dSJacob Faibussowitsch PetscCall(MatColoringSetDistance(mc, 2)); 799566063dSJacob Faibussowitsch PetscCall(MatColoringSetType(mc, MATCOLORINGSL)); 809566063dSJacob Faibussowitsch PetscCall(MatColoringSetFromOptions(mc)); 819566063dSJacob Faibussowitsch PetscCall(MatColoringApply(mc, &iscoloring)); 829566063dSJacob Faibussowitsch PetscCall(MatColoringDestroy(&mc)); 830df40c35SBarry Smith } 849566063dSJacob Faibussowitsch PetscCall(MatFDColoringCreate(B, iscoloring, &color)); 859566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &dms)); 860df40c35SBarry Smith if (dms->ops->computemffunction) { 879566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFunction(color, (PetscErrorCode(*)(void))SNESComputeMFFunctionCtx, NULL)); 880df40c35SBarry Smith } else { 899566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFunction(color, (PetscErrorCode(*)(void))SNESComputeFunctionCtx, NULL)); 900df40c35SBarry Smith } 919566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFromOptions(color)); 929566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetUp(B, iscoloring, color)); 939566063dSJacob Faibussowitsch PetscCall(ISColoringDestroy(&iscoloring)); 949566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)B, "SNESMatFDColoring", (PetscObject)color)); 959566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)color)); 964a9d489dSBarry Smith } 9795862db2SPeter Brune 98c89319d2SPeter Brune /* F is only usable if there is no RHS on the SNES and the full solution corresponds to x1 */ 999566063dSJacob Faibussowitsch PetscCall(VecEqual(x1, snes->vec_sol, &solvec)); 100c89319d2SPeter Brune if (!snes->vec_rhs && solvec) { 10162cd874fSBarry Smith Vec F; 1029566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &F, NULL, NULL)); 1039566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetF(color, F)); 10495862db2SPeter Brune } 1059566063dSJacob Faibussowitsch PetscCall(MatFDColoringApply(B, color, x1, snes)); 10694ab13aaSBarry Smith if (J != B) { 1079566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 1089566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 109194405b3SBarry Smith } 1103a40ed3dSBarry Smith PetscFunctionReturn(0); 11191627157SBarry Smith } 112