xref: /petsc/src/snes/interface/snesj2.c (revision 883893826fc4951fb9ae538d71784dda28966998)
191627157SBarry Smith 
291627157SBarry Smith #ifndef lint
3*88389382SBarry Smith static char vcid[] = "$Id: snesj2.c,v 1.2 1996/11/07 15:11:28 bsmith Exp bsmith $";
491627157SBarry Smith #endif
591627157SBarry Smith 
6639f9d9dSBarry Smith #include "src/mat/matimpl.h"      /*I  "mat.h"  I*/
7639f9d9dSBarry Smith #include "src/snes/snesimpl.h"    /*I  "snes.h"  I*/
891627157SBarry Smith 
991627157SBarry Smith 
1091627157SBarry Smith /*@C
1191627157SBarry Smith      SNESDefaultComputeJacobianWithColoring
1291627157SBarry Smith 
1391627157SBarry Smith    Input Parameters:
1491627157SBarry Smith .    snes - nonlinear solver object
1591627157SBarry Smith .    x1 - location at which to evaluate Jacobian
1691627157SBarry Smith .    ctx - MatFDColoring contex
1791627157SBarry Smith 
1891627157SBarry Smith    Output Parameters:
1991627157SBarry Smith .    J - Jacobian matrix
2091627157SBarry Smith .    B - Jacobian preconditioner
2191627157SBarry Smith .    flag - flag indicating if the matrix nonzero structure has changed
2291627157SBarry Smith 
2391627157SBarry Smith .keywords: SNES, finite differences, Jacobian
2491627157SBarry Smith 
2591627157SBarry Smith .seealso: SNESSetJacobian(), SNESTestJacobian()
2691627157SBarry Smith @*/
2791627157SBarry Smith int SNESDefaultComputeJacobianWithColoring(SNES snes,Vec x1,Mat *JJ,Mat *B,MatStructure *flag,void *ctx)
2891627157SBarry Smith {
2991627157SBarry Smith   MatFDColoring color = (MatFDColoring) ctx;
30*88389382SBarry Smith   Vec           w1,w2,w3;
31*88389382SBarry Smith 
32*88389382SBarry Smith   if (!snes->nvwork) {
33*88389382SBarry Smith     ierr = VecDuplicateVecs(x1,3,&snes->vwork); CHKERRQ(ierr);
34*88389382SBarry Smith     snes->nvwork = 3;
35*88389382SBarry Smith     PLogObjectParents(snes,3,snes->vwork);
36*88389382SBarry Smith   }
37*88389382SBarry Smith   w1 = snes->vwork[0]; w2 = snes->vwork[1]; w3 = snes->vwork[2];
38*88389382SBarry Smith   ierr = MatFDColoringApply(*B,color,x1,w1,w2,w3,f,snes,snes->funP); CHKERRQ(ierr);
39*88389382SBarry Smith 
40*88389382SBarry Smith 
41639f9d9dSBarry Smith   Mat           J = *B;
4291627157SBarry Smith   Vec           jj1,jj2,x2;
43639f9d9dSBarry Smith   int           k, ierr,N,start,end,l,row,col,srow;
4491627157SBarry Smith   Scalar        dx, mone = -1.0,*y,*scale = color->scale,*xx,*wscale = color->wscale;
45639f9d9dSBarry Smith   double        epsilon = color->error_rel, umin = color->umin;
4691627157SBarry Smith   MPI_Comm      comm = color->comm;
4791627157SBarry Smith 
4891627157SBarry Smith   ierr = MatZeroEntries(J); CHKERRQ(ierr);
49*88389382SBarry Smith 
50*88389382SBarry Smith 
5191627157SBarry Smith   jj1 = snes->vwork[0]; jj2 = snes->vwork[1]; x2 = snes->vwork[2];
5291627157SBarry Smith 
5391627157SBarry Smith   ierr = VecGetOwnershipRange(x1,&start,&end); CHKERRQ(ierr);
5491627157SBarry Smith   ierr = VecGetSize(x1,&N); CHKERRQ(ierr);
5591627157SBarry Smith   ierr = VecGetArray(x1,&xx); CHKERRQ(ierr);
5691627157SBarry Smith   ierr = SNESComputeFunction(snes,x1,jj1); CHKERRQ(ierr);
5791627157SBarry Smith 
5891627157SBarry Smith   PetscMemzero(wscale,N*sizeof(Scalar));
5991627157SBarry Smith   /*
6091627157SBarry Smith       Loop over each color
6191627157SBarry Smith   */
62639f9d9dSBarry Smith 
6391627157SBarry Smith   for (k=0; k<color->ncolors; k++) {
6491627157SBarry Smith     ierr = VecCopy(x1,x2); CHKERRQ(ierr);
6591627157SBarry Smith     /*
6691627157SBarry Smith        Loop over each column associated with color adding the
6791627157SBarry Smith        perturbation to the vector x2.
6891627157SBarry Smith     */
6991627157SBarry Smith     for (l=0; l<color->ncolumns[k]; l++) {
7091627157SBarry Smith       col = color->columns[k][l];    /* column of the matrix we are probing for */
7191627157SBarry Smith       dx  = xx[col-start];
7291627157SBarry Smith #if !defined(PETSC_COMPLEX)
73639f9d9dSBarry Smith       if (dx < umin && dx >= 0.0) dx = .1;
74639f9d9dSBarry Smith       else if (dx < 0.0 && dx > -umin) dx = -.1;
7591627157SBarry Smith #else
76639f9d9dSBarry Smith       if (abs(dx) < umin && real(dx) >= 0.0) dx = .1;
77639f9d9dSBarry Smith       else if (real(dx) < 0.0 && abs(dx) < umin) dx = -.1;
7891627157SBarry Smith #endif
7991627157SBarry Smith       dx          *= epsilon;
8091627157SBarry Smith       wscale[col] = 1.0/dx;
8191627157SBarry Smith       VecSetValues(x2,1,&col,&dx,ADD_VALUES);
8291627157SBarry Smith     }
8391627157SBarry Smith     VecRestoreArray(x1,&xx);
8491627157SBarry Smith     /*
8591627157SBarry Smith        Evaluate function at x1 + dx (here dx is a vector, of perturbations)
8691627157SBarry Smith     */
8791627157SBarry Smith     ierr = SNESComputeFunction(snes,x2,jj2); CHKERRQ(ierr);
8891627157SBarry Smith     ierr = VecAXPY(&mone,jj1,jj2); CHKERRQ(ierr);
8991627157SBarry Smith     /* Communicate scale to all processors */
9091627157SBarry Smith #if !defined(PETSC_COMPLEX)
9191627157SBarry Smith     MPI_Allreduce(wscale,scale,N,MPI_DOUBLE,MPI_SUM,comm);
9291627157SBarry Smith #else
9391627157SBarry Smith     MPI_Allreduce(wscale,scale,2*N,MPI_DOUBLE,MPI_SUM,comm);
9491627157SBarry Smith #endif
9591627157SBarry Smith     /*
9691627157SBarry Smith        Loop over rows of vector putting results into Jacobian matrix
9791627157SBarry Smith     */
9891627157SBarry Smith     VecGetArray(jj2,&y);
9991627157SBarry Smith     for (l=0; l<color->nrows[k]; l++) {
10091627157SBarry Smith       row    = color->rows[k][l];
10191627157SBarry Smith       col    = color->columnsforrow[k][l];
102639f9d9dSBarry Smith       y[row] *= scale[col];
103639f9d9dSBarry Smith       srow   = row + start;
104639f9d9dSBarry Smith       ierr   = MatSetValues(J,1,&srow,1,&col,y+row,INSERT_VALUES);CHKERRQ(ierr);
10591627157SBarry Smith     }
10691627157SBarry Smith     VecRestoreArray(jj2,&y);
10791627157SBarry Smith   }
10891627157SBarry Smith   ierr  = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
10991627157SBarry Smith   ierr  = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
11091627157SBarry Smith   *flag = SAME_NONZERO_PATTERN;
11191627157SBarry Smith   return 0;
11291627157SBarry Smith }
11391627157SBarry Smith 
11491627157SBarry Smith 
11591627157SBarry Smith 
116