xref: /petsc/src/snes/interface/snesj2.c (revision 9371c9d470a9602b6d10a8bf50c9b2280a79e45a)
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 */
9*9371c9d4SSatish Balay static PetscErrorCode SNESComputeFunctionCtx(SNES snes, Vec x, Vec f, void *ctx) {
1062cd874fSBarry Smith   return SNESComputeFunction(snes, x, f);
1162cd874fSBarry Smith }
12*9371c9d4SSatish 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 
20fee21e36SBarry 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 
335620d6dcSBarry Smith    Options Database Key:
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
355620d6dcSBarry 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
38ec5066bdSBarry 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
447fb41025SPeter Brune         coloring from the DM.  If the DM type has no coloring routine, then it will try to
457fb41025SPeter Brune         get the coloring from the matrix.  This requires that the matrix have nonzero entries
46f80563f6SBarry Smith         precomputed.
47b0ae01b7SPeter Brune 
480df40c35SBarry Smith        SNES supports three approaches for computing (approximate) Jacobians: user provided via SNESSetJacobian(), matrix free via SNESSetUseMatrixFree(),
49a5b23f4aSJose E. Roman        and computing explicitly with finite differences and coloring using MatFDColoring. It is also possible to use automatic differentiation
500df40c35SBarry Smith        and the MatFDColoring object, see src/ts/tutorials/autodiff/ex16adj_tl.cxx
51ec5066bdSBarry Smith 
52db781477SPatrick Sanan .seealso: `SNESSetJacobian()`, `SNESTestJacobian()`, `SNESComputeJacobianDefault()`, `SNESSetUseMatrixFree()`,
53db781477SPatrick Sanan           `MatFDColoringCreate()`, `MatFDColoringSetFunction()`
54cb5b572fSBarry Smith 
5591627157SBarry Smith @*/
56*9371c9d4SSatish 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