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