1 2 #include <petsc/private/snesimpl.h> /*I "petscsnes.h" I*/ 3 #include <petscdm.h> /*I "petscdm.h" I*/ 4 5 /* 6 MatFDColoringSetFunction() takes a function with four arguments, we want to use SNESComputeFunction() 7 since it logs function computation information. 8 */ 9 static PetscErrorCode SNESComputeFunctionCtx(SNES snes,Vec x,Vec f,void *ctx) 10 { 11 return SNESComputeFunction(snes,x,f); 12 } 13 static PetscErrorCode SNESComputeMFFunctionCtx(SNES snes,Vec x,Vec f,void *ctx) 14 { 15 return SNESComputeMFFunction(snes,x,f); 16 } 17 18 /*@C 19 SNESComputeJacobianDefaultColor - Computes the Jacobian using 20 finite differences and coloring to exploit matrix sparsity. 21 22 Collective on SNES 23 24 Input Parameters: 25 + snes - nonlinear solver object 26 . x1 - location at which to evaluate Jacobian 27 - ctx - MatFDColoring context or NULL 28 29 Output Parameters: 30 + J - Jacobian matrix (not altered in this routine) 31 - B - newly computed Jacobian matrix to use with preconditioner (generally the same as J) 32 33 Level: intermediate 34 35 Options Database Key: 36 + -snes_fd_color_use_mat - use a matrix coloring from the explicit matrix nonzero pattern instead of from the DM providing the matrix 37 . -snes_fd_color - Activates SNESComputeJacobianDefaultColor() in SNESSetFromOptions() 38 . -mat_fd_coloring_err <err> - Sets <err> (square root of relative error in the function) 39 . -mat_fd_coloring_umin <umin> - Sets umin, the minimum allowable u-value magnitude 40 . -mat_fd_type - Either wp or ds (see MATMFFD_WP or MATMFFD_DS) 41 . -snes_mf_operator - Use matrix free application of Jacobian 42 - -snes_mf - Use matrix free Jacobian with no explicit Jacobian represenation 43 44 Notes: 45 If the coloring is not provided through the context, this will first try to get the 46 coloring from the DM. If the DM type has no coloring routine, then it will try to 47 get the coloring from the matrix. This requires that the matrix have nonzero entries 48 precomputed. 49 50 SNES supports three approaches for computing (approximate) Jacobians: user provided via SNESSetJacobian(), matrix free via SNESSetUseMatrixFree(), 51 and computing explictly with finite differences and coloring using MatFDColoring. It is also possible to use automatic differentiation 52 and the MatFDColoring object, see src/ts/tutorials/autodiff/ex16adj_tl.cxx 53 54 .seealso: SNESSetJacobian(), SNESTestJacobian(), SNESComputeJacobianDefault(), SNESSetUseMatrixFree(), 55 MatFDColoringCreate(), MatFDColoringSetFunction() 56 57 @*/ 58 PetscErrorCode SNESComputeJacobianDefaultColor(SNES snes,Vec x1,Mat J,Mat B,void *ctx) 59 { 60 MatFDColoring color = (MatFDColoring)ctx; 61 PetscErrorCode ierr; 62 DM dm; 63 MatColoring mc; 64 ISColoring iscoloring; 65 PetscBool hascolor; 66 PetscBool solvec,matcolor = PETSC_FALSE; 67 DMSNES dms; 68 69 PetscFunctionBegin; 70 if (color) PetscValidHeaderSpecific(color,MAT_FDCOLORING_CLASSID,5); 71 if (!color) {ierr = PetscObjectQuery((PetscObject)B,"SNESMatFDColoring",(PetscObject*)&color);CHKERRQ(ierr);} 72 73 if (!color) { 74 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 75 ierr = DMHasColoring(dm,&hascolor);CHKERRQ(ierr); 76 matcolor = PETSC_FALSE; 77 ierr = PetscOptionsGetBool(((PetscObject)snes)->options,((PetscObject)snes)->prefix,"-snes_fd_color_use_mat",&matcolor,NULL);CHKERRQ(ierr); 78 if (hascolor && !matcolor) { 79 ierr = DMCreateColoring(dm,IS_COLORING_GLOBAL,&iscoloring);CHKERRQ(ierr); 80 } else { 81 ierr = MatColoringCreate(B,&mc);CHKERRQ(ierr); 82 ierr = MatColoringSetDistance(mc,2);CHKERRQ(ierr); 83 ierr = MatColoringSetType(mc,MATCOLORINGSL);CHKERRQ(ierr); 84 ierr = MatColoringSetFromOptions(mc);CHKERRQ(ierr); 85 ierr = MatColoringApply(mc,&iscoloring);CHKERRQ(ierr); 86 ierr = MatColoringDestroy(&mc);CHKERRQ(ierr); 87 } 88 ierr = MatFDColoringCreate(B,iscoloring,&color);CHKERRQ(ierr); 89 ierr = DMGetDMSNES(dm,&dms);CHKERRQ(ierr); 90 if (dms->ops->computemffunction) { 91 ierr = MatFDColoringSetFunction(color,(PetscErrorCode (*)(void))SNESComputeMFFunctionCtx,NULL);CHKERRQ(ierr); 92 } else { 93 ierr = MatFDColoringSetFunction(color,(PetscErrorCode (*)(void))SNESComputeFunctionCtx,NULL);CHKERRQ(ierr); 94 } 95 ierr = MatFDColoringSetFromOptions(color);CHKERRQ(ierr); 96 ierr = MatFDColoringSetUp(B,iscoloring,color);CHKERRQ(ierr); 97 ierr = ISColoringDestroy(&iscoloring);CHKERRQ(ierr); 98 ierr = PetscObjectCompose((PetscObject)B,"SNESMatFDColoring",(PetscObject)color);CHKERRQ(ierr); 99 ierr = PetscObjectDereference((PetscObject)color);CHKERRQ(ierr); 100 } 101 102 /* F is only usable if there is no RHS on the SNES and the full solution corresponds to x1 */ 103 ierr = VecEqual(x1,snes->vec_sol,&solvec);CHKERRQ(ierr); 104 if (!snes->vec_rhs && solvec) { 105 Vec F; 106 ierr = SNESGetFunction(snes,&F,NULL,NULL);CHKERRQ(ierr); 107 ierr = MatFDColoringSetF(color,F);CHKERRQ(ierr); 108 } 109 ierr = MatFDColoringApply(B,color,x1,snes);CHKERRQ(ierr); 110 if (J != B) { 111 ierr = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 112 ierr = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 113 } 114 PetscFunctionReturn(0); 115 } 116