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