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