xref: /petsc/src/snes/interface/snesj2.c (revision f6dfbefd03961ab3be6f06be75c96cbf27a49667)
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