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