xref: /petsc/src/snes/mf/snesmfj.c (revision cc2e6a90c05b27ffec69cb207fe793d447f14420)
181e6777dSBarry Smith 
2af0996ceSBarry Smith #include <petsc/private/snesimpl.h>  /*I  "petscsnes.h" I*/
31e25c274SJed Brown #include <petscdm.h>                 /*I  "petscdm.h"   I*/
4c6db04a5SJed Brown #include <../src/mat/impls/mffd/mffdimpl.h>
5af0996ceSBarry Smith #include <petsc/private/matimpl.h>
681e6777dSBarry Smith 
7e884886fSBarry Smith #undef __FUNCT__
8e884886fSBarry Smith #define __FUNCT__ "MatMFFDComputeJacobian"
95fe378a3SBarry Smith /*@C
10e884886fSBarry Smith    MatMFFDComputeJacobian - Tells the matrix-free Jacobian object the new location at which
11174415d9SBarry Smith        Jacobian matrix vector products will be computed at, i.e. J(x) * a. The x is obtained
12174415d9SBarry Smith        from the SNES object (using SNESGetSolution()).
13e884886fSBarry Smith 
143f9fe445SBarry Smith    Logically Collective on SNES
15e884886fSBarry Smith 
16e884886fSBarry Smith    Input Parameters:
17e884886fSBarry Smith +   snes - the nonlinear solver context
18e884886fSBarry Smith .   x - the point at which the Jacobian vector products will be performed
19e884886fSBarry Smith .   jac - the matrix-free Jacobian object
20e884886fSBarry Smith .   B - either the same as jac or another matrix type (ignored)
21e884886fSBarry Smith .   flag - not relevent for matrix-free form
22e884886fSBarry Smith -   dummy - the user context (ignored)
23e884886fSBarry Smith 
24e884886fSBarry Smith    Level: developer
25e884886fSBarry Smith 
26174415d9SBarry Smith    Warning:
27174415d9SBarry Smith       If MatMFFDSetBase() is ever called on jac then this routine will NO longer get
28174415d9SBarry Smith     the x from the SNES object and MatMFFDSetBase() must from that point on be used to
29174415d9SBarry Smith     change the base vector x.
30174415d9SBarry Smith 
31e884886fSBarry Smith    Notes:
32ecaffddaSVictor Eijkhout      This can be passed into SNESSetJacobian() as the Jacobian evaluation function argument
33ecaffddaSVictor Eijkhout      when using a completely matrix-free solver,
34e884886fSBarry Smith      that is the B matrix is also the same matrix operator. This is used when you select
355fe378a3SBarry Smith      -snes_mf but rarely used directly by users. (All this routine does is call MatAssemblyBegin/End() on
3614f633e2SBarry Smith      the Mat jac.)
375fe378a3SBarry Smith 
380decc0a3SBarry Smith .seealso: MatMFFDGetH(), MatCreateSNESMF(), MatCreateMFFD(), MATMFFD,
391d0fab5eSBarry Smith           MatMFFDSetHHistory(), MatMFFDSetFunctionError(), MatCreateMFFD(), SNESSetJacobian()
40e884886fSBarry Smith 
41e884886fSBarry Smith @*/
42d1e9a80fSBarry Smith PetscErrorCode  MatMFFDComputeJacobian(SNES snes,Vec x,Mat jac,Mat B,void *dummy)
43e884886fSBarry Smith {
44e884886fSBarry Smith   PetscErrorCode ierr;
455fd66863SKarl Rupp 
46e884886fSBarry Smith   PetscFunctionBegin;
4794ab13aaSBarry Smith   ierr = MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4894ab13aaSBarry Smith   ierr = MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
49e884886fSBarry Smith   PetscFunctionReturn(0);
50e884886fSBarry Smith }
51e884886fSBarry Smith 
52d8fa6a54SBarry Smith PETSC_EXTERN PetscErrorCode MatAssemblyEnd_MFFD(Mat,MatAssemblyType);
53d8fa6a54SBarry Smith PETSC_EXTERN PetscErrorCode MatMFFDSetBase_MFFD(Mat,Vec,Vec);
54563d23a3SJed Brown 
553ec795f1SBarry Smith #undef __FUNCT__
563ec795f1SBarry Smith #define __FUNCT__ "MatAssemblyEnd_SNESMF"
573ec795f1SBarry Smith /*
583ec795f1SBarry Smith    MatAssemblyEnd_SNESMF - Calls MatAssemblyEnd_MFFD() and then sets the
593ec795f1SBarry Smith     base from the SNES context
603ec795f1SBarry Smith 
613ec795f1SBarry Smith */
62*cc2e6a90SBarry Smith static PetscErrorCode MatAssemblyEnd_SNESMF(Mat J,MatAssemblyType mt)
633ec795f1SBarry Smith {
643ec795f1SBarry Smith   PetscErrorCode ierr;
653ec795f1SBarry Smith   MatMFFD        j    = (MatMFFD)J->data;
665eb111a0SBarry Smith   SNES           snes = (SNES)j->ctx;
6709ffd372SDmitry Karpeev   Vec            u,f;
683ec795f1SBarry Smith 
693ec795f1SBarry Smith   PetscFunctionBegin;
703ec795f1SBarry Smith   ierr = MatAssemblyEnd_MFFD(J,mt);CHKERRQ(ierr);
713ec795f1SBarry Smith 
72be4711e3SBarry Smith   ierr = SNESGetSolution(snes,&u);CHKERRQ(ierr);
735eb111a0SBarry Smith   if (j->func == (PetscErrorCode (*)(void*,Vec,Vec))SNESComputeFunction) {
740298fd71SBarry Smith     ierr = SNESGetFunction(snes,&f,NULL,NULL);CHKERRQ(ierr);
7509ffd372SDmitry Karpeev     ierr = MatMFFDSetBase_MFFD(J,u,f);CHKERRQ(ierr);
765eb111a0SBarry Smith   } else {
775eb111a0SBarry Smith     /* f value known by SNES is not correct for other differencing function */
785eb111a0SBarry Smith     ierr = MatMFFDSetBase_MFFD(J,u,NULL);CHKERRQ(ierr);
795eb111a0SBarry Smith   }
803ec795f1SBarry Smith   PetscFunctionReturn(0);
813ec795f1SBarry Smith }
823ec795f1SBarry Smith 
83174415d9SBarry Smith /*
84174415d9SBarry Smith     This routine resets the MatAssemblyEnd() for the MatMFFD created from MatCreateSNESMF() so that it NO longer
85174415d9SBarry Smith   uses the solution in the SNES object to update the base. See the warning in MatCreateSNESMF().
86174415d9SBarry Smith */
87174415d9SBarry Smith #undef __FUNCT__
88174415d9SBarry Smith #define __FUNCT__ "MatMFFDSetBase_SNESMF"
89*cc2e6a90SBarry Smith static PetscErrorCode  MatMFFDSetBase_SNESMF(Mat J,Vec U,Vec F)
90174415d9SBarry Smith {
91174415d9SBarry Smith   PetscErrorCode ierr;
92174415d9SBarry Smith 
93174415d9SBarry Smith   PetscFunctionBegin;
94885877adSHong Zhang   ierr = MatMFFDSetBase_MFFD(J,U,F);CHKERRQ(ierr);
951aa26658SKarl Rupp 
96174415d9SBarry Smith   J->ops->assemblyend = MatAssemblyEnd_MFFD;
97174415d9SBarry Smith   PetscFunctionReturn(0);
98174415d9SBarry Smith }
99174415d9SBarry Smith 
100c5c390f1SBarry Smith #undef __FUNCT__
1014a2ae208SSatish Balay #define __FUNCT__ "MatCreateSNESMF"
10252baeb72SSatish Balay /*@
10365f2ba5bSLois Curfman McInnes    MatCreateSNESMF - Creates a matrix-free matrix context for use with
10465f2ba5bSLois Curfman McInnes    a SNES solver.  This matrix can be used as the Jacobian argument for
105174415d9SBarry Smith    the routine SNESSetJacobian(). See MatCreateMFFD() for details on how
106174415d9SBarry Smith    the finite difference computation is done.
107a4d4d686SBarry Smith 
108a4d4d686SBarry Smith    Collective on SNES and Vec
109a4d4d686SBarry Smith 
110a4d4d686SBarry Smith    Input Parameters:
111fef1beadSBarry Smith .  snes - the SNES context
112a4d4d686SBarry Smith 
113a4d4d686SBarry Smith    Output Parameter:
114a4d4d686SBarry Smith .  J - the matrix-free matrix
115a4d4d686SBarry Smith 
11615091d37SBarry Smith    Level: advanced
11715091d37SBarry Smith 
1185eb111a0SBarry Smith 
1195eb111a0SBarry Smith    Notes:
1205eb111a0SBarry Smith      You can call SNESSetJacobian() with MatMFFDComputeJacobian() if you are using matrix and not a different
1215eb111a0SBarry Smith      preconditioner matrix
1225eb111a0SBarry Smith 
1235eb111a0SBarry Smith      If you wish to provide a different function to do differencing on to compute the matrix-free operator than
1245eb111a0SBarry Smith      that provided to SNESSetFunction() then call MatMFFDSetFunction() with your function after this call.
1255eb111a0SBarry Smith 
1265eb111a0SBarry Smith      The difference between this routine and MatCreateMFFD() is that this matrix
1275eb111a0SBarry Smith      automatically gets the current base vector from the SNES object and not from an
1285eb111a0SBarry Smith      explicit call to MatMFFDSetBase().
1295eb111a0SBarry Smith 
130174415d9SBarry Smith    Warning:
131174415d9SBarry Smith      If MatMFFDSetBase() is ever called on jac then this routine will NO longer get
132174415d9SBarry Smith      the x from the SNES object and MatMFFDSetBase() must from that point on be used to
133174415d9SBarry Smith      change the base vector x.
1349a6cb015SBarry Smith 
1355eb111a0SBarry Smith    Warning:
1365eb111a0SBarry Smith      Using a different function for the differencing will not work if you are using non-linear left preconditioning.
137ca93e954SBarry Smith 
138ca93e954SBarry Smith 
139722329fbSBarry Smith .seealso: MatDestroy(), MatMFFDSetFunction(), MatMFFDSetFunctionError(), MatMFFDDSSetUmin()
140174415d9SBarry Smith           MatMFFDSetHHistory(), MatMFFDResetHHistory(), MatCreateMFFD(),
14181242352SJed Brown           MatMFFDGetH(), MatMFFDRegister(), MatMFFDComputeJacobian()
142a4d4d686SBarry Smith 
143a4d4d686SBarry Smith @*/
1447087cfbeSBarry Smith PetscErrorCode  MatCreateSNESMF(SNES snes,Mat *J)
145a4d4d686SBarry Smith {
146dfbe8321SBarry Smith   PetscErrorCode ierr;
147fef1beadSBarry Smith   PetscInt       n,N;
1485eb111a0SBarry Smith   MatMFFD        mf;
1491d1367b7SBarry Smith 
1501d1367b7SBarry Smith   PetscFunctionBegin;
151a8248277SBarry Smith   if (snes->vec_func) {
152fef1beadSBarry Smith     ierr = VecGetLocalSize(snes->vec_func,&n);CHKERRQ(ierr);
153fef1beadSBarry Smith     ierr = VecGetSize(snes->vec_func,&N);CHKERRQ(ierr);
154a8248277SBarry Smith   } else if (snes->dm) {
155a8248277SBarry Smith     Vec tmp;
156a8248277SBarry Smith     ierr = DMGetGlobalVector(snes->dm,&tmp);CHKERRQ(ierr);
157a8248277SBarry Smith     ierr = VecGetLocalSize(tmp,&n);CHKERRQ(ierr);
158a8248277SBarry Smith     ierr = VecGetSize(tmp,&N);CHKERRQ(ierr);
159a8248277SBarry Smith     ierr = DMRestoreGlobalVector(snes->dm,&tmp);CHKERRQ(ierr);
160ce94432eSBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"Must call SNESSetFunction() or SNESSetDM() first");
161ce94432eSBarry Smith   ierr = MatCreateMFFD(PetscObjectComm((PetscObject)snes),n,n,N,N,J);CHKERRQ(ierr);
1625eb111a0SBarry Smith   mf      = (MatMFFD)(*J)->data;
1635eb111a0SBarry Smith   mf->ctx = snes;
1645eb111a0SBarry Smith 
165ed07d7d7SPeter Brune   if (snes->pc && snes->pcside == PC_LEFT) {
166be95d8f1SBarry Smith     ierr = MatMFFDSetFunction(*J,(PetscErrorCode (*)(void*,Vec,Vec))SNESComputeFunctionDefaultNPC,snes);CHKERRQ(ierr);
167ed07d7d7SPeter Brune   } else {
168ece7ea46SSatish Balay     ierr = MatMFFDSetFunction(*J,(PetscErrorCode (*)(void*,Vec,Vec))SNESComputeFunction,snes);CHKERRQ(ierr);
169ed07d7d7SPeter Brune   }
1701aa26658SKarl Rupp 
1713ec795f1SBarry Smith   (*J)->ops->assemblyend = MatAssemblyEnd_SNESMF;
1721aa26658SKarl Rupp 
173bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)*J,"MatMFFDSetBase_C",MatMFFDSetBase_SNESMF);CHKERRQ(ierr);
1741d1367b7SBarry Smith   PetscFunctionReturn(0);
1751d1367b7SBarry Smith }
1761d1367b7SBarry Smith 
177cf57b110SBarry Smith 
178cf57b110SBarry Smith 
179cf57b110SBarry Smith 
180cf57b110SBarry Smith 
181cf57b110SBarry Smith 
182