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