xref: /petsc/src/snes/mf/snesmfj.c (revision 7d0a6c19129e7069c8a40e210b34ed62989173db)
1 
2 #include "private/snesimpl.h"  /*I  "petscsnes.h" I*/
3 #include "../src/mat/impls/mffd/mffdimpl.h"
4 #include "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() 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.
35 
36 .seealso: MatMFFDGetH(), MatCreateSNESMF(), MatCreateMFFD(), MATMFFD,
37           MatMFFDSetHHistory(), MatMFFDSetFunctionError(), MatCreateMFFD(), SNESSetJacobian()
38 
39 @*/
40 PetscErrorCode  MatMFFDComputeJacobian(SNES snes,Vec x,Mat *jac,Mat *B,MatStructure *flag,void *dummy)
41 {
42   PetscErrorCode ierr;
43   PetscFunctionBegin;
44   ierr = MatAssemblyBegin(*jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
45   ierr = MatAssemblyEnd(*jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
46   PetscFunctionReturn(0);
47 }
48 
49 PetscErrorCode MatAssemblyEnd_MFFD(Mat,MatAssemblyType);
50 #undef __FUNCT__
51 #define __FUNCT__ "MatAssemblyEnd_SNESMF"
52 /*
53    MatAssemblyEnd_SNESMF - Calls MatAssemblyEnd_MFFD() and then sets the
54     base from the SNES context
55 
56 */
57 PetscErrorCode MatAssemblyEnd_SNESMF(Mat J,MatAssemblyType mt)
58 {
59   PetscErrorCode ierr;
60   MatMFFD        j = (MatMFFD)J->data;
61   SNES           snes = (SNES)j->funcctx;
62   Vec            u,f;
63 
64   PetscFunctionBegin;
65   ierr = MatAssemblyEnd_MFFD(J,mt);CHKERRQ(ierr);
66 
67   ierr = SNESGetSolution(snes,&u);CHKERRQ(ierr);
68   ierr = SNESGetFunction(snes,&f,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
69   ierr = MatMFFDSetBase(J,u,f);CHKERRQ(ierr);
70   PetscFunctionReturn(0);
71 }
72 
73 EXTERN_C_BEGIN
74 extern PetscErrorCode  MatMFFDSetBase_MFFD(Mat,Vec,Vec);
75 /*
76     This routine resets the MatAssemblyEnd() for the MatMFFD created from MatCreateSNESMF() so that it NO longer
77   uses the solution in the SNES object to update the base. See the warning in MatCreateSNESMF().
78 */
79 #undef __FUNCT__
80 #define __FUNCT__ "MatMFFDSetBase_SNESMF"
81 PetscErrorCode  MatMFFDSetBase_SNESMF(Mat J,Vec U,Vec F)
82 {
83   PetscErrorCode ierr;
84 
85   PetscFunctionBegin;
86   ierr = MatMFFDSetBase_MFFD(J,U,F);CHKERRQ(ierr);
87   J->ops->assemblyend = MatAssemblyEnd_MFFD;
88   PetscFunctionReturn(0);
89 }
90 EXTERN_C_END
91 
92 #undef __FUNCT__
93 #define __FUNCT__ "MatCreateSNESMF"
94 /*@
95    MatCreateSNESMF - Creates a matrix-free matrix context for use with
96    a SNES solver.  This matrix can be used as the Jacobian argument for
97    the routine SNESSetJacobian(). See MatCreateMFFD() for details on how
98    the finite difference computation is done.
99 
100    Collective on SNES and Vec
101 
102    Input Parameters:
103 .  snes - the SNES context
104 
105    Output Parameter:
106 .  J - the matrix-free matrix
107 
108    Level: advanced
109 
110    Warning:
111       If MatMFFDSetBase() is ever called on jac then this routine will NO longer get
112     the x from the SNES object and MatMFFDSetBase() must from that point on be used to
113     change the base vector x.
114 
115    Notes: The difference between this routine and MatCreateMFFD() is that this matrix
116      automatically gets the current base vector from the SNES object and not from an
117      explicit call to MatMFFDSetBase().
118 
119 .seealso: MatDestroy(), MatMFFDSetFunctionError(), MatMFFDDSSetUmin()
120           MatMFFDSetHHistory(), MatMFFDResetHHistory(), MatCreateMFFD(),
121           MatMFFDGetH(), MatMFFDRegisterDynamic), MatMFFDComputeJacobian()
122 
123 @*/
124 PetscErrorCode  MatCreateSNESMF(SNES snes,Mat *J)
125 {
126   PetscErrorCode ierr;
127   PetscInt       n,N;
128 
129   PetscFunctionBegin;
130   if (!snes->vec_func) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"SNESSetFunction() must be called first");
131 
132   ierr = VecGetLocalSize(snes->vec_func,&n);CHKERRQ(ierr);
133   ierr = VecGetSize(snes->vec_func,&N);CHKERRQ(ierr);
134   ierr = MatCreateMFFD(((PetscObject)snes)->comm,n,n,N,N,J);CHKERRQ(ierr);
135   ierr = MatMFFDSetFunction(*J,(PetscErrorCode (*)(void*,Vec,Vec))SNESComputeFunction,snes);CHKERRQ(ierr);
136   (*J)->ops->assemblyend = MatAssemblyEnd_SNESMF;
137   ierr = PetscObjectComposeFunctionDynamic((PetscObject)*J,"MatMFFDSetBase_C","MatMFFDSetBase_SNESMF",MatMFFDSetBase_SNESMF);CHKERRQ(ierr);
138   PetscFunctionReturn(0);
139 }
140 
141 
142 
143 
144 
145 
146