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