xref: /petsc/src/snes/mf/snesmfj.c (revision 5392566e307f4c743d2e3a1f9d4485cd364fbdad)
181e6777dSBarry Smith 
281e6777dSBarry Smith #ifndef lint
3*5392566eSBarry Smith static char vcid[] = "$Id: snesmfj.c,v 1.9 1995/06/08 03:11:42 bsmith Exp bsmith $";
481e6777dSBarry Smith #endif
581e6777dSBarry Smith 
681e6777dSBarry Smith #include "draw.h"
7f3b845d0SBarry Smith #include "snes.h"
881e6777dSBarry Smith 
939e2f89bSBarry Smith typedef struct {
1039e2f89bSBarry Smith   SNES snes;
1139e2f89bSBarry Smith   Vec  w;
1239e2f89bSBarry Smith } MFCtx_Private;
1339e2f89bSBarry Smith 
1439e2f89bSBarry Smith /*
1539e2f89bSBarry Smith     SNESMatrixFreeMult_Private - Default matrix free form of A*u.
1639e2f89bSBarry Smith 
1739e2f89bSBarry Smith */
1839e2f89bSBarry Smith int SNESMatrixFreeMult_Private(void *ptr,Vec dx,Vec y)
1939e2f89bSBarry Smith {
2039e2f89bSBarry Smith   MFCtx_Private *ctx = (MFCtx_Private* ) ptr;
2139e2f89bSBarry Smith   SNES          snes = ctx->snes;
2239e2f89bSBarry Smith   double        norm,epsilon = 1.e-8; /* assumes double precision */
2339e2f89bSBarry Smith   Scalar        h,dot,sum;
2439e2f89bSBarry Smith   Scalar        mone = -1.0;
2539e2f89bSBarry Smith   Vec           w = ctx->w,U,F;
2639e2f89bSBarry Smith   int           ierr;
2739e2f89bSBarry Smith 
2878b31e54SBarry Smith   ierr = SNESGetSolution(snes,&U); CHKERRQ(ierr);
2978b31e54SBarry Smith   ierr = SNESGetFunction(snes,&F); CHKERRQ(ierr);
3039e2f89bSBarry Smith   /* determine a "good" step size */
3139e2f89bSBarry Smith   VecDot(U,dx,&dot); VecASum(dx,&sum); VecNorm(dx,&norm);
32edd2f0e1SBarry Smith   if (sum == 0.0) {dot = 1.0; norm = 1.0;}
33edd2f0e1SBarry Smith   else if (dot < 1.e-16*sum && dot >= 0.0) dot = 1.e-16*sum;
3439e2f89bSBarry Smith   else if (dot < 0.0 && dot > 1.e-16*sum) dot = -1.e-16*sum;
3539e2f89bSBarry Smith   h = epsilon*dot/(norm*norm);
3639e2f89bSBarry Smith 
3739e2f89bSBarry Smith   /* evaluate function at F(x + dx) */
3839e2f89bSBarry Smith   VecWAXPY(&h,dx,U,w);
3978b31e54SBarry Smith   ierr = SNESComputeFunction(snes,w,y); CHKERRQ(ierr);
4039e2f89bSBarry Smith   VecAXPY(&mone,F,y);
4139e2f89bSBarry Smith   h = -1.0/h;
4239e2f89bSBarry Smith   VecScale(&h,y);
4339e2f89bSBarry Smith   return 0;
4439e2f89bSBarry Smith }
4581e6777dSBarry Smith /*@
46*5392566eSBarry Smith      SNESDefaultMatrixFreeMatCreate - Creates a matrix-free matrix
47*5392566eSBarry Smith          for use with SNES solver. You may use this matrix as
48*5392566eSBarry Smith          Jacobian argument for the routine SNESSetJacobian. This is
49*5392566eSBarry Smith          most useful when you are using finite differences for a
50*5392566eSBarry Smith          matrix free Newton method but explictly are forming a
51*5392566eSBarry Smith          preconditioner matrix.
52*5392566eSBarry Smith 
53*5392566eSBarry Smith   Input Parameters:
54*5392566eSBarry Smith .  x - vector where SNES solution is to be stored.
55*5392566eSBarry Smith 
56*5392566eSBarry Smith   Output Parameters:
57*5392566eSBarry Smith .  J - the matrix-free matrix
58*5392566eSBarry Smith 
59*5392566eSBarry Smith @*/
60*5392566eSBarry Smith int SNESDefaultMatrixFreeMatCreate(SNES snes,Vec x, Mat *J)
61*5392566eSBarry Smith {
62*5392566eSBarry Smith   MPI_Comm      comm;
63*5392566eSBarry Smith   MFCtx_Private *mfctx;
64*5392566eSBarry Smith   int           n,ierr;
65*5392566eSBarry Smith 
66*5392566eSBarry Smith   mfctx = (MFCtx_Private *) PETSCMALLOC(sizeof(MFCtx_Private));CHKPTRQ(mfctx);
67*5392566eSBarry Smith   mfctx->snes = snes;
68*5392566eSBarry Smith   ierr = VecDuplicate(x,&mfctx->w); CHKERRQ(ierr);
69*5392566eSBarry Smith   PetscObjectGetComm((PetscObject)x,&comm);
70*5392566eSBarry Smith   VecGetSize(x,&n);
71*5392566eSBarry Smith   ierr = MatShellCreate(comm,n,n,(void*)mfctx,J); CHKERRQ(ierr);
72*5392566eSBarry Smith   MatShellSetMult(*J,SNESMatrixFreeMult_Private);
73*5392566eSBarry Smith   return 0;
74*5392566eSBarry Smith }
75*5392566eSBarry Smith /*@
7639e2f89bSBarry Smith    SNESDefaultMatrixFreeComputeJacobian - Computes Jacobian using finite
7771dce806SLois Curfman McInnes    differences, matrix-free style.
7881e6777dSBarry Smith 
7981e6777dSBarry Smith    Input Parameters:
8081e6777dSBarry Smith .  x - compute Jacobian at this point
81ad960d00SLois Curfman McInnes .  ctx - application's function context, as set with SNESSetFunction()
8281e6777dSBarry Smith 
8381e6777dSBarry Smith    Output Parameters:
8481e6777dSBarry Smith .  J - Jacobian
8581e6777dSBarry Smith .  B - preconditioner, same as Jacobian
86ad960d00SLois Curfman McInnes .  flag - matrix flag
87ad960d00SLois Curfman McInnes 
88ad960d00SLois Curfman McInnes    Options Database Key:
89ad960d00SLois Curfman McInnes $  -snes_mf
9081e6777dSBarry Smith 
9171dce806SLois Curfman McInnes .keywords: SNES, finite differences, Jacobian
9281e6777dSBarry Smith 
9371dce806SLois Curfman McInnes .seealso: SNESSetJacobian(), SNESTestJacobian()
9481e6777dSBarry Smith @*/
9539e2f89bSBarry Smith int SNESDefaultMatrixFreeComputeJacobian(SNES snes, Vec x1,Mat *J,Mat *B,
96edd2f0e1SBarry Smith                                          MatStructure *flag,void *ctx)
9781e6777dSBarry Smith {
9839e2f89bSBarry Smith   int         n,ierr;
997f223b93SBarry Smith   MatType     type;
1007f223b93SBarry Smith 
10139e2f89bSBarry Smith   VecGetSize(x1,&n);
1027f223b93SBarry Smith   if (*J) MatGetType(*J,&type);
1037f223b93SBarry Smith   if (!*J || type != MATSHELL) {
1047f223b93SBarry Smith     MPI_Comm    comm;
10539e2f89bSBarry Smith     MFCtx_Private *mfctx;
10639e2f89bSBarry Smith     /* first time in, therefore build datastructures */
10778b31e54SBarry Smith     mfctx = (MFCtx_Private *) PETSCMALLOC(sizeof(MFCtx_Private)); CHKPTRQ(mfctx);
10839e2f89bSBarry Smith     mfctx->snes = snes;
10978b31e54SBarry Smith     ierr = VecDuplicate(x1,&mfctx->w); CHKERRQ(ierr);
1107f223b93SBarry Smith     PetscObjectGetComm((PetscObject)x1,&comm);
11178b31e54SBarry Smith     ierr = MatShellCreate(comm,n,n,(void*)mfctx,J); CHKERRQ(ierr);
11239e2f89bSBarry Smith     MatShellSetMult(*J,SNESMatrixFreeMult_Private);
11339e2f89bSBarry Smith     *B = *J;
11481e6777dSBarry Smith   }
11581e6777dSBarry Smith   return 0;
11681e6777dSBarry Smith }
11781e6777dSBarry Smith 
118