181e6777dSBarry Smith 2b45d2f2cSJed Brown #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> 5b45d2f2cSJed Brown #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 @*/ 427087cfbeSBarry Smith PetscErrorCode MatMFFDComputeJacobian(SNES snes,Vec x,Mat *jac,Mat *B,MatStructure *flag,void *dummy) 43e884886fSBarry Smith { 44e884886fSBarry Smith PetscErrorCode ierr; 455fd66863SKarl Rupp 46e884886fSBarry Smith PetscFunctionBegin; 47e884886fSBarry Smith ierr = MatAssemblyBegin(*jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 48e884886fSBarry 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 */ 623ec795f1SBarry Smith PetscErrorCode MatAssemblyEnd_SNESMF(Mat J,MatAssemblyType mt) 633ec795f1SBarry Smith { 643ec795f1SBarry Smith PetscErrorCode ierr; 653ec795f1SBarry Smith MatMFFD j = (MatMFFD)J->data; 66*5eb111a0SBarry 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); 73*5eb111a0SBarry 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); 76*5eb111a0SBarry Smith } else { 77*5eb111a0SBarry Smith /* f value known by SNES is not correct for other differencing function */ 78*5eb111a0SBarry Smith ierr = MatMFFDSetBase_MFFD(J,u,NULL);CHKERRQ(ierr); 79*5eb111a0SBarry 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" 897087cfbeSBarry Smith 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 118*5eb111a0SBarry Smith 119*5eb111a0SBarry Smith Notes: 120*5eb111a0SBarry Smith You can call SNESSetJacobian() with MatMFFDComputeJacobian() if you are using matrix and not a different 121*5eb111a0SBarry Smith preconditioner matrix 122*5eb111a0SBarry Smith 123*5eb111a0SBarry Smith If you wish to provide a different function to do differencing on to compute the matrix-free operator than 124*5eb111a0SBarry Smith that provided to SNESSetFunction() then call MatMFFDSetFunction() with your function after this call. 125*5eb111a0SBarry Smith 126*5eb111a0SBarry Smith The difference between this routine and MatCreateMFFD() is that this matrix 127*5eb111a0SBarry Smith automatically gets the current base vector from the SNES object and not from an 128*5eb111a0SBarry Smith explicit call to MatMFFDSetBase(). 129*5eb111a0SBarry 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 135*5eb111a0SBarry Smith Warning: 136*5eb111a0SBarry Smith Using a different function for the differencing will not work if you are using non-linear left preconditioning. 137ca93e954SBarry Smith 138ca93e954SBarry Smith 1391d0fab5eSBarry Smith .seealso: MatDestroy(), 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; 148*5eb111a0SBarry 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); 162*5eb111a0SBarry Smith mf = (MatMFFD)(*J)->data; 163*5eb111a0SBarry Smith mf->ctx = snes; 164*5eb111a0SBarry Smith 165ed07d7d7SPeter Brune if (snes->pc && snes->pcside == PC_LEFT) { 166ed07d7d7SPeter Brune ierr = MatMFFDSetFunction(*J,(PetscErrorCode (*)(void*,Vec,Vec))SNESComputeFunctionDefaultPC,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