1*a5eb4965SSatish Balay #ifdef PETSC_RCS_HEADER 2*a5eb4965SSatish Balay static char vcid[] = "$Id: fdmatrix.c,v 1.10 1997/05/23 18:38:43 balay Exp balay $"; 3bbf0e169SBarry Smith #endif 4bbf0e169SBarry Smith 5bbf0e169SBarry Smith /* 6639f9d9dSBarry Smith This is where the abstract matrix operations are defined that are 7639f9d9dSBarry Smith used for finite difference computations of Jacobians using coloring. 8bbf0e169SBarry Smith */ 9bbf0e169SBarry Smith 10bbf0e169SBarry Smith #include "petsc.h" 11bbf0e169SBarry Smith #include "src/mat/matimpl.h" /*I "mat.h" I*/ 12bbf0e169SBarry Smith #include "src/vec/vecimpl.h" 13bbf0e169SBarry Smith #include "pinclude/pviewer.h" 14bbf0e169SBarry Smith 155615d1e5SSatish Balay #undef __FUNC__ 165eea60f9SBarry Smith #define __FUNC__ "MatFDColoringView" /* ADIC Ignore */ 17bbf0e169SBarry Smith /*@C 18639f9d9dSBarry Smith MatFDColoringView - Views a finite difference coloring context. 19bbf0e169SBarry Smith 20639f9d9dSBarry Smith Input Parameter: 21639f9d9dSBarry Smith . color - the coloring context 22bbf0e169SBarry Smith 23bbf0e169SBarry Smith 24639f9d9dSBarry Smith .seealso: MatFDColoringCreate() 25bbf0e169SBarry Smith @*/ 26639f9d9dSBarry Smith int MatFDColoringView(MatFDColoring color,Viewer viewer) 27bbf0e169SBarry Smith { 28639f9d9dSBarry Smith int i,j,format,ierr; 29bbf0e169SBarry Smith 30639f9d9dSBarry Smith if (!viewer) viewer = VIEWER_STDOUT_WORLD; 31bbf0e169SBarry Smith 32bbf0e169SBarry Smith ierr = ViewerGetFormat(viewer,&format); CHKERRQ(ierr); 33639f9d9dSBarry Smith 34639f9d9dSBarry Smith if (format == VIEWER_FORMAT_ASCII_INFO) { 35639f9d9dSBarry Smith printf("MatFDColoring Object:\n"); 36639f9d9dSBarry Smith printf(" Error tolerance %g\n",color->error_rel); 37639f9d9dSBarry Smith printf(" umin %g\n",color->umin); 38639f9d9dSBarry Smith } else { 39639f9d9dSBarry Smith printf("MatFDColoring Object:\n"); 40639f9d9dSBarry Smith printf(" Error tolerance %g\n",color->error_rel); 41639f9d9dSBarry Smith printf(" umin %g\n",color->umin); 42639f9d9dSBarry Smith printf("Number of colors %d\n",color->ncolors); 43639f9d9dSBarry Smith for ( i=0; i<color->ncolors; i++ ) { 44639f9d9dSBarry Smith printf("Information for color %d\n",i); 45639f9d9dSBarry Smith printf("Number of columns %d\n",color->ncolumns[i]); 46639f9d9dSBarry Smith for ( j=0; j<color->ncolumns[i]; j++ ) { 47639f9d9dSBarry Smith printf(" %d\n",color->columns[i][j]); 48639f9d9dSBarry Smith } 49639f9d9dSBarry Smith printf("Number of rows %d\n",color->nrows[i]); 50639f9d9dSBarry Smith for ( j=0; j<color->nrows[i]; j++ ) { 51639f9d9dSBarry Smith printf(" %d %d \n",color->rows[i][j],color->columnsforrow[i][j]); 52bbf0e169SBarry Smith } 53bbf0e169SBarry Smith } 54bbf0e169SBarry Smith } 55639f9d9dSBarry Smith return 0; 56639f9d9dSBarry Smith } 57639f9d9dSBarry Smith 585615d1e5SSatish Balay #undef __FUNC__ 595615d1e5SSatish Balay #define __FUNC__ "MatFDColoringSetParameters" 60639f9d9dSBarry Smith /*@ 61639f9d9dSBarry Smith MatFDColoringSetParameters - Sets the parameters for the approximation of 62639f9d9dSBarry Smith Jacobian using finite differences. 63639f9d9dSBarry Smith 64639f9d9dSBarry Smith $ J(u)_{:,i} = [J(u+h*dx_{i}) - J(u)]/h where 65639f9d9dSBarry Smith $ h = error_rel*u[i] if u[i] > umin 66639f9d9dSBarry Smith $ = error_rel*umin else 67639f9d9dSBarry Smith $ 68639f9d9dSBarry Smith $ dx_{i} = (0, ... 1, .... 0) 69639f9d9dSBarry Smith 70639f9d9dSBarry Smith Input Parameters: 71639f9d9dSBarry Smith . coloring - the jacobian coloring context 72639f9d9dSBarry Smith . error_rel - relative error 73639f9d9dSBarry Smith . umin - minimum allowable u-value 74639f9d9dSBarry Smith 75639f9d9dSBarry Smith .keywords: SNES, Jacobian, finite differences, parameters 76639f9d9dSBarry Smith @*/ 77639f9d9dSBarry Smith int MatFDColoringSetParameters(MatFDColoring matfd,double error,double umin) 78639f9d9dSBarry Smith { 79639f9d9dSBarry Smith PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE); 80639f9d9dSBarry Smith 81639f9d9dSBarry Smith if (error != PETSC_DEFAULT) matfd->error_rel = error; 82639f9d9dSBarry Smith if (umin != PETSC_DEFAULT) matfd->umin = umin; 83639f9d9dSBarry Smith return 0; 84639f9d9dSBarry Smith } 85639f9d9dSBarry Smith 865615d1e5SSatish Balay #undef __FUNC__ 875eea60f9SBarry Smith #define __FUNC__ "MatFDColoringSetFromOptions" /* ADIC Ignore */ 88639f9d9dSBarry Smith /*@ 89639f9d9dSBarry Smith MatFDColoringSetFromOptions - Set coloring finite difference parameters from 90639f9d9dSBarry Smith the options database. 91639f9d9dSBarry Smith 92639f9d9dSBarry Smith $ J(u)_{:,i} = [J(u+h*dx_{i}) - J(u)]/h where 93639f9d9dSBarry Smith $ h = error_rel*u[i] if u[i] > umin 94639f9d9dSBarry Smith $ = error_rel*.1 else 95639f9d9dSBarry Smith $ 96639f9d9dSBarry Smith $ dx_{i} = (0, ... 1, .... 0) 97639f9d9dSBarry Smith 98639f9d9dSBarry Smith Input Parameters: 99639f9d9dSBarry Smith . coloring - the jacobian coloring context 100639f9d9dSBarry Smith 101639f9d9dSBarry Smith Options Database: 102639f9d9dSBarry Smith . -mat_fd_coloring_error square root of relative error in function 103639f9d9dSBarry Smith . -mat_fd_coloring_umin see above 104639f9d9dSBarry Smith 105639f9d9dSBarry Smith .keywords: SNES, Jacobian, finite differences, parameters 106639f9d9dSBarry Smith @*/ 107639f9d9dSBarry Smith int MatFDColoringSetFromOptions(MatFDColoring matfd) 108639f9d9dSBarry Smith { 109639f9d9dSBarry Smith int ierr,flag; 110639f9d9dSBarry Smith double error = PETSC_DEFAULT,umin = PETSC_DEFAULT; 111639f9d9dSBarry Smith PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE); 112639f9d9dSBarry Smith 113639f9d9dSBarry Smith ierr = OptionsGetDouble(matfd->prefix,"-mat_fd_coloring_err",&error,&flag);CHKERRQ(ierr); 114639f9d9dSBarry Smith ierr = OptionsGetDouble(matfd->prefix,"-mat_fd_coloring_umin",&umin,&flag);CHKERRQ(ierr); 115639f9d9dSBarry Smith ierr = OptionsHasName(PETSC_NULL,"-help",&flag); CHKERRQ(ierr); 116639f9d9dSBarry Smith ierr = MatFDColoringSetParameters(matfd,error,umin); CHKERRQ(ierr); 117639f9d9dSBarry Smith if (flag) { 118639f9d9dSBarry Smith ierr = MatFDColoringPrintHelp(matfd); CHKERRQ(ierr); 119639f9d9dSBarry Smith } 120639f9d9dSBarry Smith return 0; 121639f9d9dSBarry Smith } 122639f9d9dSBarry Smith 1235615d1e5SSatish Balay #undef __FUNC__ 1245eea60f9SBarry Smith #define __FUNC__ "MatFDColoringPrintHelp" /* ADIC Ignore */ 125639f9d9dSBarry Smith /*@ 126639f9d9dSBarry Smith MatFDColoringPrintHelp - Prints help message for matrix finite difference calculations 127639f9d9dSBarry Smith using coloring. 128639f9d9dSBarry Smith 129639f9d9dSBarry Smith Input Parameter: 130639f9d9dSBarry Smith . fdcoloring - the MatFDColoring context 131639f9d9dSBarry Smith 132639f9d9dSBarry Smith .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringSetFromOptions() 133639f9d9dSBarry Smith @*/ 134639f9d9dSBarry Smith int MatFDColoringPrintHelp(MatFDColoring fd) 135639f9d9dSBarry Smith { 136639f9d9dSBarry Smith PetscValidHeaderSpecific(fd,MAT_FDCOLORING_COOKIE); 137639f9d9dSBarry Smith 1380f665d81SLois Curfman McInnes PetscPrintf(fd->comm,"-mat_fd_coloring_err <err>: set sqrt rel tol in function, defaults to 1.e-8\n"); 1390f665d81SLois Curfman McInnes PetscPrintf(fd->comm,"-mat_fd_coloring_umin <umin>: see users manual, defaults to 1.e-8\n"); 140bbf0e169SBarry Smith return 0; 141bbf0e169SBarry Smith } 142bbf0e169SBarry Smith 1435615d1e5SSatish Balay #undef __FUNC__ 1445615d1e5SSatish Balay #define __FUNC__ "MatFDColoringCreate" 145bbf0e169SBarry Smith /*@C 146639f9d9dSBarry Smith MatFDColoringCreate - Creates a matrix coloring context for finite difference 147639f9d9dSBarry Smith computation of Jacobians. 148bbf0e169SBarry Smith 149639f9d9dSBarry Smith Input Parameters: 150639f9d9dSBarry Smith . mat - the matrix containing the nonzero structure of the Jacobian 151639f9d9dSBarry Smith . iscoloring - the coloring of the matrix 152bbf0e169SBarry Smith 153bbf0e169SBarry Smith Output Parameter: 154639f9d9dSBarry Smith . color - the new coloring context 155bbf0e169SBarry Smith 156639f9d9dSBarry Smith 157639f9d9dSBarry Smith .seealso: MatFDColoringDestroy() 158bbf0e169SBarry Smith @*/ 159639f9d9dSBarry Smith int MatFDColoringCreate(Mat mat,ISColoring iscoloring,MatFDColoring *color) 160bbf0e169SBarry Smith { 161639f9d9dSBarry Smith MatFDColoring c; 162639f9d9dSBarry Smith MPI_Comm comm; 163639f9d9dSBarry Smith int ierr,M,N; 164639f9d9dSBarry Smith 165639f9d9dSBarry Smith ierr = MatGetSize(mat,&M,&N); CHKERRQ(ierr); 166e3372554SBarry Smith if (M != N) SETERRQ(PETSC_ERR_SUP,0,"Only for square matrices"); 167639f9d9dSBarry Smith 168639f9d9dSBarry Smith PetscObjectGetComm((PetscObject)mat,&comm); 169f09e8eb9SSatish Balay PetscHeaderCreate(c,_p_MatFDColoring,MAT_FDCOLORING_COOKIE,0,comm); 170639f9d9dSBarry Smith PLogObjectCreate(c); 171639f9d9dSBarry Smith 172639f9d9dSBarry Smith if (mat->ops.fdcoloringcreate) { 173639f9d9dSBarry Smith ierr = (*mat->ops.fdcoloringcreate)(mat,iscoloring,c); CHKERRQ(ierr); 174639f9d9dSBarry Smith } else { 175e3372554SBarry Smith SETERRQ(PETSC_ERR_SUP,0,"Code not yet written for this matrix type"); 176639f9d9dSBarry Smith } 177639f9d9dSBarry Smith 178639f9d9dSBarry Smith c->error_rel = 1.e-8; 179639f9d9dSBarry Smith c->umin = 1.e-5; 180639f9d9dSBarry Smith 181639f9d9dSBarry Smith *color = c; 182639f9d9dSBarry Smith 183bbf0e169SBarry Smith return 0; 184bbf0e169SBarry Smith } 185bbf0e169SBarry Smith 1865615d1e5SSatish Balay #undef __FUNC__ 1875eea60f9SBarry Smith #define __FUNC__ "MatFDColoringDestroy" /* ADIC Ignore */ 188bbf0e169SBarry Smith /*@C 189639f9d9dSBarry Smith MatFDColoringDestroy - Destroys a matrix coloring context that was created 190639f9d9dSBarry Smith via MatFDColoringCreate(). 191bbf0e169SBarry Smith 192639f9d9dSBarry Smith Input Paramter: 193639f9d9dSBarry Smith . c - coloring context 194bbf0e169SBarry Smith 195639f9d9dSBarry Smith .seealso: MatFDColoringCreate() 196bbf0e169SBarry Smith @*/ 197639f9d9dSBarry Smith int MatFDColoringDestroy(MatFDColoring c) 198bbf0e169SBarry Smith { 199639f9d9dSBarry Smith int i,ierr,flag; 200bbf0e169SBarry Smith 201639f9d9dSBarry Smith ierr = OptionsHasName(PETSC_NULL,"-matfdcoloring_view",&flag); 202639f9d9dSBarry Smith if (flag) { 203bbf0e169SBarry Smith Viewer viewer; 204639f9d9dSBarry Smith ierr = ViewerFileOpenASCII(c->comm,"stdout",&viewer);CHKERRQ(ierr); 205639f9d9dSBarry Smith ierr = MatFDColoringView(c,viewer);CHKERRQ(ierr); 206bbf0e169SBarry Smith ierr = ViewerDestroy(viewer); CHKERRQ(ierr); 207bbf0e169SBarry Smith } 208639f9d9dSBarry Smith ierr = OptionsHasName(PETSC_NULL,"-matfdcoloring_view_info",&flag); 209639f9d9dSBarry Smith if (flag) { 210bbf0e169SBarry Smith Viewer viewer; 211639f9d9dSBarry Smith ierr = ViewerFileOpenASCII(c->comm,"stdout",&viewer);CHKERRQ(ierr); 212639f9d9dSBarry Smith ierr = ViewerPushFormat(viewer,VIEWER_FORMAT_ASCII_INFO, PETSC_NULL); CHKERRQ(ierr); 213639f9d9dSBarry Smith ierr = MatFDColoringView(c,viewer);CHKERRQ(ierr); 214639f9d9dSBarry Smith ierr = ViewerPopFormat(viewer); 215bbf0e169SBarry Smith ierr = ViewerDestroy(viewer); CHKERRQ(ierr); 216bbf0e169SBarry Smith } 217639f9d9dSBarry Smith 218639f9d9dSBarry Smith for ( i=0; i<c->ncolors; i++ ) { 219639f9d9dSBarry Smith if (c->columns[i]) PetscFree(c->columns[i]); 220639f9d9dSBarry Smith if (c->rows[i]) PetscFree(c->rows[i]); 221639f9d9dSBarry Smith if (c->columnsforrow[i]) PetscFree(c->columnsforrow[i]); 222bbf0e169SBarry Smith } 223639f9d9dSBarry Smith PetscFree(c->ncolumns); 224639f9d9dSBarry Smith PetscFree(c->columns); 225639f9d9dSBarry Smith PetscFree(c->nrows); 226639f9d9dSBarry Smith PetscFree(c->rows); 227639f9d9dSBarry Smith PetscFree(c->columnsforrow); 228639f9d9dSBarry Smith PetscFree(c->scale); 229639f9d9dSBarry Smith PLogObjectDestroy(c); 230639f9d9dSBarry Smith PetscHeaderDestroy(c); 231bbf0e169SBarry Smith return 0; 232bbf0e169SBarry Smith } 23343a90d84SBarry Smith 2345615d1e5SSatish Balay #undef __FUNC__ 2355615d1e5SSatish Balay #define __FUNC__ "MatFDColoringApply" 23643a90d84SBarry Smith /*@ 23743a90d84SBarry Smith MatFDColoringApply - Given a matrix for which a MatFDColoring has been created, 23843a90d84SBarry Smith computes the Jacobian for a function via finite differences. 23943a90d84SBarry Smith 24043a90d84SBarry Smith Input Parameters: 24143a90d84SBarry Smith . mat - location to store Jacobian 24243a90d84SBarry Smith . coloring - coloring context created with MatFDColoringCreate() 24343a90d84SBarry Smith . x1 - location at which Jacobian is to be computed 24443a90d84SBarry Smith . w1,w2,w3 - three work vectors 24543a90d84SBarry Smith . f - function for which Jacobian is required 24643a90d84SBarry Smith . fctx - optional context required by function 24743a90d84SBarry Smith 24843a90d84SBarry Smith .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringView() 24943a90d84SBarry Smith 25043a90d84SBarry Smith .keywords: coloring, Jacobian, finite differences 25143a90d84SBarry Smith @*/ 25243a90d84SBarry Smith int MatFDColoringApply(Mat J,MatFDColoring coloring,Vec x1,Vec w1,Vec w2,Vec w3, 25343a90d84SBarry Smith int (*f)(void *,Vec,Vec,void*),void *sctx,void *fctx) 25443a90d84SBarry Smith { 25543a90d84SBarry Smith int k, ierr,N,start,end,l,row,col,srow; 25643a90d84SBarry Smith Scalar dx, mone = -1.0,*y,*scale = coloring->scale,*xx,*wscale = coloring->wscale; 25743a90d84SBarry Smith double epsilon = coloring->error_rel, umin = coloring->umin; 25843a90d84SBarry Smith MPI_Comm comm = coloring->comm; 25943a90d84SBarry Smith 26043a90d84SBarry Smith ierr = MatZeroEntries(J); CHKERRQ(ierr); 26143a90d84SBarry Smith 26243a90d84SBarry Smith ierr = VecGetOwnershipRange(x1,&start,&end); CHKERRQ(ierr); 26343a90d84SBarry Smith ierr = VecGetSize(x1,&N); CHKERRQ(ierr); 26443a90d84SBarry Smith ierr = VecGetArray(x1,&xx); CHKERRQ(ierr); 26543a90d84SBarry Smith ierr = (*f)(sctx,x1,w1,fctx); CHKERRQ(ierr); 26643a90d84SBarry Smith 26743a90d84SBarry Smith PetscMemzero(wscale,N*sizeof(Scalar)); 26843a90d84SBarry Smith /* 26943a90d84SBarry Smith Loop over each color 27043a90d84SBarry Smith */ 27143a90d84SBarry Smith 27243a90d84SBarry Smith for (k=0; k<coloring->ncolors; k++) { 27343a90d84SBarry Smith ierr = VecCopy(x1,w3); CHKERRQ(ierr); 27443a90d84SBarry Smith /* 27543a90d84SBarry Smith Loop over each column associated with color adding the 27643a90d84SBarry Smith perturbation to the vector w3. 27743a90d84SBarry Smith */ 27843a90d84SBarry Smith for (l=0; l<coloring->ncolumns[k]; l++) { 27943a90d84SBarry Smith col = coloring->columns[k][l]; /* column of the matrix we are probing for */ 28043a90d84SBarry Smith dx = xx[col-start]; 28143a90d84SBarry Smith #if !defined(PETSC_COMPLEX) 28243a90d84SBarry Smith if (dx < umin && dx >= 0.0) dx = .1; 28343a90d84SBarry Smith else if (dx < 0.0 && dx > -umin) dx = -.1; 28443a90d84SBarry Smith #else 28543a90d84SBarry Smith if (abs(dx) < umin && real(dx) >= 0.0) dx = .1; 28643a90d84SBarry Smith else if (real(dx) < 0.0 && abs(dx) < umin) dx = -.1; 28743a90d84SBarry Smith #endif 28843a90d84SBarry Smith dx *= epsilon; 28943a90d84SBarry Smith wscale[col] = 1.0/dx; 29043a90d84SBarry Smith VecSetValues(w3,1,&col,&dx,ADD_VALUES); 29143a90d84SBarry Smith } 29243a90d84SBarry Smith VecRestoreArray(x1,&xx); 29343a90d84SBarry Smith /* 29443a90d84SBarry Smith Evaluate function at x1 + dx (here dx is a vector, of perturbations) 29543a90d84SBarry Smith */ 29643a90d84SBarry Smith ierr = (*f)(sctx,w3,w2,fctx); CHKERRQ(ierr); 29743a90d84SBarry Smith ierr = VecAXPY(&mone,w1,w2); CHKERRQ(ierr); 29843a90d84SBarry Smith /* Communicate scale to all processors */ 29943a90d84SBarry Smith #if !defined(PETSC_COMPLEX) 30043a90d84SBarry Smith MPI_Allreduce(wscale,scale,N,MPI_DOUBLE,MPI_SUM,comm); 30143a90d84SBarry Smith #else 30243a90d84SBarry Smith MPI_Allreduce(wscale,scale,2*N,MPI_DOUBLE,MPI_SUM,comm); 30343a90d84SBarry Smith #endif 30443a90d84SBarry Smith /* 30543a90d84SBarry Smith Loop over rows of vector putting results into Jacobian matrix 30643a90d84SBarry Smith */ 30743a90d84SBarry Smith VecGetArray(w2,&y); 30843a90d84SBarry Smith for (l=0; l<coloring->nrows[k]; l++) { 30943a90d84SBarry Smith row = coloring->rows[k][l]; 31043a90d84SBarry Smith col = coloring->columnsforrow[k][l]; 31143a90d84SBarry Smith y[row] *= scale[col]; 31243a90d84SBarry Smith srow = row + start; 31343a90d84SBarry Smith ierr = MatSetValues(J,1,&srow,1,&col,y+row,INSERT_VALUES);CHKERRQ(ierr); 31443a90d84SBarry Smith } 31543a90d84SBarry Smith VecRestoreArray(w2,&y); 31643a90d84SBarry Smith } 31743a90d84SBarry Smith ierr = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); 31843a90d84SBarry Smith ierr = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); 31943a90d84SBarry Smith return 0; 32043a90d84SBarry Smith } 321