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 533ec795f1SBarry Smith /* 543ec795f1SBarry Smith MatAssemblyEnd_SNESMF - Calls MatAssemblyEnd_MFFD() and then sets the 553ec795f1SBarry Smith base from the SNES context 563ec795f1SBarry Smith 573ec795f1SBarry Smith */ 58cc2e6a90SBarry Smith static PetscErrorCode MatAssemblyEnd_SNESMF(Mat J,MatAssemblyType mt) 593ec795f1SBarry Smith { 603ec795f1SBarry Smith PetscErrorCode ierr; 613ec795f1SBarry Smith MatMFFD j = (MatMFFD)J->data; 625eb111a0SBarry Smith SNES snes = (SNES)j->ctx; 6309ffd372SDmitry Karpeev Vec u,f; 643ec795f1SBarry Smith 653ec795f1SBarry Smith PetscFunctionBegin; 663ec795f1SBarry Smith ierr = MatAssemblyEnd_MFFD(J,mt);CHKERRQ(ierr); 673ec795f1SBarry Smith 68be4711e3SBarry Smith ierr = SNESGetSolution(snes,&u);CHKERRQ(ierr); 695eb111a0SBarry Smith if (j->func == (PetscErrorCode (*)(void*,Vec,Vec))SNESComputeFunction) { 700298fd71SBarry Smith ierr = SNESGetFunction(snes,&f,NULL,NULL);CHKERRQ(ierr); 7109ffd372SDmitry Karpeev ierr = MatMFFDSetBase_MFFD(J,u,f);CHKERRQ(ierr); 725eb111a0SBarry Smith } else { 735eb111a0SBarry Smith /* f value known by SNES is not correct for other differencing function */ 745eb111a0SBarry Smith ierr = MatMFFDSetBase_MFFD(J,u,NULL);CHKERRQ(ierr); 755eb111a0SBarry Smith } 763ec795f1SBarry Smith PetscFunctionReturn(0); 773ec795f1SBarry Smith } 783ec795f1SBarry Smith 79174415d9SBarry Smith /* 80*208be567SBarry Smith MatAssemblyEnd_SNESMF_UseBase - Calls MatAssemblyEnd_MFFD() and then sets the 81*208be567SBarry Smith base from the SNES context. This version will cause the base to be used for differencing 82*208be567SBarry Smith even if the func is not SNESComputeFunction. See: MatSNESMFUseBase() 83*208be567SBarry Smith 84*208be567SBarry Smith 85*208be567SBarry Smith */ 86*208be567SBarry Smith static PetscErrorCode MatAssemblyEnd_SNESMF_UseBase(Mat J,MatAssemblyType mt) 87*208be567SBarry Smith { 88*208be567SBarry Smith PetscErrorCode ierr; 89*208be567SBarry Smith MatMFFD j = (MatMFFD)J->data; 90*208be567SBarry Smith SNES snes = (SNES)j->ctx; 91*208be567SBarry Smith Vec u,f; 92*208be567SBarry Smith 93*208be567SBarry Smith PetscFunctionBegin; 94*208be567SBarry Smith ierr = MatAssemblyEnd_MFFD(J,mt);CHKERRQ(ierr); 95*208be567SBarry Smith 96*208be567SBarry Smith ierr = SNESGetSolution(snes,&u);CHKERRQ(ierr); 97*208be567SBarry Smith ierr = SNESGetFunction(snes,&f,NULL,NULL);CHKERRQ(ierr); 98*208be567SBarry Smith ierr = MatMFFDSetBase_MFFD(J,u,f);CHKERRQ(ierr); 99*208be567SBarry Smith PetscFunctionReturn(0); 100*208be567SBarry Smith } 101*208be567SBarry Smith 102*208be567SBarry Smith /* 103174415d9SBarry Smith This routine resets the MatAssemblyEnd() for the MatMFFD created from MatCreateSNESMF() so that it NO longer 104174415d9SBarry Smith uses the solution in the SNES object to update the base. See the warning in MatCreateSNESMF(). 105174415d9SBarry Smith */ 106cc2e6a90SBarry Smith static PetscErrorCode MatMFFDSetBase_SNESMF(Mat J,Vec U,Vec F) 107174415d9SBarry Smith { 108174415d9SBarry Smith PetscErrorCode ierr; 109174415d9SBarry Smith 110174415d9SBarry Smith PetscFunctionBegin; 111885877adSHong Zhang ierr = MatMFFDSetBase_MFFD(J,U,F);CHKERRQ(ierr); 112174415d9SBarry Smith J->ops->assemblyend = MatAssemblyEnd_MFFD; 113174415d9SBarry Smith PetscFunctionReturn(0); 114174415d9SBarry Smith } 115174415d9SBarry Smith 116*208be567SBarry Smith static PetscErrorCode MatSNESMFSetReuseBase_SNESMF(Mat J,PetscBool use) 117*208be567SBarry Smith { 118*208be567SBarry Smith PetscFunctionBegin; 119*208be567SBarry Smith if (use) { 120*208be567SBarry Smith J->ops->assemblyend = MatAssemblyEnd_SNESMF_UseBase; 121*208be567SBarry Smith } else { 122*208be567SBarry Smith J->ops->assemblyend = MatAssemblyEnd_SNESMF; 123*208be567SBarry Smith } 124*208be567SBarry Smith PetscFunctionReturn(0); 125*208be567SBarry Smith } 126*208be567SBarry Smith 127*208be567SBarry Smith /*@ 128*208be567SBarry Smith MatSNESMFSetReuseBase - Causes the base vector to be used for differencing even if the function provided to SNESSetFunction() is not the 129*208be567SBarry Smith same as that provided to MatMFFDSetFunction(). 130*208be567SBarry Smith 131*208be567SBarry Smith Logically Collective on Mat 132*208be567SBarry Smith 133*208be567SBarry Smith Input Parameters: 134*208be567SBarry Smith + J - the MatMFFD matrix 135*208be567SBarry Smith - use - if true always reuse the base vector instead of recomputing f(u) even if the function in the MatSNESMF is 136*208be567SBarry Smith not SNESComputeFunction() 137*208be567SBarry Smith 138*208be567SBarry Smith Notes: Care must be taken when using this routine to insure that the function provided to MatMFFDSetFunction(), call it F_MF() is compatible with 139*208be567SBarry Smith with that provided to SNESSetFunction(), call it F_SNES(). That is, (F_MF(u + h*d) - F_SNES(u))/h has to approximate the derivative 140*208be567SBarry Smith 141*208be567SBarry Smith Developer Notes: This was provided for the MOOSE team who desired to have a SNESSetFunction() function that could change configurations due 142*208be567SBarry Smith to contacts while the function provided to MatMFFDSetFunction() cannot. Except for the possibility of changing the configuration 143*208be567SBarry Smith both functions compute the same mathematical function so the differencing makes sense. 144*208be567SBarry Smith 145*208be567SBarry Smith Level: advanced 146*208be567SBarry Smith 147*208be567SBarry Smith .seealso: MatCreateSNESMF(), MatSNESMFGetReuseBase() 148*208be567SBarry Smith @*/ 149*208be567SBarry Smith PetscErrorCode MatSNESMFSetReuseBase(Mat J,PetscBool use) 150*208be567SBarry Smith { 151*208be567SBarry Smith PetscErrorCode ierr; 152*208be567SBarry Smith 153*208be567SBarry Smith PetscFunctionBegin; 154*208be567SBarry Smith PetscValidHeaderSpecific(J,MAT_CLASSID,1); 155*208be567SBarry Smith ierr = PetscTryMethod(J,"MatSNESMFSetReuseBase_C",(Mat,PetscBool),(J,use));CHKERRQ(ierr); 156*208be567SBarry Smith PetscFunctionReturn(0); 157*208be567SBarry Smith } 158*208be567SBarry Smith 159*208be567SBarry Smith static PetscErrorCode MatSNESMFGetReuseBase_SNESMF(Mat J,PetscBool *use) 160*208be567SBarry Smith { 161*208be567SBarry Smith PetscFunctionBegin; 162*208be567SBarry Smith if (J->ops->assemblyend == MatAssemblyEnd_SNESMF_UseBase) *use = PETSC_TRUE; 163*208be567SBarry Smith else *use = PETSC_FALSE; 164*208be567SBarry Smith PetscFunctionReturn(0); 165*208be567SBarry Smith } 166*208be567SBarry Smith 167*208be567SBarry Smith /*@ 168*208be567SBarry Smith MatSNESMFGetReuseBase - Determines if the base vector is to be used for differencing even if the function provided to SNESSetFunction() is not the 169*208be567SBarry Smith same as that provided to MatMFFDSetFunction(). 170*208be567SBarry Smith 171*208be567SBarry Smith Logically Collective on Mat 172*208be567SBarry Smith 173*208be567SBarry Smith Input Parameter: 174*208be567SBarry Smith . J - the MatMFFD matrix 175*208be567SBarry Smith 176*208be567SBarry Smith Output Parameter: 177*208be567SBarry Smith . use - if true always reuse the base vector instead of recomputing f(u) even if the function in the MatSNESMF is 178*208be567SBarry Smith not SNESComputeFunction() 179*208be567SBarry Smith 180*208be567SBarry Smith Notes: Care must be taken when using this routine to insure that the function provided to MatMFFDSetFunction(), call it F_MF() is compatible with 181*208be567SBarry Smith with that provided to SNESSetFunction(), call it F_SNES(). That is, (F_MF(u + h*d) - F_SNES(u))/h has to approximate the derivative 182*208be567SBarry Smith 183*208be567SBarry Smith Developer Notes: This was provided for the MOOSE team who desired to have a SNESSetFunction() function that could change configurations due 184*208be567SBarry Smith to contacts while the function provided to MatMFFDSetFunction() cannot. Except for the possibility of changing the configuration 185*208be567SBarry Smith both functions compute the same mathematical function so the differencing makes sense. 186*208be567SBarry Smith 187*208be567SBarry Smith Level: advanced 188*208be567SBarry Smith 189*208be567SBarry Smith .seealso: MatCreateSNESMF(), MatSNESMFSetReuseBase() 190*208be567SBarry Smith @*/ 191*208be567SBarry Smith PetscErrorCode MatSNESMFGetReuseBase(Mat J,PetscBool *use) 192*208be567SBarry Smith { 193*208be567SBarry Smith PetscErrorCode ierr; 194*208be567SBarry Smith 195*208be567SBarry Smith PetscFunctionBegin; 196*208be567SBarry Smith PetscValidHeaderSpecific(J,MAT_CLASSID,1); 197*208be567SBarry Smith ierr = PetscUseMethod(J,"MatSNESMFGetReuseBase_C",(Mat,PetscBool*),(J,use));CHKERRQ(ierr); 198*208be567SBarry Smith PetscFunctionReturn(0); 199*208be567SBarry Smith } 200*208be567SBarry Smith 20152baeb72SSatish Balay /*@ 20265f2ba5bSLois Curfman McInnes MatCreateSNESMF - Creates a matrix-free matrix context for use with 20365f2ba5bSLois Curfman McInnes a SNES solver. This matrix can be used as the Jacobian argument for 204174415d9SBarry Smith the routine SNESSetJacobian(). See MatCreateMFFD() for details on how 205174415d9SBarry Smith the finite difference computation is done. 206a4d4d686SBarry Smith 207a4d4d686SBarry Smith Collective on SNES and Vec 208a4d4d686SBarry Smith 209a4d4d686SBarry Smith Input Parameters: 210fef1beadSBarry Smith . snes - the SNES context 211a4d4d686SBarry Smith 212a4d4d686SBarry Smith Output Parameter: 213a4d4d686SBarry Smith . J - the matrix-free matrix 214a4d4d686SBarry Smith 21515091d37SBarry Smith Level: advanced 21615091d37SBarry Smith 2175eb111a0SBarry Smith 2185eb111a0SBarry Smith Notes: 2195eb111a0SBarry Smith You can call SNESSetJacobian() with MatMFFDComputeJacobian() if you are using matrix and not a different 2205eb111a0SBarry Smith preconditioner matrix 2215eb111a0SBarry Smith 2225eb111a0SBarry Smith If you wish to provide a different function to do differencing on to compute the matrix-free operator than 2235eb111a0SBarry Smith that provided to SNESSetFunction() then call MatMFFDSetFunction() with your function after this call. 2245eb111a0SBarry Smith 2255eb111a0SBarry Smith The difference between this routine and MatCreateMFFD() is that this matrix 2265eb111a0SBarry Smith automatically gets the current base vector from the SNES object and not from an 2275eb111a0SBarry Smith explicit call to MatMFFDSetBase(). 2285eb111a0SBarry Smith 229174415d9SBarry Smith Warning: 230174415d9SBarry Smith If MatMFFDSetBase() is ever called on jac then this routine will NO longer get 231174415d9SBarry Smith the x from the SNES object and MatMFFDSetBase() must from that point on be used to 232174415d9SBarry Smith change the base vector x. 2339a6cb015SBarry Smith 2345eb111a0SBarry Smith Warning: 2355eb111a0SBarry Smith Using a different function for the differencing will not work if you are using non-linear left preconditioning. 236ca93e954SBarry Smith 237ca93e954SBarry Smith 238722329fbSBarry Smith .seealso: MatDestroy(), MatMFFDSetFunction(), MatMFFDSetFunctionError(), MatMFFDDSSetUmin() 239174415d9SBarry Smith MatMFFDSetHHistory(), MatMFFDResetHHistory(), MatCreateMFFD(), 240*208be567SBarry Smith MatMFFDGetH(), MatMFFDRegister(), MatMFFDComputeJacobian(), MatSNESMFSetReuseBase(), MatSNESMFGetReuseBase() 241a4d4d686SBarry Smith 242a4d4d686SBarry Smith @*/ 2437087cfbeSBarry Smith PetscErrorCode MatCreateSNESMF(SNES snes,Mat *J) 244a4d4d686SBarry Smith { 245dfbe8321SBarry Smith PetscErrorCode ierr; 246fef1beadSBarry Smith PetscInt n,N; 2475eb111a0SBarry Smith MatMFFD mf; 2481d1367b7SBarry Smith 2491d1367b7SBarry Smith PetscFunctionBegin; 250a8248277SBarry Smith if (snes->vec_func) { 251fef1beadSBarry Smith ierr = VecGetLocalSize(snes->vec_func,&n);CHKERRQ(ierr); 252fef1beadSBarry Smith ierr = VecGetSize(snes->vec_func,&N);CHKERRQ(ierr); 253a8248277SBarry Smith } else if (snes->dm) { 254a8248277SBarry Smith Vec tmp; 255a8248277SBarry Smith ierr = DMGetGlobalVector(snes->dm,&tmp);CHKERRQ(ierr); 256a8248277SBarry Smith ierr = VecGetLocalSize(tmp,&n);CHKERRQ(ierr); 257a8248277SBarry Smith ierr = VecGetSize(tmp,&N);CHKERRQ(ierr); 258a8248277SBarry Smith ierr = DMRestoreGlobalVector(snes->dm,&tmp);CHKERRQ(ierr); 259ce94432eSBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"Must call SNESSetFunction() or SNESSetDM() first"); 260ce94432eSBarry Smith ierr = MatCreateMFFD(PetscObjectComm((PetscObject)snes),n,n,N,N,J);CHKERRQ(ierr); 26188b4c220SStefano Zampini 2625eb111a0SBarry Smith mf = (MatMFFD)(*J)->data; 2635eb111a0SBarry Smith mf->ctx = snes; 2645eb111a0SBarry Smith 265efd4aadfSBarry Smith if (snes->npc && snes->npcside== PC_LEFT) { 266be95d8f1SBarry Smith ierr = MatMFFDSetFunction(*J,(PetscErrorCode (*)(void*,Vec,Vec))SNESComputeFunctionDefaultNPC,snes);CHKERRQ(ierr); 267ed07d7d7SPeter Brune } else { 268ece7ea46SSatish Balay ierr = MatMFFDSetFunction(*J,(PetscErrorCode (*)(void*,Vec,Vec))SNESComputeFunction,snes);CHKERRQ(ierr); 269ed07d7d7SPeter Brune } 2701aa26658SKarl Rupp 2713ec795f1SBarry Smith (*J)->ops->assemblyend = MatAssemblyEnd_SNESMF; 2721aa26658SKarl Rupp 273bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)*J,"MatMFFDSetBase_C",MatMFFDSetBase_SNESMF);CHKERRQ(ierr); 274*208be567SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)*J,"MatSNESMFSetReuseBase_C",MatSNESMFSetReuseBase_SNESMF);CHKERRQ(ierr); 275*208be567SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)*J,"MatSNESMFGetReuseBase_C",MatSNESMFGetReuseBase_SNESMF);CHKERRQ(ierr); 2761d1367b7SBarry Smith PetscFunctionReturn(0); 2771d1367b7SBarry Smith } 278