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