xref: /petsc/src/mat/matfd/fdmatrix.c (revision a5eb49655b3fdf389f9d65fc4214d6e1c240a941)
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