1 2 #include <petsc-private/snesimpl.h> /*I "petscsnes.h" I*/ 3 #include <../src/mat/impls/mffd/mffdimpl.h> 4 #include <petsc-private/matimpl.h> 5 6 #undef __FUNCT__ 7 #define __FUNCT__ "MatMFFDComputeJacobian" 8 /*@C 9 MatMFFDComputeJacobian - Tells the matrix-free Jacobian object the new location at which 10 Jacobian matrix vector products will be computed at, i.e. J(x) * a. The x is obtained 11 from the SNES object (using SNESGetSolution()). 12 13 Logically Collective on SNES 14 15 Input Parameters: 16 + snes - the nonlinear solver context 17 . x - the point at which the Jacobian vector products will be performed 18 . jac - the matrix-free Jacobian object 19 . B - either the same as jac or another matrix type (ignored) 20 . flag - not relevent for matrix-free form 21 - dummy - the user context (ignored) 22 23 Level: developer 24 25 Warning: 26 If MatMFFDSetBase() is ever called on jac then this routine will NO longer get 27 the x from the SNES object and MatMFFDSetBase() must from that point on be used to 28 change the base vector x. 29 30 Notes: 31 This can be passed into SNESSetJacobian() as the Jacobian evaluation function argument 32 when using a completely matrix-free solver, 33 that is the B matrix is also the same matrix operator. This is used when you select 34 -snes_mf but rarely used directly by users. (All this routine does is call MatAssemblyBegin/End() on 35 the Mat jac. 36 37 .seealso: MatMFFDGetH(), MatCreateSNESMF(), MatCreateMFFD(), MATMFFD, 38 MatMFFDSetHHistory(), MatMFFDSetFunctionError(), MatCreateMFFD(), SNESSetJacobian() 39 40 @*/ 41 PetscErrorCode MatMFFDComputeJacobian(SNES snes,Vec x,Mat *jac,Mat *B,MatStructure *flag,void *dummy) 42 { 43 PetscErrorCode ierr; 44 45 PetscFunctionBegin; 46 ierr = MatAssemblyBegin(*jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 47 ierr = MatAssemblyEnd(*jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 48 PetscFunctionReturn(0); 49 } 50 51 PetscErrorCode MatAssemblyEnd_MFFD(Mat,MatAssemblyType); 52 EXTERN_C_BEGIN 53 PetscErrorCode MatMFFDSetBase_MFFD(Mat,Vec,Vec); 54 EXTERN_C_END 55 56 #undef __FUNCT__ 57 #define __FUNCT__ "MatAssemblyEnd_SNESMF" 58 /* 59 MatAssemblyEnd_SNESMF - Calls MatAssemblyEnd_MFFD() and then sets the 60 base from the SNES context 61 62 */ 63 PetscErrorCode MatAssemblyEnd_SNESMF(Mat J,MatAssemblyType mt) 64 { 65 PetscErrorCode ierr; 66 MatMFFD j = (MatMFFD)J->data; 67 SNES snes = (SNES)j->funcctx; 68 Vec u,f; 69 70 PetscFunctionBegin; 71 ierr = MatAssemblyEnd_MFFD(J,mt);CHKERRQ(ierr); 72 73 ierr = SNESGetSolution(snes,&u);CHKERRQ(ierr); 74 ierr = SNESGetFunction(snes,&f,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 75 ierr = MatMFFDSetBase_MFFD(J,u,f);CHKERRQ(ierr); 76 PetscFunctionReturn(0); 77 } 78 79 EXTERN_C_BEGIN 80 /* 81 This routine resets the MatAssemblyEnd() for the MatMFFD created from MatCreateSNESMF() so that it NO longer 82 uses the solution in the SNES object to update the base. See the warning in MatCreateSNESMF(). 83 */ 84 #undef __FUNCT__ 85 #define __FUNCT__ "MatMFFDSetBase_SNESMF" 86 PetscErrorCode MatMFFDSetBase_SNESMF(Mat J,Vec U,Vec F) 87 { 88 PetscErrorCode ierr; 89 90 PetscFunctionBegin; 91 ierr = MatMFFDSetBase_MFFD(J,U,F);CHKERRQ(ierr); 92 93 J->ops->assemblyend = MatAssemblyEnd_MFFD; 94 PetscFunctionReturn(0); 95 } 96 EXTERN_C_END 97 98 #undef __FUNCT__ 99 #define __FUNCT__ "MatCreateSNESMF" 100 /*@ 101 MatCreateSNESMF - Creates a matrix-free matrix context for use with 102 a SNES solver. This matrix can be used as the Jacobian argument for 103 the routine SNESSetJacobian(). See MatCreateMFFD() for details on how 104 the finite difference computation is done. 105 106 Collective on SNES and Vec 107 108 Input Parameters: 109 . snes - the SNES context 110 111 Output Parameter: 112 . J - the matrix-free matrix 113 114 Level: advanced 115 116 Warning: 117 If MatMFFDSetBase() is ever called on jac then this routine will NO longer get 118 the x from the SNES object and MatMFFDSetBase() must from that point on be used to 119 change the base vector x. 120 121 Notes: The difference between this routine and MatCreateMFFD() is that this matrix 122 automatically gets the current base vector from the SNES object and not from an 123 explicit call to MatMFFDSetBase(). 124 125 .seealso: MatDestroy(), MatMFFDSetFunctionError(), MatMFFDDSSetUmin() 126 MatMFFDSetHHistory(), MatMFFDResetHHistory(), MatCreateMFFD(), 127 MatMFFDGetH(), MatMFFDRegisterDynamic), MatMFFDComputeJacobian() 128 129 @*/ 130 PetscErrorCode MatCreateSNESMF(SNES snes,Mat *J) 131 { 132 PetscErrorCode ierr; 133 PetscInt n,N; 134 135 PetscFunctionBegin; 136 if (snes->vec_func) { 137 ierr = VecGetLocalSize(snes->vec_func,&n);CHKERRQ(ierr); 138 ierr = VecGetSize(snes->vec_func,&N);CHKERRQ(ierr); 139 } else if (snes->dm) { 140 Vec tmp; 141 ierr = DMGetGlobalVector(snes->dm,&tmp);CHKERRQ(ierr); 142 ierr = VecGetLocalSize(tmp,&n);CHKERRQ(ierr); 143 ierr = VecGetSize(tmp,&N);CHKERRQ(ierr); 144 ierr = DMRestoreGlobalVector(snes->dm,&tmp);CHKERRQ(ierr); 145 } else SETERRQ(((PetscObject)snes)->comm,PETSC_ERR_ARG_WRONGSTATE,"Must call SNESSetFunction() or SNESSetDM() first"); 146 ierr = MatCreateMFFD(((PetscObject)snes)->comm,n,n,N,N,J);CHKERRQ(ierr); 147 ierr = MatMFFDSetFunction(*J,(PetscErrorCode (*)(void*,Vec,Vec))SNESComputeFunction,snes);CHKERRQ(ierr); 148 149 (*J)->ops->assemblyend = MatAssemblyEnd_SNESMF; 150 151 ierr = PetscObjectComposeFunctionDynamic((PetscObject)*J,"MatMFFDSetBase_C","MatMFFDSetBase_SNESMF",MatMFFDSetBase_SNESMF);CHKERRQ(ierr); 152 PetscFunctionReturn(0); 153 } 154 155 156 157 158 159 160