xref: /petsc/src/snes/mf/snesmfj.c (revision bc13fc8d7dcc2fcf5ede0633f15129b4f2c23e6e)
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 
75fe378a3SBarry Smith /*@C
8e884886fSBarry Smith    MatMFFDComputeJacobian - Tells the matrix-free Jacobian object the new location at which
9174415d9SBarry Smith        Jacobian matrix vector products will be computed at, i.e. J(x) * a. The x is obtained
10174415d9SBarry Smith        from the SNES object (using SNESGetSolution()).
11e884886fSBarry Smith 
123f9fe445SBarry Smith    Logically Collective on SNES
13e884886fSBarry Smith 
14e884886fSBarry Smith    Input Parameters:
15e884886fSBarry Smith +   snes - the nonlinear solver context
16e884886fSBarry Smith .   x - the point at which the Jacobian vector products will be performed
17e884886fSBarry Smith .   jac - the matrix-free Jacobian object
18e884886fSBarry Smith .   B - either the same as jac or another matrix type (ignored)
19e884886fSBarry Smith .   flag - not relevent for matrix-free form
20e884886fSBarry Smith -   dummy - the user context (ignored)
21e884886fSBarry Smith 
22e884886fSBarry Smith    Level: developer
23e884886fSBarry Smith 
24174415d9SBarry Smith    Warning:
25174415d9SBarry Smith       If MatMFFDSetBase() is ever called on jac then this routine will NO longer get
26174415d9SBarry Smith     the x from the SNES object and MatMFFDSetBase() must from that point on be used to
27174415d9SBarry Smith     change the base vector x.
28174415d9SBarry Smith 
29e884886fSBarry Smith    Notes:
30ecaffddaSVictor Eijkhout      This can be passed into SNESSetJacobian() as the Jacobian evaluation function argument
31ecaffddaSVictor Eijkhout      when using a completely matrix-free solver,
32e884886fSBarry Smith      that is the B matrix is also the same matrix operator. This is used when you select
335fe378a3SBarry Smith      -snes_mf but rarely used directly by users. (All this routine does is call MatAssemblyBegin/End() on
3414f633e2SBarry Smith      the Mat jac.)
355fe378a3SBarry Smith 
360decc0a3SBarry Smith .seealso: MatMFFDGetH(), MatCreateSNESMF(), MatCreateMFFD(), MATMFFD,
371d0fab5eSBarry Smith           MatMFFDSetHHistory(), MatMFFDSetFunctionError(), MatCreateMFFD(), SNESSetJacobian()
38e884886fSBarry Smith 
39e884886fSBarry Smith @*/
40d1e9a80fSBarry Smith PetscErrorCode  MatMFFDComputeJacobian(SNES snes,Vec x,Mat jac,Mat B,void *dummy)
41e884886fSBarry Smith {
42e884886fSBarry Smith   PetscErrorCode ierr;
435fd66863SKarl Rupp 
44e884886fSBarry Smith   PetscFunctionBegin;
4594ab13aaSBarry Smith   ierr = MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4694ab13aaSBarry Smith   ierr = MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
47e884886fSBarry Smith   PetscFunctionReturn(0);
48e884886fSBarry Smith }
49e884886fSBarry Smith 
50d8fa6a54SBarry Smith PETSC_EXTERN PetscErrorCode MatAssemblyEnd_MFFD(Mat,MatAssemblyType);
51d8fa6a54SBarry Smith PETSC_EXTERN PetscErrorCode MatMFFDSetBase_MFFD(Mat,Vec,Vec);
52563d23a3SJed Brown 
53*bc13fc8dSBarry Smith /*@
54*bc13fc8dSBarry Smith     MatSNESMFGetSNES - returns the SNES associated with a matrix created with MatCreateSNESMF()
55*bc13fc8dSBarry Smith 
56*bc13fc8dSBarry Smith     Not collective
57*bc13fc8dSBarry Smith 
58*bc13fc8dSBarry Smith     Input Parameter:
59*bc13fc8dSBarry Smith .   J - the matrix
60*bc13fc8dSBarry Smith 
61*bc13fc8dSBarry Smith     Output Parameter:
62*bc13fc8dSBarry Smith .   snes - the SNES object
63*bc13fc8dSBarry Smith 
64*bc13fc8dSBarry Smith .seealso: MatCreateSNESMF()
65*bc13fc8dSBarry Smith @*/
66*bc13fc8dSBarry Smith PetscErrorCode MatSNESMFGetSNES(Mat J,SNES *snes)
67*bc13fc8dSBarry Smith {
68*bc13fc8dSBarry Smith   MatMFFD        j    = (MatMFFD)J->data;
69*bc13fc8dSBarry Smith 
70*bc13fc8dSBarry Smith   PetscFunctionBegin;
71*bc13fc8dSBarry Smith   *snes = (SNES)j->ctx;
72*bc13fc8dSBarry Smith   PetscFunctionReturn(0);
73*bc13fc8dSBarry Smith }
74*bc13fc8dSBarry Smith 
753ec795f1SBarry Smith /*
763ec795f1SBarry Smith    MatAssemblyEnd_SNESMF - Calls MatAssemblyEnd_MFFD() and then sets the
773ec795f1SBarry Smith     base from the SNES context
783ec795f1SBarry Smith 
793ec795f1SBarry Smith */
80cc2e6a90SBarry Smith static PetscErrorCode MatAssemblyEnd_SNESMF(Mat J,MatAssemblyType mt)
813ec795f1SBarry Smith {
823ec795f1SBarry Smith   PetscErrorCode ierr;
833ec795f1SBarry Smith   MatMFFD        j    = (MatMFFD)J->data;
845eb111a0SBarry Smith   SNES           snes = (SNES)j->ctx;
8509ffd372SDmitry Karpeev   Vec            u,f;
863ec795f1SBarry Smith 
873ec795f1SBarry Smith   PetscFunctionBegin;
883ec795f1SBarry Smith   ierr = MatAssemblyEnd_MFFD(J,mt);CHKERRQ(ierr);
893ec795f1SBarry Smith 
90be4711e3SBarry Smith   ierr = SNESGetSolution(snes,&u);CHKERRQ(ierr);
915eb111a0SBarry Smith   if (j->func == (PetscErrorCode (*)(void*,Vec,Vec))SNESComputeFunction) {
920298fd71SBarry Smith     ierr = SNESGetFunction(snes,&f,NULL,NULL);CHKERRQ(ierr);
9309ffd372SDmitry Karpeev     ierr = MatMFFDSetBase_MFFD(J,u,f);CHKERRQ(ierr);
945eb111a0SBarry Smith   } else {
955eb111a0SBarry Smith     /* f value known by SNES is not correct for other differencing function */
965eb111a0SBarry Smith     ierr = MatMFFDSetBase_MFFD(J,u,NULL);CHKERRQ(ierr);
975eb111a0SBarry Smith   }
983ec795f1SBarry Smith   PetscFunctionReturn(0);
993ec795f1SBarry Smith }
1003ec795f1SBarry Smith 
101174415d9SBarry Smith /*
102174415d9SBarry Smith     This routine resets the MatAssemblyEnd() for the MatMFFD created from MatCreateSNESMF() so that it NO longer
103174415d9SBarry Smith   uses the solution in the SNES object to update the base. See the warning in MatCreateSNESMF().
104174415d9SBarry Smith */
105cc2e6a90SBarry Smith static PetscErrorCode  MatMFFDSetBase_SNESMF(Mat J,Vec U,Vec F)
106174415d9SBarry Smith {
107174415d9SBarry Smith   PetscErrorCode ierr;
108174415d9SBarry Smith 
109174415d9SBarry Smith   PetscFunctionBegin;
110885877adSHong Zhang   ierr = MatMFFDSetBase_MFFD(J,U,F);CHKERRQ(ierr);
1111aa26658SKarl Rupp 
112174415d9SBarry Smith   J->ops->assemblyend = MatAssemblyEnd_MFFD;
113174415d9SBarry Smith   PetscFunctionReturn(0);
114174415d9SBarry Smith }
115174415d9SBarry Smith 
11652baeb72SSatish Balay /*@
11765f2ba5bSLois Curfman McInnes    MatCreateSNESMF - Creates a matrix-free matrix context for use with
11865f2ba5bSLois Curfman McInnes    a SNES solver.  This matrix can be used as the Jacobian argument for
119174415d9SBarry Smith    the routine SNESSetJacobian(). See MatCreateMFFD() for details on how
120174415d9SBarry Smith    the finite difference computation is done.
121a4d4d686SBarry Smith 
122a4d4d686SBarry Smith    Collective on SNES and Vec
123a4d4d686SBarry Smith 
124a4d4d686SBarry Smith    Input Parameters:
125fef1beadSBarry Smith .  snes - the SNES context
126a4d4d686SBarry Smith 
127a4d4d686SBarry Smith    Output Parameter:
128a4d4d686SBarry Smith .  J - the matrix-free matrix
129a4d4d686SBarry Smith 
13015091d37SBarry Smith    Level: advanced
13115091d37SBarry Smith 
1325eb111a0SBarry Smith 
1335eb111a0SBarry Smith    Notes:
1345eb111a0SBarry Smith      You can call SNESSetJacobian() with MatMFFDComputeJacobian() if you are using matrix and not a different
1355eb111a0SBarry Smith      preconditioner matrix
1365eb111a0SBarry Smith 
1375eb111a0SBarry Smith      If you wish to provide a different function to do differencing on to compute the matrix-free operator than
1385eb111a0SBarry Smith      that provided to SNESSetFunction() then call MatMFFDSetFunction() with your function after this call.
1395eb111a0SBarry Smith 
1405eb111a0SBarry Smith      The difference between this routine and MatCreateMFFD() is that this matrix
1415eb111a0SBarry Smith      automatically gets the current base vector from the SNES object and not from an
1425eb111a0SBarry Smith      explicit call to MatMFFDSetBase().
1435eb111a0SBarry Smith 
144174415d9SBarry Smith    Warning:
145174415d9SBarry Smith      If MatMFFDSetBase() is ever called on jac then this routine will NO longer get
146174415d9SBarry Smith      the x from the SNES object and MatMFFDSetBase() must from that point on be used to
147174415d9SBarry Smith      change the base vector x.
1489a6cb015SBarry Smith 
1495eb111a0SBarry Smith    Warning:
1505eb111a0SBarry Smith      Using a different function for the differencing will not work if you are using non-linear left preconditioning.
151ca93e954SBarry Smith 
152ca93e954SBarry Smith 
153722329fbSBarry Smith .seealso: MatDestroy(), MatMFFDSetFunction(), MatMFFDSetFunctionError(), MatMFFDDSSetUmin()
154174415d9SBarry Smith           MatMFFDSetHHistory(), MatMFFDResetHHistory(), MatCreateMFFD(),
15581242352SJed Brown           MatMFFDGetH(), MatMFFDRegister(), MatMFFDComputeJacobian()
156a4d4d686SBarry Smith 
157a4d4d686SBarry Smith @*/
1587087cfbeSBarry Smith PetscErrorCode  MatCreateSNESMF(SNES snes,Mat *J)
159a4d4d686SBarry Smith {
160dfbe8321SBarry Smith   PetscErrorCode ierr;
161fef1beadSBarry Smith   PetscInt       n,N;
1625eb111a0SBarry Smith   MatMFFD        mf;
1631d1367b7SBarry Smith 
1641d1367b7SBarry Smith   PetscFunctionBegin;
165a8248277SBarry Smith   if (snes->vec_func) {
166fef1beadSBarry Smith     ierr = VecGetLocalSize(snes->vec_func,&n);CHKERRQ(ierr);
167fef1beadSBarry Smith     ierr = VecGetSize(snes->vec_func,&N);CHKERRQ(ierr);
168a8248277SBarry Smith   } else if (snes->dm) {
169a8248277SBarry Smith     Vec tmp;
170a8248277SBarry Smith     ierr = DMGetGlobalVector(snes->dm,&tmp);CHKERRQ(ierr);
171a8248277SBarry Smith     ierr = VecGetLocalSize(tmp,&n);CHKERRQ(ierr);
172a8248277SBarry Smith     ierr = VecGetSize(tmp,&N);CHKERRQ(ierr);
173a8248277SBarry Smith     ierr = DMRestoreGlobalVector(snes->dm,&tmp);CHKERRQ(ierr);
174ce94432eSBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"Must call SNESSetFunction() or SNESSetDM() first");
175ce94432eSBarry Smith   ierr = MatCreateMFFD(PetscObjectComm((PetscObject)snes),n,n,N,N,J);CHKERRQ(ierr);
17688b4c220SStefano Zampini 
1775eb111a0SBarry Smith   mf      = (MatMFFD)(*J)->data;
1785eb111a0SBarry Smith   mf->ctx = snes;
1795eb111a0SBarry Smith 
180efd4aadfSBarry Smith   if (snes->npc && snes->npcside== PC_LEFT) {
181be95d8f1SBarry Smith     ierr = MatMFFDSetFunction(*J,(PetscErrorCode (*)(void*,Vec,Vec))SNESComputeFunctionDefaultNPC,snes);CHKERRQ(ierr);
182ed07d7d7SPeter Brune   } else {
183ece7ea46SSatish Balay     ierr = MatMFFDSetFunction(*J,(PetscErrorCode (*)(void*,Vec,Vec))SNESComputeFunction,snes);CHKERRQ(ierr);
184ed07d7d7SPeter Brune   }
1851aa26658SKarl Rupp 
1863ec795f1SBarry Smith   (*J)->ops->assemblyend = MatAssemblyEnd_SNESMF;
1871aa26658SKarl Rupp 
188bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)*J,"MatMFFDSetBase_C",MatMFFDSetBase_SNESMF);CHKERRQ(ierr);
1891d1367b7SBarry Smith   PetscFunctionReturn(0);
1901d1367b7SBarry Smith }
191