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