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: }