xref: /petsc/src/snes/mf/snesmfj.c (revision 7a7abfa69b0374585fa8a72fee458bcb23e2090a)
1 #define PETSCSNES_DLL
2 
3 #include "include/private/snesimpl.h"  /*I  "petscsnes.h" I*/
4 #include "include/private/matimpl.h"
5 #include "src/mat/impls/mffd/mffdimpl.h"
6 
7 #undef __FUNCT__
8 #define __FUNCT__ "MatMFFDComputeJacobian"
9 /*@
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.
35 
36 .seealso: MatMFFDGetH(), MatCreateSNESMF(), MatCreateMFFD(), MATMFFD,
37           MatMFFDSetHHistory(),
38           MatMFFDKSPMonitor(), MatMFFDSetFunctionError(), MatMFFDCreate(), SNESSetJacobian()
39 
40 @*/
41 PetscErrorCode PETSCSNES_DLLEXPORT MatMFFDComputeJacobian(SNES snes,Vec x,Mat *jac,Mat *B,MatStructure *flag,void *dummy)
42 {
43   PetscErrorCode ierr;
44   PetscFunctionBegin;
45   ierr = MatAssemblyBegin(*jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
46   ierr = MatAssemblyEnd(*jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
47   PetscFunctionReturn(0);
48 }
49 
50 PetscErrorCode MatAssemblyEnd_MFFD(Mat,MatAssemblyType);
51 #undef __FUNCT__
52 #define __FUNCT__ "MatAssemblyEnd_SNESMF"
53 /*
54    MatAssemblyEnd_SNESMF - Calls MatAssemblyEnd_MFFD() and then sets the
55     base from the SNES context
56 
57 */
58 PetscErrorCode MatAssemblyEnd_SNESMF(Mat J,MatAssemblyType mt)
59 {
60   PetscErrorCode ierr;
61   MatMFFD        j = (MatMFFD)J->data;
62   SNES           snes = (SNES)j->funcctx;
63 
64   PetscFunctionBegin;
65   ierr = MatAssemblyEnd_MFFD(J,mt);CHKERRQ(ierr);
66 
67   ierr = SNESGetSolution(snes,&j->current_u);CHKERRQ(ierr);
68   ierr = SNESGetFunction(snes,&j->current_f,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
69   if (!j->w) {
70     ierr = VecDuplicate(j->current_u, &j->w);CHKERRQ(ierr);
71   }
72   PetscFunctionReturn(0);
73 }
74 
75 EXTERN_C_BEGIN
76 extern PetscErrorCode PETSCMAT_DLLEXPORT MatMFFDSetBase_FD(Mat,Vec,Vec);
77 /*
78     This routine resets the MatAssemblyEnd() for the MatMFFD created from MatCreateSNESMF() so that it NO longer
79   uses the solution in the SNES object to update the base. See the warning in MatCreateSNESMF().
80 */
81 #undef __FUNCT__
82 #define __FUNCT__ "MatMFFDSetBase_SNESMF"
83 PetscErrorCode PETSCMAT_DLLEXPORT MatMFFDSetBase_SNESMF(Mat J,Vec U,Vec F)
84 {
85   PetscErrorCode ierr;
86 
87   PetscFunctionBegin;
88   ierr = MatMFFDSetBase_FD(J,U,F);CHKERRQ(ierr);
89   J->ops->assemblyend = MatAssemblyEnd_MFFD;
90   PetscFunctionReturn(0);
91 }
92 EXTERN_C_END
93 
94 #undef __FUNCT__
95 #define __FUNCT__ "MatCreateSNESMF"
96 /*@
97    MatCreateSNESMF - Creates a matrix-free matrix context for use with
98    a SNES solver.  This matrix can be used as the Jacobian argument for
99    the routine SNESSetJacobian(). See MatCreateMFFD() for details on how
100    the finite difference computation is done.
101 
102    Collective on SNES and Vec
103 
104    Input Parameters:
105 +  snes - the SNES context
106 -  x - vector where SNES solution is to be stored.
107 
108    Output Parameter:
109 .  J - the matrix-free matrix
110 
111    Level: advanced
112 
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.
117 
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().
121 
122 .seealso: MatDestroy(), MatMFFDSetFunctionError(), MatMFFDDefaultSetUmin()
123           MatMFFDSetHHistory(), MatMFFDResetHHistory(), MatCreateMFFD(),
124           MatMFFDGetH(),MatMFFDKSPMonitor(), MatMFFDRegisterDynamic), MatMFFDComputeJacobian()
125 
126 @*/
127 PetscErrorCode PETSCSNES_DLLEXPORT MatCreateSNESMF(SNES snes,Vec x,Mat *J)
128 {
129   PetscErrorCode ierr;
130 
131   PetscFunctionBegin;
132   ierr = MatCreateMFFD(x,J);CHKERRQ(ierr);
133   ierr = MatMFFDSetFunction(*J,(PetscErrorCode (*)(void*, _p_Vec*, _p_Vec*))SNESComputeFunction,snes);CHKERRQ(ierr);
134   (*J)->ops->assemblyend = MatAssemblyEnd_SNESMF;
135   ierr = PetscObjectComposeFunctionDynamic((PetscObject)*J,"MatMFFDSetBase_C","MatMFFDSetBase_SNESMF",MatMFFDSetBase_SNESMF);CHKERRQ(ierr);
136   PetscFunctionReturn(0);
137 }
138 
139 
140 
141 
142 
143 
144