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