1bbf0e169SBarry Smith 2bbf0e169SBarry Smith #ifndef lint 3*5615d1e5SSatish Balay static char vcid[] = "$Id: fdmatrix.c,v 1.6 1997/01/01 03:37:22 bsmith Exp balay $"; 4bbf0e169SBarry Smith #endif 5bbf0e169SBarry Smith 6bbf0e169SBarry Smith /* 7639f9d9dSBarry Smith This is where the abstract matrix operations are defined that are 8639f9d9dSBarry Smith used for finite difference computations of Jacobians using coloring. 9bbf0e169SBarry Smith */ 10bbf0e169SBarry Smith 11bbf0e169SBarry Smith #include "petsc.h" 12bbf0e169SBarry Smith #include "src/mat/matimpl.h" /*I "mat.h" I*/ 13bbf0e169SBarry Smith #include "src/vec/vecimpl.h" 14bbf0e169SBarry Smith #include "pinclude/pviewer.h" 15bbf0e169SBarry Smith 16*5615d1e5SSatish Balay #undef __FUNC__ 17*5615d1e5SSatish Balay #define __FUNC__ "MatFDColoringView" 18bbf0e169SBarry Smith /*@C 19639f9d9dSBarry Smith MatFDColoringView - Views a finite difference coloring context. 20bbf0e169SBarry Smith 21639f9d9dSBarry Smith Input Parameter: 22639f9d9dSBarry Smith . color - the coloring context 23bbf0e169SBarry Smith 24bbf0e169SBarry Smith 25639f9d9dSBarry Smith .seealso: MatFDColoringCreate() 26bbf0e169SBarry Smith @*/ 27639f9d9dSBarry Smith int MatFDColoringView(MatFDColoring color,Viewer viewer) 28bbf0e169SBarry Smith { 29639f9d9dSBarry Smith int i,j,format,ierr; 30bbf0e169SBarry Smith 31639f9d9dSBarry Smith if (!viewer) viewer = VIEWER_STDOUT_WORLD; 32bbf0e169SBarry Smith 33bbf0e169SBarry Smith ierr = ViewerGetFormat(viewer,&format); CHKERRQ(ierr); 34639f9d9dSBarry Smith 35639f9d9dSBarry Smith if (format == VIEWER_FORMAT_ASCII_INFO) { 36639f9d9dSBarry Smith printf("MatFDColoring Object:\n"); 37639f9d9dSBarry Smith printf(" Error tolerance %g\n",color->error_rel); 38639f9d9dSBarry Smith printf(" umin %g\n",color->umin); 39639f9d9dSBarry Smith } else { 40639f9d9dSBarry Smith printf("MatFDColoring Object:\n"); 41639f9d9dSBarry Smith printf(" Error tolerance %g\n",color->error_rel); 42639f9d9dSBarry Smith printf(" umin %g\n",color->umin); 43639f9d9dSBarry Smith printf("Number of colors %d\n",color->ncolors); 44639f9d9dSBarry Smith for ( i=0; i<color->ncolors; i++ ) { 45639f9d9dSBarry Smith printf("Information for color %d\n",i); 46639f9d9dSBarry Smith printf("Number of columns %d\n",color->ncolumns[i]); 47639f9d9dSBarry Smith for ( j=0; j<color->ncolumns[i]; j++ ) { 48639f9d9dSBarry Smith printf(" %d\n",color->columns[i][j]); 49639f9d9dSBarry Smith } 50639f9d9dSBarry Smith printf("Number of rows %d\n",color->nrows[i]); 51639f9d9dSBarry Smith for ( j=0; j<color->nrows[i]; j++ ) { 52639f9d9dSBarry Smith printf(" %d %d \n",color->rows[i][j],color->columnsforrow[i][j]); 53bbf0e169SBarry Smith } 54bbf0e169SBarry Smith } 55bbf0e169SBarry Smith } 56639f9d9dSBarry Smith return 0; 57639f9d9dSBarry Smith } 58639f9d9dSBarry Smith 59*5615d1e5SSatish Balay #undef __FUNC__ 60*5615d1e5SSatish Balay #define __FUNC__ "MatFDColoringSetParameters" 61639f9d9dSBarry Smith /*@ 62639f9d9dSBarry Smith MatFDColoringSetParameters - Sets the parameters for the approximation of 63639f9d9dSBarry Smith Jacobian using finite differences. 64639f9d9dSBarry Smith 65639f9d9dSBarry Smith $ J(u)_{:,i} = [J(u+h*dx_{i}) - J(u)]/h where 66639f9d9dSBarry Smith $ h = error_rel*u[i] if u[i] > umin 67639f9d9dSBarry Smith $ = error_rel*umin else 68639f9d9dSBarry Smith $ 69639f9d9dSBarry Smith $ dx_{i} = (0, ... 1, .... 0) 70639f9d9dSBarry Smith 71639f9d9dSBarry Smith Input Parameters: 72639f9d9dSBarry Smith . coloring - the jacobian coloring context 73639f9d9dSBarry Smith . error_rel - relative error 74639f9d9dSBarry Smith . umin - minimum allowable u-value 75639f9d9dSBarry Smith 76639f9d9dSBarry Smith .keywords: SNES, Jacobian, finite differences, parameters 77639f9d9dSBarry Smith @*/ 78639f9d9dSBarry Smith int MatFDColoringSetParameters(MatFDColoring matfd,double error,double umin) 79639f9d9dSBarry Smith { 80639f9d9dSBarry Smith PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE); 81639f9d9dSBarry Smith 82639f9d9dSBarry Smith if (error != PETSC_DEFAULT) matfd->error_rel = error; 83639f9d9dSBarry Smith if (umin != PETSC_DEFAULT) matfd->umin = umin; 84639f9d9dSBarry Smith return 0; 85639f9d9dSBarry Smith } 86639f9d9dSBarry Smith 87*5615d1e5SSatish Balay #undef __FUNC__ 88*5615d1e5SSatish Balay #define __FUNC__ "MatFDColoringSetFromOptions" 89639f9d9dSBarry Smith /*@ 90639f9d9dSBarry Smith MatFDColoringSetFromOptions - Set coloring finite difference parameters from 91639f9d9dSBarry Smith the options database. 92639f9d9dSBarry Smith 93639f9d9dSBarry Smith $ J(u)_{:,i} = [J(u+h*dx_{i}) - J(u)]/h where 94639f9d9dSBarry Smith $ h = error_rel*u[i] if u[i] > umin 95639f9d9dSBarry Smith $ = error_rel*.1 else 96639f9d9dSBarry Smith $ 97639f9d9dSBarry Smith $ dx_{i} = (0, ... 1, .... 0) 98639f9d9dSBarry Smith 99639f9d9dSBarry Smith Input Parameters: 100639f9d9dSBarry Smith . coloring - the jacobian coloring context 101639f9d9dSBarry Smith 102639f9d9dSBarry Smith Options Database: 103639f9d9dSBarry Smith . -mat_fd_coloring_error square root of relative error in function 104639f9d9dSBarry Smith . -mat_fd_coloring_umin see above 105639f9d9dSBarry Smith 106639f9d9dSBarry Smith .keywords: SNES, Jacobian, finite differences, parameters 107639f9d9dSBarry Smith @*/ 108639f9d9dSBarry Smith int MatFDColoringSetFromOptions(MatFDColoring matfd) 109639f9d9dSBarry Smith { 110639f9d9dSBarry Smith int ierr,flag; 111639f9d9dSBarry Smith double error = PETSC_DEFAULT,umin = PETSC_DEFAULT; 112639f9d9dSBarry Smith PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE); 113639f9d9dSBarry Smith 114639f9d9dSBarry Smith ierr = OptionsGetDouble(matfd->prefix,"-mat_fd_coloring_err",&error,&flag);CHKERRQ(ierr); 115639f9d9dSBarry Smith ierr = OptionsGetDouble(matfd->prefix,"-mat_fd_coloring_umin",&umin,&flag);CHKERRQ(ierr); 116639f9d9dSBarry Smith ierr = OptionsHasName(PETSC_NULL,"-help",&flag); CHKERRQ(ierr); 117639f9d9dSBarry Smith ierr = MatFDColoringSetParameters(matfd,error,umin); CHKERRQ(ierr); 118639f9d9dSBarry Smith if (flag) { 119639f9d9dSBarry Smith ierr = MatFDColoringPrintHelp(matfd); CHKERRQ(ierr); 120639f9d9dSBarry Smith } 121639f9d9dSBarry Smith return 0; 122639f9d9dSBarry Smith } 123639f9d9dSBarry Smith 124*5615d1e5SSatish Balay #undef __FUNC__ 125*5615d1e5SSatish Balay #define __FUNC__ "MatFDColoringPrintHelp" 126639f9d9dSBarry Smith /*@ 127639f9d9dSBarry Smith MatFDColoringPrintHelp - Prints help message for matrix finite difference calculations 128639f9d9dSBarry Smith using coloring. 129639f9d9dSBarry Smith 130639f9d9dSBarry Smith Input Parameter: 131639f9d9dSBarry Smith . fdcoloring - the MatFDColoring context 132639f9d9dSBarry Smith 133639f9d9dSBarry Smith .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringSetFromOptions() 134639f9d9dSBarry Smith @*/ 135639f9d9dSBarry Smith int MatFDColoringPrintHelp(MatFDColoring fd) 136639f9d9dSBarry Smith { 137639f9d9dSBarry Smith PetscValidHeaderSpecific(fd,MAT_FDCOLORING_COOKIE); 138639f9d9dSBarry Smith 139639f9d9dSBarry Smith PetscPrintf(fd->comm,"-mat_fd_coloring_err <err> set sqrt rel tol in function. Default 1.e-8\n"); 140639f9d9dSBarry Smith PetscPrintf(fd->comm,"-mat_fd_coloring_umin <umin> see users manual. Default 1.e-8\n"); 141bbf0e169SBarry Smith return 0; 142bbf0e169SBarry Smith } 143bbf0e169SBarry Smith 144*5615d1e5SSatish Balay #undef __FUNC__ 145*5615d1e5SSatish Balay #define __FUNC__ "MatFDColoringCreate" 146bbf0e169SBarry Smith /*@C 147639f9d9dSBarry Smith MatFDColoringCreate - Creates a matrix coloring context for finite difference 148639f9d9dSBarry Smith computation of Jacobians. 149bbf0e169SBarry Smith 150639f9d9dSBarry Smith Input Parameters: 151639f9d9dSBarry Smith . mat - the matrix containing the nonzero structure of the Jacobian 152639f9d9dSBarry Smith . iscoloring - the coloring of the matrix 153bbf0e169SBarry Smith 154bbf0e169SBarry Smith Output Parameter: 155639f9d9dSBarry Smith . color - the new coloring context 156bbf0e169SBarry Smith 157639f9d9dSBarry Smith 158639f9d9dSBarry Smith .seealso: MatFDColoringDestroy() 159bbf0e169SBarry Smith @*/ 160639f9d9dSBarry Smith int MatFDColoringCreate(Mat mat,ISColoring iscoloring,MatFDColoring *color) 161bbf0e169SBarry Smith { 162639f9d9dSBarry Smith MatFDColoring c; 163639f9d9dSBarry Smith MPI_Comm comm; 164639f9d9dSBarry Smith int ierr,M,N; 165639f9d9dSBarry Smith 166639f9d9dSBarry Smith ierr = MatGetSize(mat,&M,&N); CHKERRQ(ierr); 167e3372554SBarry Smith if (M != N) SETERRQ(PETSC_ERR_SUP,0,"Only for square matrices"); 168639f9d9dSBarry Smith 169639f9d9dSBarry Smith PetscObjectGetComm((PetscObject)mat,&comm); 170639f9d9dSBarry Smith PetscHeaderCreate(c,_MatFDColoring,MAT_FDCOLORING_COOKIE,0,comm); 171639f9d9dSBarry Smith PLogObjectCreate(c); 172639f9d9dSBarry Smith 173639f9d9dSBarry Smith if (mat->ops.fdcoloringcreate) { 174639f9d9dSBarry Smith ierr = (*mat->ops.fdcoloringcreate)(mat,iscoloring,c); CHKERRQ(ierr); 175639f9d9dSBarry Smith } else { 176e3372554SBarry Smith SETERRQ(PETSC_ERR_SUP,0,"Code not yet written for this matrix type"); 177639f9d9dSBarry Smith } 178639f9d9dSBarry Smith 179639f9d9dSBarry Smith c->error_rel = 1.e-8; 180639f9d9dSBarry Smith c->umin = 1.e-5; 181639f9d9dSBarry Smith 182639f9d9dSBarry Smith *color = c; 183639f9d9dSBarry Smith 184bbf0e169SBarry Smith return 0; 185bbf0e169SBarry Smith } 186bbf0e169SBarry Smith 187*5615d1e5SSatish Balay #undef __FUNC__ 188*5615d1e5SSatish Balay #define __FUNC__ "MatFDColoringDestroy" 189bbf0e169SBarry Smith /*@C 190639f9d9dSBarry Smith MatFDColoringDestroy - Destroys a matrix coloring context that was created 191639f9d9dSBarry Smith via MatFDColoringCreate(). 192bbf0e169SBarry Smith 193639f9d9dSBarry Smith Input Paramter: 194639f9d9dSBarry Smith . c - coloring context 195bbf0e169SBarry Smith 196639f9d9dSBarry Smith .seealso: MatFDColoringCreate() 197bbf0e169SBarry Smith @*/ 198639f9d9dSBarry Smith int MatFDColoringDestroy(MatFDColoring c) 199bbf0e169SBarry Smith { 200639f9d9dSBarry Smith int i,ierr,flag; 201bbf0e169SBarry Smith 202639f9d9dSBarry Smith ierr = OptionsHasName(PETSC_NULL,"-matfdcoloring_view",&flag); 203639f9d9dSBarry Smith if (flag) { 204bbf0e169SBarry Smith Viewer viewer; 205639f9d9dSBarry Smith ierr = ViewerFileOpenASCII(c->comm,"stdout",&viewer);CHKERRQ(ierr); 206639f9d9dSBarry Smith ierr = MatFDColoringView(c,viewer);CHKERRQ(ierr); 207bbf0e169SBarry Smith ierr = ViewerDestroy(viewer); CHKERRQ(ierr); 208bbf0e169SBarry Smith } 209639f9d9dSBarry Smith ierr = OptionsHasName(PETSC_NULL,"-matfdcoloring_view_info",&flag); 210639f9d9dSBarry Smith if (flag) { 211bbf0e169SBarry Smith Viewer viewer; 212639f9d9dSBarry Smith ierr = ViewerFileOpenASCII(c->comm,"stdout",&viewer);CHKERRQ(ierr); 213639f9d9dSBarry Smith ierr = ViewerPushFormat(viewer,VIEWER_FORMAT_ASCII_INFO, PETSC_NULL); CHKERRQ(ierr); 214639f9d9dSBarry Smith ierr = MatFDColoringView(c,viewer);CHKERRQ(ierr); 215639f9d9dSBarry Smith ierr = ViewerPopFormat(viewer); 216bbf0e169SBarry Smith ierr = ViewerDestroy(viewer); CHKERRQ(ierr); 217bbf0e169SBarry Smith } 218639f9d9dSBarry Smith 219639f9d9dSBarry Smith for ( i=0; i<c->ncolors; i++ ) { 220639f9d9dSBarry Smith if (c->columns[i]) PetscFree(c->columns[i]); 221639f9d9dSBarry Smith if (c->rows[i]) PetscFree(c->rows[i]); 222639f9d9dSBarry Smith if (c->columnsforrow[i]) PetscFree(c->columnsforrow[i]); 223bbf0e169SBarry Smith } 224639f9d9dSBarry Smith PetscFree(c->ncolumns); 225639f9d9dSBarry Smith PetscFree(c->columns); 226639f9d9dSBarry Smith PetscFree(c->nrows); 227639f9d9dSBarry Smith PetscFree(c->rows); 228639f9d9dSBarry Smith PetscFree(c->columnsforrow); 229639f9d9dSBarry Smith PetscFree(c->scale); 230639f9d9dSBarry Smith PLogObjectDestroy(c); 231639f9d9dSBarry Smith PetscHeaderDestroy(c); 232bbf0e169SBarry Smith return 0; 233bbf0e169SBarry Smith } 23443a90d84SBarry Smith 235*5615d1e5SSatish Balay #undef __FUNC__ 236*5615d1e5SSatish Balay #define __FUNC__ "MatFDColoringApply" 23743a90d84SBarry Smith /*@ 23843a90d84SBarry Smith MatFDColoringApply - Given a matrix for which a MatFDColoring has been created, 23943a90d84SBarry Smith computes the Jacobian for a function via finite differences. 24043a90d84SBarry Smith 24143a90d84SBarry Smith Input Parameters: 24243a90d84SBarry Smith . mat - location to store Jacobian 24343a90d84SBarry Smith . coloring - coloring context created with MatFDColoringCreate() 24443a90d84SBarry Smith . x1 - location at which Jacobian is to be computed 24543a90d84SBarry Smith . w1,w2,w3 - three work vectors 24643a90d84SBarry Smith . f - function for which Jacobian is required 24743a90d84SBarry Smith . fctx - optional context required by function 24843a90d84SBarry Smith 24943a90d84SBarry Smith .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringView() 25043a90d84SBarry Smith 25143a90d84SBarry Smith .keywords: coloring, Jacobian, finite differences 25243a90d84SBarry Smith @*/ 25343a90d84SBarry Smith int MatFDColoringApply(Mat J,MatFDColoring coloring,Vec x1,Vec w1,Vec w2,Vec w3, 25443a90d84SBarry Smith int (*f)(void *,Vec,Vec,void*),void *sctx,void *fctx) 25543a90d84SBarry Smith { 25643a90d84SBarry Smith int k, ierr,N,start,end,l,row,col,srow; 25743a90d84SBarry Smith Scalar dx, mone = -1.0,*y,*scale = coloring->scale,*xx,*wscale = coloring->wscale; 25843a90d84SBarry Smith double epsilon = coloring->error_rel, umin = coloring->umin; 25943a90d84SBarry Smith MPI_Comm comm = coloring->comm; 26043a90d84SBarry Smith 26143a90d84SBarry Smith ierr = MatZeroEntries(J); CHKERRQ(ierr); 26243a90d84SBarry Smith 26343a90d84SBarry Smith ierr = VecGetOwnershipRange(x1,&start,&end); CHKERRQ(ierr); 26443a90d84SBarry Smith ierr = VecGetSize(x1,&N); CHKERRQ(ierr); 26543a90d84SBarry Smith ierr = VecGetArray(x1,&xx); CHKERRQ(ierr); 26643a90d84SBarry Smith ierr = (*f)(sctx,x1,w1,fctx); CHKERRQ(ierr); 26743a90d84SBarry Smith 26843a90d84SBarry Smith PetscMemzero(wscale,N*sizeof(Scalar)); 26943a90d84SBarry Smith /* 27043a90d84SBarry Smith Loop over each color 27143a90d84SBarry Smith */ 27243a90d84SBarry Smith 27343a90d84SBarry Smith for (k=0; k<coloring->ncolors; k++) { 27443a90d84SBarry Smith ierr = VecCopy(x1,w3); CHKERRQ(ierr); 27543a90d84SBarry Smith /* 27643a90d84SBarry Smith Loop over each column associated with color adding the 27743a90d84SBarry Smith perturbation to the vector w3. 27843a90d84SBarry Smith */ 27943a90d84SBarry Smith for (l=0; l<coloring->ncolumns[k]; l++) { 28043a90d84SBarry Smith col = coloring->columns[k][l]; /* column of the matrix we are probing for */ 28143a90d84SBarry Smith dx = xx[col-start]; 28243a90d84SBarry Smith #if !defined(PETSC_COMPLEX) 28343a90d84SBarry Smith if (dx < umin && dx >= 0.0) dx = .1; 28443a90d84SBarry Smith else if (dx < 0.0 && dx > -umin) dx = -.1; 28543a90d84SBarry Smith #else 28643a90d84SBarry Smith if (abs(dx) < umin && real(dx) >= 0.0) dx = .1; 28743a90d84SBarry Smith else if (real(dx) < 0.0 && abs(dx) < umin) dx = -.1; 28843a90d84SBarry Smith #endif 28943a90d84SBarry Smith dx *= epsilon; 29043a90d84SBarry Smith wscale[col] = 1.0/dx; 29143a90d84SBarry Smith VecSetValues(w3,1,&col,&dx,ADD_VALUES); 29243a90d84SBarry Smith } 29343a90d84SBarry Smith VecRestoreArray(x1,&xx); 29443a90d84SBarry Smith /* 29543a90d84SBarry Smith Evaluate function at x1 + dx (here dx is a vector, of perturbations) 29643a90d84SBarry Smith */ 29743a90d84SBarry Smith ierr = (*f)(sctx,w3,w2,fctx); CHKERRQ(ierr); 29843a90d84SBarry Smith ierr = VecAXPY(&mone,w1,w2); CHKERRQ(ierr); 29943a90d84SBarry Smith /* Communicate scale to all processors */ 30043a90d84SBarry Smith #if !defined(PETSC_COMPLEX) 30143a90d84SBarry Smith MPI_Allreduce(wscale,scale,N,MPI_DOUBLE,MPI_SUM,comm); 30243a90d84SBarry Smith #else 30343a90d84SBarry Smith MPI_Allreduce(wscale,scale,2*N,MPI_DOUBLE,MPI_SUM,comm); 30443a90d84SBarry Smith #endif 30543a90d84SBarry Smith /* 30643a90d84SBarry Smith Loop over rows of vector putting results into Jacobian matrix 30743a90d84SBarry Smith */ 30843a90d84SBarry Smith VecGetArray(w2,&y); 30943a90d84SBarry Smith for (l=0; l<coloring->nrows[k]; l++) { 31043a90d84SBarry Smith row = coloring->rows[k][l]; 31143a90d84SBarry Smith col = coloring->columnsforrow[k][l]; 31243a90d84SBarry Smith y[row] *= scale[col]; 31343a90d84SBarry Smith srow = row + start; 31443a90d84SBarry Smith ierr = MatSetValues(J,1,&srow,1,&col,y+row,INSERT_VALUES);CHKERRQ(ierr); 31543a90d84SBarry Smith } 31643a90d84SBarry Smith VecRestoreArray(w2,&y); 31743a90d84SBarry Smith } 31843a90d84SBarry Smith ierr = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); 31943a90d84SBarry Smith ierr = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); 32043a90d84SBarry Smith return 0; 32143a90d84SBarry Smith } 322