xref: /petsc/src/snes/interface/snesj2.c (revision 0df40c3555541438f50e9ac13eaa6989b426b66a)
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 */
962cd874fSBarry Smith static PetscErrorCode SNESComputeFunctionCtx(SNES snes,Vec x,Vec f,void *ctx)
1062cd874fSBarry Smith {
1162cd874fSBarry Smith   return SNESComputeFunction(snes,x,f);
1262cd874fSBarry Smith }
13*0df40c35SBarry Smith static PetscErrorCode SNESComputeMFFunctionCtx(SNES snes,Vec x,Vec f,void *ctx)
14*0df40c35SBarry Smith {
15*0df40c35SBarry Smith   return SNESComputeMFFunction(snes,x,f);
16*0df40c35SBarry Smith }
1762cd874fSBarry Smith 
1891627157SBarry Smith /*@C
198d359177SBarry Smith     SNESComputeJacobianDefaultColor - Computes the Jacobian using
20b4fc646aSLois Curfman McInnes     finite differences and coloring to exploit matrix sparsity.
2191627157SBarry Smith 
22fee21e36SBarry Smith     Collective on SNES
23fee21e36SBarry Smith 
24c7afd0dbSLois Curfman McInnes     Input Parameters:
25c7afd0dbSLois Curfman McInnes +   snes - nonlinear solver object
26c7afd0dbSLois Curfman McInnes .   x1 - location at which to evaluate Jacobian
277fb41025SPeter Brune -   ctx - MatFDColoring context or NULL
28c7afd0dbSLois Curfman McInnes 
29c7afd0dbSLois Curfman McInnes     Output Parameters:
30c7afd0dbSLois Curfman McInnes +   J - Jacobian matrix (not altered in this routine)
3156744491SBarry Smith -   B - newly computed Jacobian matrix to use with preconditioner (generally the same as J)
32c7afd0dbSLois Curfman McInnes 
3336851e7fSLois Curfman McInnes     Level: intermediate
3436851e7fSLois Curfman McInnes 
355620d6dcSBarry Smith    Options Database Key:
365620d6dcSBarry Smith +  -snes_fd_color_use_mat - use a matrix coloring from the explicit matrix nonzero pattern instead of from the DM providing the matrix
375620d6dcSBarry Smith .  -snes_fd_color - Activates SNESComputeJacobianDefaultColor() in SNESSetFromOptions()
385620d6dcSBarry Smith .  -mat_fd_coloring_err <err> - Sets <err> (square root of relative error in the function)
395620d6dcSBarry Smith .  -mat_fd_coloring_umin <umin> - Sets umin, the minimum allowable u-value magnitude
40ec5066bdSBarry Smith .  -mat_fd_type - Either wp or ds (see MATMFFD_WP or MATMFFD_DS)
41ec5066bdSBarry Smith .  -snes_mf_operator - Use matrix free application of Jacobian
42*0df40c35SBarry Smith -  -snes_mf - Use matrix free Jacobian with no explicit Jacobian represenation
435620d6dcSBarry Smith 
4495452b02SPatrick Sanan     Notes:
4595452b02SPatrick Sanan         If the coloring is not provided through the context, this will first try to get the
467fb41025SPeter Brune         coloring from the DM.  If the DM type has no coloring routine, then it will try to
477fb41025SPeter Brune         get the coloring from the matrix.  This requires that the matrix have nonzero entries
48f80563f6SBarry Smith         precomputed.
49b0ae01b7SPeter Brune 
50*0df40c35SBarry Smith        SNES supports three approaches for computing (approximate) Jacobians: user provided via SNESSetJacobian(), matrix free via SNESSetUseMatrixFree(),
51*0df40c35SBarry Smith        and computing explictly with finite differences and coloring using MatFDColoring. It is also possible to use automatic differentiation
52*0df40c35SBarry Smith        and the MatFDColoring object, see src/ts/tutorials/autodiff/ex16adj_tl.cxx
53ec5066bdSBarry Smith 
54ec5066bdSBarry Smith 
55ec5066bdSBarry Smith .seealso: SNESSetJacobian(), SNESTestJacobian(), SNESComputeJacobianDefault(), SNESSetUseMatrixFree(),
56ab637aeaSJed Brown           MatFDColoringCreate(), MatFDColoringSetFunction()
57cb5b572fSBarry Smith 
5891627157SBarry Smith @*/
59d1e9a80fSBarry Smith PetscErrorCode  SNESComputeJacobianDefaultColor(SNES snes,Vec x1,Mat J,Mat B,void *ctx)
6091627157SBarry Smith {
617fb41025SPeter Brune   MatFDColoring  color = (MatFDColoring)ctx;
62dfbe8321SBarry Smith   PetscErrorCode ierr;
634e269d77SPeter Brune   DM             dm;
64335efc43SPeter Brune   MatColoring    mc;
654e269d77SPeter Brune   ISColoring     iscoloring;
66b0ae01b7SPeter Brune   PetscBool      hascolor;
67aa2f1b4eSJed Brown   PetscBool      solvec,matcolor = PETSC_FALSE;
68*0df40c35SBarry Smith   DMSNES         dms;
69dff777c9SBarry Smith 
703a40ed3dSBarry Smith   PetscFunctionBegin;
717fb41025SPeter Brune   if (color) PetscValidHeaderSpecific(color,MAT_FDCOLORING_CLASSID,6);
72d27375acSBarry Smith   if (!color) {ierr  = PetscObjectQuery((PetscObject)B,"SNESMatFDColoring",(PetscObject*)&color);CHKERRQ(ierr);}
7362cd874fSBarry Smith 
744e269d77SPeter Brune   if (!color) {
754e269d77SPeter Brune     ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr);
76b0ae01b7SPeter Brune     ierr = DMHasColoring(dm,&hascolor);CHKERRQ(ierr);
77924833adSPeter Brune     matcolor = PETSC_FALSE;
78c5929fdfSBarry Smith     ierr = PetscOptionsGetBool(((PetscObject)snes)->options,((PetscObject)snes)->prefix,"-snes_fd_color_use_mat",&matcolor,NULL);CHKERRQ(ierr);
79c3138ed3SPeter Brune     if (hascolor && !matcolor) {
80b412c318SBarry Smith       ierr = DMCreateColoring(dm,IS_COLORING_GLOBAL,&iscoloring);CHKERRQ(ierr);
81b0ae01b7SPeter Brune     } else {
8294ab13aaSBarry Smith       ierr = MatColoringCreate(B,&mc);CHKERRQ(ierr);
83335efc43SPeter Brune       ierr = MatColoringSetDistance(mc,2);CHKERRQ(ierr);
84335efc43SPeter Brune       ierr = MatColoringSetType(mc,MATCOLORINGSL);CHKERRQ(ierr);
85335efc43SPeter Brune       ierr = MatColoringSetFromOptions(mc);CHKERRQ(ierr);
86335efc43SPeter Brune       ierr = MatColoringApply(mc,&iscoloring);CHKERRQ(ierr);
87335efc43SPeter Brune       ierr = MatColoringDestroy(&mc);CHKERRQ(ierr);
88*0df40c35SBarry Smith     }
8994ab13aaSBarry Smith     ierr = MatFDColoringCreate(B,iscoloring,&color);CHKERRQ(ierr);
90*0df40c35SBarry Smith     ierr = DMGetDMSNES(dm,&dms);CHKERRQ(ierr);
91*0df40c35SBarry Smith     if (dms->ops->computemffunction) {
92*0df40c35SBarry Smith       ierr = MatFDColoringSetFunction(color,(PetscErrorCode (*)(void))SNESComputeMFFunctionCtx,NULL);CHKERRQ(ierr);
93*0df40c35SBarry Smith     } else {
9462cd874fSBarry Smith       ierr = MatFDColoringSetFunction(color,(PetscErrorCode (*)(void))SNESComputeFunctionCtx,NULL);CHKERRQ(ierr);
95*0df40c35SBarry Smith     }
96b0ae01b7SPeter Brune     ierr = MatFDColoringSetFromOptions(color);CHKERRQ(ierr);
9794ab13aaSBarry Smith     ierr = MatFDColoringSetUp(B,iscoloring,color);CHKERRQ(ierr);
98f86b9fbaSHong Zhang     ierr = ISColoringDestroy(&iscoloring);CHKERRQ(ierr);
9994ab13aaSBarry Smith     ierr = PetscObjectCompose((PetscObject)B,"SNESMatFDColoring",(PetscObject)color);CHKERRQ(ierr);
1004108615fSPeter Brune     ierr = PetscObjectDereference((PetscObject)color);CHKERRQ(ierr);
1014a9d489dSBarry Smith   }
10295862db2SPeter Brune 
103c89319d2SPeter Brune   /* F is only usable if there is no RHS on the SNES and the full solution corresponds to x1 */
104c89319d2SPeter Brune   ierr = VecEqual(x1,snes->vec_sol,&solvec);CHKERRQ(ierr);
105c89319d2SPeter Brune   if (!snes->vec_rhs && solvec) {
10662cd874fSBarry Smith     Vec F;
10762cd874fSBarry Smith     ierr = SNESGetFunction(snes,&F,NULL,NULL);CHKERRQ(ierr);
108432bb422SPeter Brune     ierr = MatFDColoringSetF(color,F);CHKERRQ(ierr);
10995862db2SPeter Brune   }
110d1e9a80fSBarry Smith   ierr = MatFDColoringApply(B,color,x1,snes);CHKERRQ(ierr);
11194ab13aaSBarry Smith   if (J != B) {
11294ab13aaSBarry Smith     ierr = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
11394ab13aaSBarry Smith     ierr = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
114194405b3SBarry Smith   }
1153a40ed3dSBarry Smith   PetscFunctionReturn(0);
11691627157SBarry Smith }
117