Actual source code: snesmfj.c

  2: #include <private/snesimpl.h>  /*I  "petscsnes.h" I*/
  3: #include <../src/mat/impls/mffd/mffdimpl.h>
  4: #include <private/matimpl.h>

  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()).

 13:    Logically Collective on SNES

 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)

 23:    Level: developer

 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.

 30:    Notes:
 31:      This can be passed into SNESSetJacobian() when using a completely matrix-free solver,
 32:      that is the B matrix is also the same matrix operator. This is used when you select
 33:      -snes_mf but rarely used directly by users. (All this routine does is call MatAssemblyBegin/End() on
 34:      the Mat jac.

 36: .seealso: MatMFFDGetH(), MatCreateSNESMF(), MatCreateMFFD(), MATMFFD,
 37:           MatMFFDSetHHistory(), MatMFFDSetFunctionError(), MatCreateMFFD(), SNESSetJacobian()

 39: @*/
 40: PetscErrorCode  MatMFFDComputeJacobian(SNES snes,Vec x,Mat *jac,Mat *B,MatStructure *flag,void *dummy)
 41: {
 44:   MatAssemblyBegin(*jac,MAT_FINAL_ASSEMBLY);
 45:   MatAssemblyEnd(*jac,MAT_FINAL_ASSEMBLY);
 46:   return(0);
 47: }

 49: PetscErrorCode MatAssemblyEnd_MFFD(Mat,MatAssemblyType);
 51: PetscErrorCode MatMFFDSetBase_MFFD(Mat,Vec,Vec);

 56: /*
 57:    MatAssemblyEnd_SNESMF - Calls MatAssemblyEnd_MFFD() and then sets the 
 58:     base from the SNES context

 60: */
 61: PetscErrorCode MatAssemblyEnd_SNESMF(Mat J,MatAssemblyType mt)
 62: {
 64:   MatMFFD        j = (MatMFFD)J->data;
 65:   SNES           snes = (SNES)j->funcctx;
 66:   Vec            u,f;

 69:   MatAssemblyEnd_MFFD(J,mt);

 71:   SNESGetSolution(snes,&u);
 72:   SNESGetFunction(snes,&f,PETSC_NULL,PETSC_NULL);
 73:   MatMFFDSetBase_MFFD(J,u,f);
 74:   return(0);
 75: }

 78: /*
 79:     This routine resets the MatAssemblyEnd() for the MatMFFD created from MatCreateSNESMF() so that it NO longer
 80:   uses the solution in the SNES object to update the base. See the warning in MatCreateSNESMF().
 81: */
 84: PetscErrorCode  MatMFFDSetBase_SNESMF(Mat J,Vec U,Vec F)
 85: {

 89:   MatMFFDSetBase_MFFD(J,U,F);
 90:   J->ops->assemblyend = MatAssemblyEnd_MFFD;
 91:   return(0);
 92: }

 97: /*@
 98:    MatCreateSNESMF - Creates a matrix-free matrix context for use with
 99:    a SNES solver.  This matrix can be used as the Jacobian argument for
100:    the routine SNESSetJacobian(). See MatCreateMFFD() for details on how
101:    the finite difference computation is done.

103:    Collective on SNES and Vec

105:    Input Parameters:
106: .  snes - the SNES context

108:    Output Parameter:
109: .  J - the matrix-free matrix

111:    Level: advanced

113:    Warning: 
114:       If MatMFFDSetBase() is ever called on jac then this routine will NO longer get 
115:     the x from the SNES object and MatMFFDSetBase() must from that point on be used to
116:     change the base vector x.

118:    Notes: The difference between this routine and MatCreateMFFD() is that this matrix
119:      automatically gets the current base vector from the SNES object and not from an
120:      explicit call to MatMFFDSetBase().

122: .seealso: MatDestroy(), MatMFFDSetFunctionError(), MatMFFDDSSetUmin()
123:           MatMFFDSetHHistory(), MatMFFDResetHHistory(), MatCreateMFFD(),
124:           MatMFFDGetH(), MatMFFDRegisterDynamic), MatMFFDComputeJacobian()
125:  
126: @*/
127: PetscErrorCode  MatCreateSNESMF(SNES snes,Mat *J)
128: {
130:   PetscInt       n,N;

133:   if (snes->vec_func) {
134:     VecGetLocalSize(snes->vec_func,&n);
135:     VecGetSize(snes->vec_func,&N);
136:   } else if (snes->dm) {
137:     Vec tmp;
138:     DMGetGlobalVector(snes->dm,&tmp);
139:     VecGetLocalSize(tmp,&n);
140:     VecGetSize(tmp,&N);
141:     DMRestoreGlobalVector(snes->dm,&tmp);
142:   } else SETERRQ(((PetscObject)snes)->comm,PETSC_ERR_ARG_WRONGSTATE,"Must call SNESSetFunction() or SNESSetDM() first");
143:   MatCreateMFFD(((PetscObject)snes)->comm,n,n,N,N,J);
144:   MatMFFDSetFunction(*J,(PetscErrorCode (*)(void*,Vec,Vec))SNESComputeFunction,snes);
145:   (*J)->ops->assemblyend = MatAssemblyEnd_SNESMF;
146:   PetscObjectComposeFunctionDynamic((PetscObject)*J,"MatMFFDSetBase_C","MatMFFDSetBase_SNESMF",MatMFFDSetBase_SNESMF);
147:   return(0);
148: }